历史上的今天
返回首页

历史上的今天

今天是:2025年03月04日(星期二)

正在发生

2020年03月04日 | STM8开发记录二:UART RX空闲中断和DMA操作

2020-03-04 来源:eefocus

一、用STM8L的时候,没能在同时读取Rx中断和IDLE中断标志,最后用DMA取数据,见 (三、DMA实现数据拷贝):


1.1 uart配置


void UsartConfig(void)

{

// USART_DeInit(USART1);

 

/* Enable USART clock */  

CLK_PeripheralClockConfig(CLK_Peripheral_USART1, ENABLE);

 

/* USART pin remap */

SYSCFG_REMAPPinConfig(REMAP_Pin_USART1TxRxPortA, ENABLE);

 

/* Configure USART Tx as alternate function push-pull  (software pull up)*/

GPIO_ExternalPullUpConfig(USART1_Tx_PORT, USART1_Tx_Pin, ENABLE);

 

/* Configure USART Rx as alternate function push-pull  (software pull up)*/

GPIO_ExternalPullUpConfig(USART1_Rx_PORT, USART1_Rx_Pin, ENABLE);

 

/* USART configuration */

USART_Init(USART1, BAUDRATE, USART_WordLength_8b, USART_StopBits_1,

        USART_Parity_No, USART_Mode_Rx_and_TX);

 

 

/* Enable the USART Receive interrupt: this interrupt is generated when the USART*/

USART_ITConfig(USART1 , USART_IT_RXNE, ENABLE);

USART_ITConfig(USART1 , USART_IT_IDLE , ENABLE); //空闲中断

 

 

//配置ITC 中断管理

ITC_SetSoftwarePriority(USART1_RX_IRQn, ITC_PriorityLevel_3);

 

//start UART

USART_Cmd(USART1 , ENABLE); //打开串口

 

//解决第一个数据发送失败的问题

USART_ClearFlag(USART3 , USART_FLAG_TC);

//    USART_ClearFlag(USART3 , USART_FLAG_IDLE);

}


1.2 中断处理, 不能判断IDLE中断:如发送 AA01数据后,不能进入IDLE中断。但是只开IDLE中断,发送完毕会进入IDLE中断。


/* Enable the USART Receive interrupt: this interrupt is generated when the USART*/

//USART_ITConfig(USART1 , USART_IT_RXNE, ENABLE);        

USART_ITConfig(USART1 , USART_IT_IDLE , ENABLE);        //空闲中断


INTERRUPT_HANDLER(USART1_RX_TIM5_CC_IRQHandler, 28)

{

/* In order to detect unexpected events during development,

it is recommended to set a breakpoint on the following instruction.

*/

static U8 BytesPos = 0;

static U8 MessagePos = 0;

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //RX interrupt

{

UartApiVar.RXBuffer[MessagePos][BytesPos] = USART_ReceiveData8(USART1);  

printflog("MessagePos = %d, BytesPos = %dnr", MessagePos, BytesPos);

printflog("data_0 = %dnr", UartApiVar.RXBuffer[MessagePos][BytesPos]);

BytesPos++;

}

else if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) //IDLE interrupt

{

USART1->SR;//先读SR

USART1->DR;//再读DR

printflog("MessagePos = %d, BytesPos = %dnr", MessagePos, BytesPos);

printflog("data_1 = %dnr", UartApiVar.RXBuffer[MessagePos][0]);

if((BytesPos < COMM_IF_UART_RX_BUFFER_LENGTH) && 

(UartApiVar.RXBuffer[MessagePos][0] == 0xAA))

{

if(MessagePos < COMM_IF_UART_RX_MSG_NUM)

{

MessagePos++;

}

else

{

MessagePos = 0;

}

}

BytesPos = 0;

}

}


二、用STM32的时候,可以同时判断Rx中断和IDLE中断:

2.1 uart配置:


void USART3Conf(u32 baudRate, u32 nvicPre, u32 nvicSub)

{

USART_InitTypeDef USART_InitStructure;

GPIO_InitTypeDef GPIO_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); //使能USART1

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //GPIOA时钟

//USART3_TX   GPIOB.10

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出

GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOA.10

 

//USART3_RX   GPIOB.11初始化

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PB11

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入

GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOA.10 

 

//  //Usart3 NVIC 配置

NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=nvicPre ;//抢占优先级3

