当前位置: 代码迷 >> 单片机 >> STM32 在串口终端增加数据处理后,没法正确接受数据
  详细解决方案

STM32 在串口终端增加数据处理后,没法正确接受数据

热度:334   发布时间:2016-04-28 14:53:19.0
STM32 在串口终端增加数据处理后,无法正确接受数据
现象:
1.通过电脑向STM32 串口发送数据0xaa,0x6f,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,当满足一定条件时,串口数据在主函数打印接收到的数据。如第一段代码所示。
2.当在串口1中断增加数据处理时,串口数据只有前两位是正确的,结果为0xaa,0x6f,0x6f,0x6f,0x6f,0x6f,0x0,0x0,0x0,0x0 。如第二段代码所示。
3.当串口1中断只做接收数据时,串口能完整接收数据。如第三段代码所示。

在main.c中用如下代码进行打印:

while(1)
    {   
    if(1==usart_flag)
{

printf("STM32 receive data\r\n");
for(i=0;i<10;i++)
{
printf("0x%x,",usart_buff[i]);
}
printf("\r\n");
usart_flag=0;
}
    }

SMT32用以下代码只有前2个字节数据正确。STM32 打印 结果为0xaa,0x6f,0x6f,0x6f,0x6f,0x6f,0x0,0x0,0x0,0x0,

void USART1_IRQHandler(void)
{

u8 key=0;
u16 i=0,j=0;
u8 input=0;

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

while(input!=0xaa)
{
input=USART_ReceiveData(USART1);
}//寻找帧头
usart_buff[count++]=0xaa;
printf("get the head\r\n");
key=USART_ReceiveData(USART1);

usart_buff[count++]=key;
printf("key =0x%x\r\n",key);
 
#if 1  

switch(key)
{
case 'o'://接收到PC->STM32板的消息接收成功消息
{
 
//获取长度
for(i=0;i<4;i++)
{
usart_buff[count++]=USART_ReceiveData(USART1);
}  
//获取data,命令O  没有数据
//获取CRC32
for(i=0;i<4;i++)
{
usart_buff[count++]=USART_ReceiveData(USART1);
}  
usart_flag=1;
break;
}
default: break;
}
#endif
}
}


STM32用以下代码,能够完全接受数据:

void USART1_IRQHandler(void)
{

u8 key=0;
u16 i=0,j=0;
u8 input=0;

   if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
   {
     usart_buff[count++]=USART_ReceiveData(USART1);
if(count>8)
{
usart_flag=1;
}

    }

}

------解决方案--------------------
STM32 在串口终端增加数据处理后,无法正确接受数据,不增加数据处理接收到的数据是否正确?

如果正确,请仔细检查数据处理部分的代码。
------解决方案--------------------
逻辑问题
你仔细看,在接收正常的那个代码里
每次执行
 usart_buff[count++]=USART_ReceiveData(USART1);
时,满足条件
if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)

但在你增加了printf的那个代码里,从第二个
key=USART_ReceiveData(USART1);
开始,
(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
不一定满足.
即你后面读的数据是错误的,你没判断GetITStatus就去读了
------解决方案--------------------
引用:
逻辑问题
你仔细看,在接收正常的那个代码里
每次执行
 usart_buff[count++]=USART_ReceiveData(USART1);
时,满足条件
if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)

但在你增加了printf的那个代码里,从第二个
key=USART_ReceiveData(USART1);
开始,
(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
不一定满足.
即你后面读的数据是错误的,你没判断GetITStatus就去读了

同意,问题不在数据处理上。
楼主用中断接收时,每次中断都只收了一个字节,也就是这个硬件系统中,UART有收到数据会产生中断。数据读完,FIFO空掉才不会再产生中断。
而楼主带数据处理的程序中,来了中断,就直接去把所有数据读出来,根本没考虑UART FIFO中是否有后续字节过来。所以后面的字节全无效了。这相当于把中断模式改成了轮询模式,而又没有去看状态寄存器,UART是否已收到数据可以读了。

------解决方案--------------------
楼主的处理确实有问题。比较好的方式是中断只管接收,主循环中去查询处理。如果一定要在中断中处理,也只能是每次中断进入只接收当前数据,保存当前状态(接收到第几个字节等),然后退出等待下次中断。像printf之类复杂函数应避免在中断中调用
------解决方案--------------------
LZ在中断里面做的事情太多了
而且还有一个 while(input!=0xaa)    {        input=USART_ReceiveData(USART1);         }//寻找帧头 
像这样的代码是绝对不允许的
还是请LZ优化一下代码结构
像楼上说的,中断只接收数据,数据的处理放在中断外