关于STM32串口中 0x0a,0x0d的学习

**

以STM32正点原子的串口接收中断 服务程序为例:

**

    void USART1_IRQHandler(void)                	//串口1中断服务程序
    	{
    	u8 Res;
    #ifdef OS_TICKS_PER_SEC	 	//如果时钟节拍数定义了,说明要使用ucosII了.
    	OSIntEnter();    
    #endif
    	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    		{
    		Res =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据
		
		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;//接收数据错误,重新开始接收	  
					}		 
				}
			}   		 
     } 
#ifdef OS_TICKS_PER_SEC	 	//如果时钟节拍数定义了,说明要使用ucosII了.
	OSIntExit();  											 
#endif
} 

其中 0D 0A这是自行定义的一种数据帧结束标志,不定义这个不没法判断你这一帧数据什么时候结束了, 0D 0A是什么东西咧,它就是我们的回车键的ASCII码, 0D回车,0A换行 像在windows超级终端里一条数据输入完按回车正好来了个0D 0A,表示数据发完了

0x0D(asc码是13) 指的是“回车” \r是把光标置于本行行首

0x0A(asc码是10) 指的是“换行” \n是把光标置于下一行的同一列

0x0D + 0x0A 回车换行 \r\n把光标置于下一行行首

\n是换行,英文是linefeed,ASCII码是0xA。

\r是回车,英文是carriage return ,ASCII码是0xD。

USART_RX_STA是16位的数据,原子定义了最高位15是接收完成标志位,USART_RX_STA[15]=1时表示接收完成。所以0x8000好理解吧,就是最高位为1其他都为0,跟USART_RX_STA相与,低15位都被置0了只留下最高位即接收完成标志位,所以就可以通过USART_RX_STA&0x8000这样的方式来判断是否接收完成。
USART_RX_STA与0X3FFF进行与运算是用来确定接收到的数据长度的,USART_RX_STA的每个bit的含义教程里面有详细的讲解。

下面转自一个解读:
解读:
怎么写接收函数?

只要收到一个字节 stm32会产生中断

进入中断编写

//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
u16 USART_RX_STA=0; //接收状态标记

第一步判断标志位是否正的接收到

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

第二步 接收下数据

Res =USART_ReceiveData(USART1); //读取接收到的数据

第三步判断标志位USART_RX_STA 上次是否接收完成(上次接收完成了会把标志位置1)

if((USART_RX_STA&0x8000)==0)//接收未完成

其中USART_RX_STA 是自己定义的16位变量用于标志接收完成或者接收到0x0d 类似于自己定义了一个寄存器

第四步 判断标志位USART_RX_STA 上次是否接收到了0xod

if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始 如果上次接收到了/r(0x0d)这次应该是/n (0x0a)

else USART_RX_STA|=0x8000; //接收完成了

否则上次没有接收到0x0d

if(Res==0x0d)USART_RX_STA|=0x4000; //判断本次是否接收到了0x0d
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; //把接收到的数据存入buf缓存区
USART_RX_STA++; //记录接收的数据字节数量

if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收 接收的数据不能无限制的大

}

总结
这样的编程方式其实利用了状态机思想,增强稳定性,减少错误

本次实验有两个状态bit15接收状态,bit14接收到/r状态

编程时应该观察两个状态,注意到临界态 切换状态

首先判断当前接收处于什么状态,而不是盲目的接收

1、首先观察bit15状态 如果处于接收态应该注意 观察下一个状态bit14 在满足条件时切换bit15

2、观察bit14状态 如果处于接收到了/r态 再应该判断接收值是否满足 切换bit15态的条件

如果处于没有接收到\r态,应该判断接收值是否满足切换bit14的条件

if(USART_RX_STA&0x4000)//上次接收到了0x0d /r

else USART_RX_STA|=0x8000; 改变接收状态bit15

if(Res==0x0d) 接收到了/r

USART_RX_STA|=0x4000; 切换状态bit14

https://blog.csdn.net/shenlong1356/article/details/79940280
版权声明:本文为博主原创文章,转载请附上博文链接!

你可能感兴趣的:(STM32)