NVIC_InitStructure.NVIC_IRQChannelSubPriority = nvicSub; //子优先级2

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能

NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器

 

//USART3 Configure

USART_InitStructure.USART_BaudRate = baudRate;

USART_InitStructure.USART_WordLength = USART_WordLength_8b;

USART_InitStructure.USART_StopBits = USART_StopBits_1;

USART_InitStructure.USART_Parity = USART_Parity_No;

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

//USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

USART_Init(USART3 , &USART_InitStructure);

//USART3_INT Configure

USART_ITConfig(USART3 , USART_IT_RXNE, ENABLE);

  USART_ITConfig(USART3 , USART_IT_IDLE , ENABLE); //空闲中断

USART_Cmd(USART3 , ENABLE);//打开串口

USART_ClearFlag(USART3 , USART_FLAG_TC);//解决第一个数据发送失败的问题

}


2.2中断处理:

void USART3_IRQHandler(void)

{

static u8 i = 0;

if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)

{

UsartBuf[i] = (u8)USART_ReceiveData(USART3);

i++;

/* deliver rx byte */

}

else if(USART_GetITStatus(USART3, USART_IT_IDLE) != RESET)

{

USART3->SR;//先读SR

USART3->DR;//再读DR

 

if(UsartBuf[i -1] == 0x0A)

{

UsartBuf[UART_DATA_LEN -2] = i;

UsartBuf[UART_DATA_LEN -1] = UART_DATA_END_CODE;

}

i = 0;

}

 

if(USART_GetITStatus(USART3, USART_IT_TXE) != RESET)

{   

}

}


三、鉴于STM8L没有能让RX和IDLE中断标志同时置位,故采用DMA实现数据拷贝。

3.1DMA配置:

/**********************************************************************/

//Description: DmaConfig()   

//Parameters:    //0x5231, 为UART数据寄存器地址:USART1_BASE = 0x5230                    

//Return:      

//Date:            quanwu.xu  

/**********************************************************************/

void DmaConfig(void)

{

CLK_PeripheralClockConfig(CLK_Peripheral_DMA1, ENABLE);//打开时钟,很重要

/* Deinitialize DMA channels */

DMA_GlobalDeInit(); 

DMA_DeInit(DMA1_Channel1);

DMA_DeInit(DMA1_Channel2);

/* DMA channel Rx of USART Configuration */    //该函数主要要配置好接受的数组,以及USART的数据寄存器地址,数组大小,以及DMA模式

DMA_Init(DMA1_Channel2, (uint16_t)UartApiVar.RxBuffer, UART_DR_ADDRESS,  

COMM_IF_UART_RX_BUFFER_LENGTH,  DMA_DIR_PeripheralToMemory, DMA_Mode_Normal, 

DMA_MemoryIncMode_Inc, DMA_Priority_High, DMA_MemoryDataSize_Byte); 

 

/* DMA channel Tx of USART Configuration */    //该函数主要配置发送数组,以及USART的数据寄存器地址,数组大小,以及DMA模式

DMA_Init(DMA1_Channel1, (uint16_t)UartApiVar.TxBuffer, UART_DR_ADDRESS, 

COMM_IF_UART_TX_BUFFER_LENGTH,  DMA_DIR_MemoryToPeripheral, DMA_Mode_Normal, 

DMA_MemoryIncMode_Inc, DMA_Priority_Low, DMA_MemoryDataSize_Byte);

 

/* Enable the USART Tx/Rx DMA requests */

USART_DMACmd(USART1, USART_DMAReq_TX, ENABLE);

USART_DMACmd(USART1, USART_DMAReq_RX, ENABLE); 

 

/* Global DMA Enable */

DMA_GlobalCmd(ENABLE); 

 

/* Enable the USART Tx DMA channel */

DMA_Cmd(DMA1_Channel1, ENABLE);

 

/* Enable the USART Rx DMA channel */

DMA_Cmd(DMA1_Channel2, ENABLE); 

}


3.2UART配置,只使能IDLE中断

/**********************************************************************/

//Description: UsartConfig()   

//Parameters:        

//Return:      

//Date:            quanwu.xu  

/**********************************************************************/

void UsartConfig(void)

