问题:USART_RX_STA有什么用,为什么USART_RX_STA会接收完成改变14和15位。
【小贴士】在介绍之前首先了解回车和换行的表示方法和区别:
回车:回到当前行行首,不会回到下一行,如果接着输入则会覆盖本行以前的内容。
换行:换到当前位置的下一行,而不会回到首行。
回车 | 换行 |
0x0d | 0x0a |
\r | \n |
如果我们想接收一个字符串“HELLO/r/n”在这个回调处理函数中是如何设计的?
串口中断接收过程:
串口接收函数每次接收到一个字符后进入中断服务函数来处理,中断服务函数主要包括回调函数,会点函数主要由以下主要参数构成:
USART_RX_STA我们定义的一个16位接收状态寄存器,首先应当明确USART_RX_STA的0-13位只是记录接收到的数据个数的作用,其结构如下:
void USART1_IRQCallback(u8 res)
{
if(huart->Instance==USART1)//如果是串口1
{
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;//接收数据错误,重新开始接收
}
}
}
}
}
设计思路如下:
当接收到从电脑发过来的数据,把接收到的数据保存在 USART_RX_BUF 中,同时在接收状态寄存器(USART_RX_STA)中计数接收到的有效数据个数,当收到回车(回车的表示由 2个字节组成: 0X0D 和 0X0A)的第一个字节 0X0D 时,计数器将不再增加,等待 0X0A 的到来,而如果 0X0A 没有来到,则认为这次接收失败,重新开始下一次接收。如果顺利接收到 0X0A,则标记 USART_RX_STA 的第 15 位,这样完成一次接收,并等待该位被其他程序清除,从而开始下一次的接收,而如果迟迟没有收到 0X0D,那么在接收数据超过 USART_REC_LEN 的时候,则会丢弃前面的数据,重新接收。
我们看USART_RX_BUF[USART_RX_STA&0X3FFF]=res这句话,USART_RX_STA&0X3FFF的值是随着USART_RX_STA的递增进而改变的,就拿“HELLO/r/n”这个例子来说。
正常接收’HELLO’这五个字母时可以按照下表的方式向USART_RX_BUF数组里存放数据,当字母接收完毕,res收到’/r’时,即’0x0d’,将USART_RX_STA的bit14置1继续接收’0x0a’,如果接收到’0x0a’则将USART_RX_STA的bit15置1,表明当前的字符串接收完毕。整个接收过程宣告结束。具体的程序流程如下:
中断次数 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
接收的数据 | H | E | L | L | O | /r | /n |
USART_RX_STA | 0 | 1 | 2 | 3 | 4 | ||
USART_RX_STA&0X3FFF | 0 | 1 | 2 | 3 | 4 | ||
M[i] | M[0] | M[1] | M[2] | M[3] | M[4] | ||
USART_RX_STA++ | 1 | 2 | 3 | 4 | 5 | ||
接收’H’ | (0x3fff) 0011 1111 1111 1111 &(1) 0000 0000 0000 0000 0001 = 1 | ||||||
接收’E’ | (0x3fff) 0011 1111 1111 1111 &(2) 0000 0000 0000 0000 0010 = 2 | ||||||
接收’L’ | (0x3fff) 0011 1111 1111 1111 &(3) 0000 0000 0000 0000 0011 = 3 | ||||||
接收’L’ | (0x3fff) 0011 1111 1111 1111 &(4) 0000 0000 0000 0000 0100 = 4 | ||||||
接收’0’ | (0x3fff) 0011 1111 1111 1111 &(5) 0000 0000 0000 0000 0101 = 5 | ||||||
接收’/r’ | USART_RX_STA =0100 0000 0000 0101 | ||||||
接收’/n’ | USART_RX_STA =1100 0000 0000 0101 | ||||||
注:便于观察将USART_RX_BUF[USART_RX_STA&0X3FFF]数组表示为M[i] |
看完上述分析我们重新回顾一下上述设计思路是不是就清晰了很多呢:
当接收到从电脑发过来的数据,把接收到的数据保存在 USART_RX_BUF 中,同时在接收状态寄存器(USART_RX_STA)中计数接收到的有效数据个数,当收到回车(回车的表示由 2个字节组成: 0X0D 和 0X0A)的第一个字节 0X0D 时,计数器将不再增加,等待 0X0A 的到来,而如果 0X0A 没有来到,则认为这次接收失败,重新开始下一次接收。如果顺利接收到 0X0A,则标记 USART_RX_STA 的第 15 位,这样完成一次接收,并等待该位被其他程序清除,从而开始下一次的接收,而如果迟迟没有收到 0X0D,那么在接收数据超过 USART_REC_LEN 的时候,则会丢弃前面的数据,重新接收。
往期回顾: