本文主要分析正点原子stm32的void USART1_IRQHandler(void) 函数
一下为源代码
void USART1_IRQHandler(void) //串口一中断服务函数
{
u8 Res;
#if SYSTEM_SUPPORT_OS 如果SYSTEM_SUPPORT_OS为真支持OS.
OSIntEnter();
#endif
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断,接收到的数据必须以0x0d 0x0a结尾
{
Res =USART_ReceiveData(USART1); //读取接收到的数据
if((USART_RX_STA&0x8000)==0)//接收未完成
{
if(USART_RX_STA&0x4000)//接收到了0x0d
{
if(Res!=0x0a)USART_RX_STA=0;//接受错误重新开始
else USART_RX_STA|=0x8000; //接收完成了
}
else //没有收到0X0D
{
if(Res==0x0d)USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收错误重新开始接收
}
}
}
}
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真支持OS.
OSIntExit();
#endif
}
-
下面我们开始一步一步地对这个程序作解释
- 1、定义了一个Res用于在Res =USART_ReceiveData(USART1);中存储串口1发送的数据,注意这里的数据是按位进行发送的。
-
2、使用if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) 经过USART_GetITStatus我也不知道判断了什么?
3、利用USART_ReceiveData(USART1)将通道1发送的数据存储到Res中
4、在这里先给大家讲解下USART_RX_STA的作用,USART_RX_STA一共有16位,前两位为标记位,后14位记录了串口发送的数的位数。第一位标记位标记了Res是否为0x0a,第二位标记位标记了Res是否为0x0d。具体为什么在接下来的讲解中会给大家讲。
以下为整篇文章的重点
if((USART_RX_STA&0x8000)==0)//接收未完成 if1
{
if(USART_RX_STA&0x4000)//接收到了0x0d if2
{
if(Res!=0x0a)USART_RX_STA=0;//接受错误重新开始 if3
else USART_RX_STA|=0x8000; //接收完成了 else1
}
else //没有收到0X0d else2
{
if(Res==0x0d)USART_RX_STA|=0x4000; if4
else //else3
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收错误重新开始接收 if5
}
}
}
首先让我们回到USART_RX_STA变量的起点u16 USART_RX_STA=0; //接收状态位标记
u16 USART_RX_STA=0; //接收状态位标记
if1使用USART_RX_STA&0x8000==0判断USART_RX_STA的第一位是否为0,这时因为USART_RX_STA的初始值为0,所以我们进入if2.
if2使用USART_RX_STA&0x4000判断USART_RX_STA的第二位是否为1,与if1类似所以我们进入else2.
else2中首先用if4判断了Res是否0x0d /0x0d 和0x0a 分别为回车和换行字符/ 即Res是否为回车,这里如果串口有输入数据的话明显是否的,所以我们进入else3.
else3为本篇代码的精髓所在,首先USART_RX_BUF[ ]是在前面定义的一个最大为USART_REC_LEN的数组,而USART_RX_STA&0X3FFF即得到USART_RX_STA变量的后14位记录串口已输入数据位数的大小。以USART_RX_STA作为USART_RX_BUF[ ]的下标,再配合上下一句的USART_RX_STA++;可以完美的把数据存储到USART_RX_BUF[ ]数组中。最后的if5则控制着输入数据的长度防止其超过USART_RX_STA的14位数据记录位的大小。
而后便是不断地从串口接收数据,不断去判断是否为串口发送数据的最后一位。如果是则在倒数第2次循环中使用USART_RX_STA|=0x4000;将第二位状态标志位置为1;在倒数第1次循环中使用USART_RX_STA|=0x8000;将第一位状态标志位也置为1,;而后串口数据接收结束,所有从串口接收的数据保存在USART_RX_BUF[ ]数组中,串口所发送的数据长度保存在USART_RX_STA的后14位中。
由于两个这两个变量都是宏定义,所以原子哥在main.c中就直接使用了它们,这里要注意的点就是USART_RX_STA只有后14位为记录串口所发数据长度的数据位,所以在使用时切记不要直接使用USART_RX_STA而是USART_RX_STA&0x3fff 得到USART_RX_STA后14位的数据位。
再次感谢原子哥开源的代码
以上