{

USART_DeInit(USART1);

 

/* Enable USART clock */  

CLK_PeripheralClockConfig(CLK_Peripheral_USART1, ENABLE);

 

/* USART pin remap */

SYSCFG_REMAPPinConfig(REMAP_Pin_USART1TxRxPortA, ENABLE);

 

/* Configure USART Tx as alternate function push-pull  (software pull up)*/

GPIO_ExternalPullUpConfig(USART1_Tx_PORT, USART1_Tx_Pin, ENABLE);

 

/* Configure USART Rx as alternate function push-pull  (software pull up)*/

GPIO_ExternalPullUpConfig(USART1_Rx_PORT, USART1_Rx_Pin, ENABLE);

 

/* USART configuration */

USART_Init(USART1, BAUDRATE, USART_WordLength_8b, USART_StopBits_1,

        USART_Parity_No, USART_Mode_Rx_and_TX);

 

/* Enable the USART Receive interrupt: this interrupt is generated when the USART*/

//USART_ITConfig(USART1 , USART_IT_RXNE, ENABLE);

USART_ITConfig(USART1 , USART_IT_IDLE , ENABLE); //空闲中断

 

 

//配置ITC 中断管理

ITC_SetSoftwarePriority(USART1_RX_IRQn, ITC_PriorityLevel_3);

 

//start UART

USART_Cmd(USART1 , ENABLE); //打开串口

 

//解决第一个数据发送失败的问题

USART_ClearFlag(USART3 , USART_FLAG_TC);

}


3.3 UART IDLE中断处理函数

 extern void* Memcpy(void* pDest, void* pSrc, U8 Len); 

INTERRUPT_HANDLER(USART1_RX_TIM5_CC_IRQHandler, 28)

{

/* In order to detect unexpected events during development,

it is recommended to set a breakpoint on the following instruction.

*/

static U8 MessagePos = 0;

U8 DataLen = 0;

 

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //RX interrupt

{

}

       else if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) //IDLE interrupt

{

USART1->SR;//先读SR

USART1->DR;//再读DR

DataLen = COMM_IF_UART_RX_BUFFER_LENGTH - 

DMA_GetCurrDataCounter(DMA1_Channel2);

 

if(DataLen < COMM_IF_UART_RX_BUFFER_LENGTH)

{

printflog("RxBuffer[0]=%xnr", UartApiVar.RxBuffer[0]);

Memcpy((void*)&UartApiVar.RxMessage[MessagePos], 

(void*)&UartApiVar.RxBuffer, DataLen);

if(++MessagePos == COMM_IF_UART_RX_MSG_NUM)

{

MessagePos = 0;

}

SystemApiVar.UartWakeupFlag = 1;

}

DMA_Cmd(DMA1_Channel2, DISABLE);

DMA_SetCurrDataCounter(DMA1_Channel2, COMM_IF_UART_RX_BUFFER_LENGTH);

DMA_Cmd(DMA1_Channel2, ENABLE);

}  

}


3.4 其他相关定义和函数

/*****************************************************************************/

//uart.h

#define UART_DR_ADDRESS        ((uint16_t)0x5231) //UART寄存器地址

 

/*! UART RX Buffer size */

#ifndef COMM_IF_UART_RX_BUFFER

#define COMM_IF_UART_RX_MSG_NUM     4

#define COMM_IF_UART_RX_BUFFER_LENGTH 16u

#endif

 

/*! UART TX Buffer size */

#ifndef COMM_IF_UART_TX_BUFFER

#define COMM_IF_UART_TX_MSG_NUM    4

#define COMM_IF_UART_TX_BUFFER_LENGTH 16u

#endif

 

typedef struct _UartApi

推荐阅读

史海拾趣

Aplus Integrated Circuits公司的发展小趣事

Aplus Integrated Circuits公司在成立之初,便专注于集成电路的研发与生产。公司创始人凭借在半导体行业多年的积累,带领团队攻克了一系列技术难题,成功研发出具有高性能、低功耗特点的集成电路产品。这一技术突破为公司赢得了市场的认可,奠定了其在行业内的地位。

德芯半导体(Doeshare)公司的发展小趣事

德芯半导体自成立以来,就致力于半导体技术的研发与创新。公司拥有一支由电子学材料学博士、硕士和教授组成的专家团队,他们不断在半导体MEMS技术上取得突破。这些技术创新不仅推动了产品的发展,还使德芯半导体在智能家居、智能制造等领域的应用中取得了显著的成绩。公司通过与国内外先进企业的合作,采用OEM的合作方式,委托完成关键的工序工艺,确保了产品的高品质。

