正点原子stm32--串口通信实验讲解里关于USART_RX_STA的问题与思考

目录

  • 问题背景
  • 问题
  • 解决
  • 结尾

问题背景

  u16 USART_RX_STA=0; //接收状态标记

  USART_RX_STA的作用就是在全部函数之间实现一个消息传递,自己设置,自己管理,自己识别。

                     USART_RX_STA

bit15 bit14 bit13~0
接收完成标志0x0a 接收到0X0d标志 接收到的有效数据个数

问题

  在串口中断函数里的一个全局变量USART_RX_STA,阅读串口中断函数里的程序时在想:USART_RX_STA里的数据是如何存入里面的,bit15接收完成标志位是从寄存器里取出来的?

解决

void USART1_IRQHandler(void)                	//串口1中断服务程序
	{
	u8 Res;

	if( USART_GetFlagStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)(0x0D是回车的ASCLL码,0x0A是换行的ASCLL码)
		{
		Res =USART_ReceiveData(USART1);	//读取接收到的数据
		
		if((USART_RX_STA&0x8000)==0)//接收未完成    1000 0000 0000 0000
			{
			if(USART_RX_STA&0x4000)//接收到了0x0d     0100 0000 0000 0000
				{
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始--接收到了0X0D但是没有接受到0x0A
				else USART_RX_STA|=0x8000;	//接收完成了--0x0d后面是0x0a 
				}
			else //还没收到0X0D
				{	
				if(Res==0x0d)USART_RX_STA|=0x4000; //再次判断这次接收到的是不是0x0d
				else
					{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; // 0011 1111 1111 1111
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
					}		 
				}
			}   		 
     } 

  我们来彻底的理一下上面程序的逻辑:假设我们第一次接收数据。接收的数据为abcd。
      ①在第一次进入串口中断处理函数,我们先判断是否接是因为USART1接受到了数据产生的中断
          【if(USART_GetFlagStatus(USART1, USART_IT_RXNE) != RESET)】
       如果是,则将USART1接受到的一位数据(a)存入变量Res里(Res = “a”)

      ②然后我们来判断接收的一系列数据是否没接收完。(当然没有啦,我们还有b、c、d三个数据没有接收)
          【if((USART_RX_STA&0x8000)==0) //接收未完成 】
       这个时候呢,USART_RX_STA——这个在全部函数之间实现消息传递的变量的值仍然为0,和0x8000相与以后为0,那么执行该if语句的内层函数。

                    要坚持继续向下看呀↓看到后面就会理解的。

     ③进入该if语句的内层语句后又是一个判断语句
          【if(USART_RX_STA&0x4000)//接收到了0x0d】知识点:0x0d是回车的ASCLL码,0x0a是换行的ASCLL码
       这里判断USART_RX_STA的第14位是否为1,如果我们接收到了回车,即0x0d那么USART_RX_STA的第14位会置1。在我们接收第一个数据a时USART_RX_STA当然还为0,(我们后面的的b、c、d、3个数据还都没接收了,当然不会收到0x0d)USART_RX_STA和0x400相与为0,该判断语句就为假,执行下面的else语句。

     ④该else语句的内层语句是一个if-else语句
          【if(Res==0x0d)USART_RX_STA|=0x4000; 】

       这里我就不再赘述,我们接收的是数据a,还没有接收到0x0d,执行else语句。          
          USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; // 0x3ff = 0011 1111 1111 1111
          USART_RX_STA++;
           if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收

            如果忘记USART_RX_STA里十六位数据分别是什么意思的话可以翻到最上面回顾一下

       USART_RX_STA的bit0~bit13代表的是接收到的有效数据个数,这里USART_RX_STA值仍为0,USART_RX_STA & 0X3FFF = 0 ,然后USART_RX_BUF[USART_RX_STA&0X3FFF]=Res,意思就是将Res里的数据存放到USART_RX_BUF[0]里了,并且USART_RX_STA自增1。
       此时USART_RX_STA = 1这样在接收到下一个数据b后USART_RX_STA&0X3FFF = 1,将b存入到了USART_RX_BUF[1]里,一直循环下去,直到我们接收到了0x0d(Res = 0x0d)。

我们可以从上面程序里找到如下代码:

else //还没收到0X0D
				{	
				if(Res==0x0d)USART_RX_STA|=0x4000; //再次判断这次接收到的是不是0x0d

  当接收到0x0d并且程序执行到这一步一时USART_RX_STA = 4,此时该if语句成立,执行USART_RX_STA|=0x4000,即0000 0000 0000 0100 | 0100 0000 0000 0000 = 0100 0000 0000 0100 ,我们可以清晰的看到bit13~0位是4,代表接收到了4个数据(a,b,c,d),第14位为1,是因为接收到了数据0x0d,也和最上面给的表对上了,然后程序向下执行,接收到了0x0d(回车),那下一个就是接收0x0a(换行)了,Res = 0x0a(跑呀跑,执行到这里了):

if(USART_RX_STA&0x4000)//接收到了0x0d     0100 0000 0000 0000
				{
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始--接收到了0X0d但是没有接受到0x0a
				else USART_RX_STA|=0x8000;	//接收完成了--0x0d后面是0x0a  
				}

  这里第一个判断语句if(USART_RX_STA&0x4000),当然为真,因为Res = 0x0a,那么执行else语句USART_RX_STA|=0x8000,即0100 0000 0000 0100 | 1000 0000 0000 0000 = 1100 0000 0000 0100。到了这一步,就说明这一串数据已经完完全全的接收完了USART_RX_STA = 1100 0000 0000 0100,最高位为1:代表接收到了0x0a,第十四位为1:代表接收到了0x0d,第0位到第13位为4,代表接收到了4位有效数据(a、b、c、d),再次把那个表格放出来我们对比一下:
                      USART_RX_STA

bit15 bit14 bit13~0
接收完成标志0x0a 接收到0X0d标志 接收到的有效数据个数

  这样我们这个串口1中断服务程序函数已经完完全全的理解了!!!

结尾

  emmm…没有什么可说的了,有强迫症,必须要格式好看(╥╯^╰╥)。

你可能感兴趣的:(STM32,串口通信,单片机,stm32)