串口中断
串口发生了相应的中断,就会跳到系统规定好中断函数去处理。先判断是否接受中断,然后读取串口接收到的数据
void USART1_IRQHandler(void) //串口1中断服务程序
{
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
}
#endif
官方串口设计的接收协议,主要运用了USART_RX_BUF[]数组和USART_RX_STA状态标志。这两个变量的操作尤其重要,如果不了解,以上的代码往往一头雾水。
Res =USART_ReceiveData(USART1); //读取接收到的数据
从串口接收到的数据只有一个字节的,也就是串口是一个字节一个字节进行判断的,每次res里面都是最新的字节,所以我们要读到一条完整的或者指定的数据长度,我们就要用USART_RX_BUF来存储,而USART_RX_STA就是辅助判断数据状态的。
u16 USART_RX_STA=0;
16位无符号数,也就对应表中的bit0~15也就是16位,每一位都有各自特定的功能。(两个表超级重要!!!!务必理解)
bit15 | bit14 | bit13~0 |
---|---|---|
&0x8000 | &0x4000 | &0x3FFF |
两个表对应看,想要知道触发串口中断后,串口是否接收完成所有数据(0代表没有接收完成,1代表完成。)
if((USART_RX_STA&0x8000)==0)//接收未完成
1000 0000 0000 0000(0x8000)
& 0000 0000 1100 0101(0xC5) = 0 (只有接收到的数据长度超过USART_RX_STA才会有,但该变量是人为操作的,我们常常判断接收到固定长度后,将USART_RX_STA|0x8000,提示已完成指定长度数据接收,也有利于其他函数调用判断)
if(USART_RX_STA&0x4000)//接收到了0x0d
{
if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
else USART_RX_STA|=0x8000; //接收完成了
}
USART_RX_BUF是专门存放数据的,串口接收到一个字节的数据,USART_RX_STA就会累加,USART_RX_BUF[USART_RX_STA]=res就可以按顺序保存数据,但是bit15和bit14位指定进行两个判断功能,就不能拿来使用保存数据,所以我们这里&0X3FFF来截断数据。
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
0011 1111 1111 1111(0x8000)
& 0000 0000 0000 0100(USART_RX_STA=4) = 0100=4
USART_RX_STA
或0x8000 | &0X3FFF | =0 | 或0x4000 |
---|---|---|---|
接收完成,跳出函数 | 收到几节数据 | 重新开始 | 是否收到空格 |