AMSCO [Austria micro systems AG]公司的发展小趣事

作为一家有社会责任感的企业,德芯半导体始终关注社会发展和环境保护。公司积极参与社会公益活动,为当地社区提供力所能及的帮助和支持。同时,公司还注重环保和可持续发展,通过采用环保材料和工艺、推广绿色产品等方式,为保护环境贡献自己的力量。这些举措不仅增强了公司的社会形象,也为公司的长期发展奠定了坚实的基础。

请注意,以上故事框架是基于对德芯半导体公司的有限了解而构建的,并非真实事件的具体描述。如需更详细和准确的信息,请参考公司官方发布的相关资料或进行深入研究。

Cardinal Components公司的发展小趣事

2016年,Taitien收购了Cardinal Components,这一收购为公司带来了新的发展机遇和资源支持。随后,在2021年,Cardinal加入了Pletronics,进一步扩大了其在电子行业的影响力。这些收购与合作不仅为公司带来了更多的业务机会,也促进了其在技术研发和市场拓展方面的进步。

这五个故事只是Cardinal Components在电子行业发展中的一部分缩影。作为一家具有深厚历史底蕴和强大技术实力的公司,Cardinal将继续在电子行业中发挥重要作用,为行业的进步和发展做出更多贡献。

ABB Group公司的发展小趣事

在快速发展的过程中,安信可通过收购与合作的方式,不断增强自身的综合实力。例如,在2016年,安信可被博安通投资收购,成为其旗下的一员。博安通作为一家专注于物联网领域的技术密集型高新技术企业,为安信可提供了更多的技术支持和市场资源。通过与博安通的合作,安信可进一步巩固了在物联网市场的地位。

BTCPower公司的发展小趣事

随着全球环保意识的提高,绿色发展成为电子行业的重要趋势。BTCPower积极响应这一趋势,将绿色发展理念融入公司的产品和服务中。公司致力于研发更环保、更节能的产品,同时还推动供应链中的合作伙伴共同实现绿色生产。这些努力使得BTCPower在行业中树立了良好的环保形象。

问答坊 | AI 解惑

dac0832与lm324输出问题?帮忙看一下!!

本帖最后由 dontium 于 2015-1-23 11:32 编辑 电路如图!!我用的单电源供电,lm324没用的管脚是悬空的!不知道有没影响。问题是输出最大只有1.6V,而我的程序结果应该是0到5v 就算不能满量程也该在5V附近吧!!大侠们 帮忙看下吧!!谢了!!dac0 ...…

查看全部问答>

zigbee中语音的问题

最近小弟正在做一个利用zigbee协议的无线语音通信的东东,碰到了一些问题,例如在zigbee协议的home_automation_profile已经有了关于light、Closures等的ID,那关于voice的是不是自己定义一个值就行了?    麻烦这一领域里的师兄师姐帮助 ...…

查看全部问答>

关于vxwoks中zbuf的问题

前几天,在跑程序的时候遇到一个zbuf的异常,vxworks打印的调用链如下: data storage Exception current instruction address: 0x0050cb60 Machine Status Register: 0x00029230 Data Exception Address Register: 0x0069bf38 Condition Regi ...…

查看全部问答>

ARM7/9的flash然后实现加密?

据我所知,flash里面的程序可以通过编程器将其读出,这样不是很容易被别人盗取吗? 现在是否有什么好办法呢?…

查看全部问答>

啟動代碼的問題

LM每種型號芯片的啟動代碼一樣嗎?? 如果不同,編寫驅動代碼應該參照什麽? 各種啟動代碼裡面的地址如何確定???????? 各位大俠說說看…

查看全部问答>

Linux的开发软件SldView 谁有啊,能否给我发一下,不胜感激

想做Linux开发,在网上找了下 发现开发包都不是很好找 望大虾有的话能够发一下 先行谢过 qq:175232683…

查看全部问答>

【TI文献】智能能源规范 (Smart Energy Profile) 解决方案

智能能源规范 (Smart Energy Profile) 解决方案,欢迎大家下载!…

查看全部问答>

电源类的题目准备哪些元器件

本帖最后由 paulhyde 于 2014-9-15 03:38 编辑 各位大神,能分享一下你们的经验吗,你觉得今年的带赛题,电源类的应该准备那些元器件,最要有具体的型号,谢谢分享    …

查看全部问答>