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

yyang0514 2014-08-11 11:33:13
现象:
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;
}

}

}
...全文
645 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
phyyww 2014-09-23
  • 打赏
  • 举报
回复
感觉说的挺好的!
yyang0514 2014-08-19
  • 打赏
  • 举报
回复
中断函数代码贴错了。

extern int count;
extern u8 *usart_buff;
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
   {
   	 usart_buff[count++]=USART_ReceiveData(USART1);
   }
}
yyang0514 2014-08-19
  • 打赏
  • 举报
回复
引用 8 楼 chengchenz 的回复:
[quote=引用 6 楼 wangfan027 的回复:] 逻辑问题 你仔细看,在接收正常的那个代码里 每次执行 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是否已收到数据可以读了。 [/quote] 问题已经处理了。主要修改方法: 1、 中断只负责接收数据,主函数里面进行数据解析。 2、主函数里面用于解析数据时,不能使用检测中断的函数来进行。 代码如下: main.c

u8 *usart_buff;
u8 count=0;
while(1)
{
	if(USART_GetFlagStatus(USART1,USART_IT_RXNE)==RESET&&count!=0)
	{
	   for(i=0;i<100;i++)
	   {
			if(usart_buff[i]!=0x0)
			{
			USART_SendData(USART1,usart_buff[i]);
			while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
			}
		   }
		for(i=0;i<100;i++)
	   {
	   	usart_buff[i]='\0';
	   }
		
	   count=0;
	
	}
}
中断函数:

extern int count;
extern u8 *usart_buff;
void USART1_IRQHandler(void)
{
if(USART_GetFlagStatus(USART1,USART_IT_RXNE)==RESET&&count!=0)
	{
	   for(i=0;i<100;i++)
	   {
			if(usart_buff[i]!=0x0)
			{
			USART_SendData(USART1,usart_buff[i]);
			while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
			}
		   }
		for(i=0;i<100;i++)
	   {
	   	usart_buff[i]='\0';
	   }
		
	   count=0;
	
	}
}
默寞 2014-08-12
  • 打赏
  • 举报
回复
LZ在中断里面做的事情太多了 而且还有一个 while(input!=0xaa) { input=USART_ReceiveData(USART1); }//寻找帧头 像这样的代码是绝对不允许的 还是请LZ优化一下代码结构 像楼上说的,中断只接收数据,数据的处理放在中断外
91program 2014-08-11
  • 打赏
  • 举报
回复
STM32 在串口终端增加数据处理后,无法正确接受数据,不增加数据处理接收到的数据是否正确? 如果正确,请仔细检查数据处理部分的代码。
mangoalx 2014-08-11
  • 打赏
  • 举报
回复
楼主的处理确实有问题。比较好的方式是中断只管接收,主循环中去查询处理。如果一定要在中断中处理,也只能是每次中断进入只接收当前数据,保存当前状态(接收到第几个字节等),然后退出等待下次中断。像printf之类复杂函数应避免在中断中调用
FreshBird 2014-08-11
  • 打赏
  • 举报
回复
引用 6 楼 wangfan027 的回复:
逻辑问题 你仔细看,在接收正常的那个代码里 每次执行 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是否已收到数据可以读了。
zhxianbin 2014-08-11
  • 打赏
  • 举报
回复
从描述看,很明显是数据处理出问题了,这个别人不知道你的逻辑,找出错误比较难。 这里我觉得就有问题 while(input!=0xaa) { input=USART_ReceiveData(USART1); }//寻找帧头 不能每次寻找帧头
dceacho 2014-08-11
  • 打赏
  • 举报
回复
逻辑问题 你仔细看,在接收正常的那个代码里 每次执行 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就去读了
91program 2014-08-11
  • 打赏
  • 举报
回复
建议 LZ 再仔细看看那部分代码,偶是认为此部分的处理逻辑有问题。 但由于偶不熟悉 STM32 的东东,没有办法给出如何修改代码。
yyang0514 2014-08-11
  • 打赏
  • 举报
回复
引用 3 楼 91program 的回复:
LZ,你的数据处理部分有问题吧! 1 既然是处理,为什么其中还有接收功能? 2 如何判断接收完毕,LZ 是如何定义的?
1 既然是处理,为什么其中还有接收功能? 我是中断中完成接收,并判断接收到的数据是否满足传送命令的格式。 如果不满足就丢弃。 2 如何判断接收完毕,LZ 是如何定义的? 当接收完成将usart_flag=1; 置为1即表示接收完成。
91program 2014-08-11
  • 打赏
  • 举报
回复
LZ,你的数据处理部分有问题吧! 1 既然是处理,为什么其中还有接收功能? 2 如何判断接收完毕,LZ 是如何定义的?
yyang0514 2014-08-11
  • 打赏
  • 举报
回复
引用 1 楼 91program 的回复:
STM32 在串口终端增加数据处理后,无法正确接受数据,不增加数据处理接收到的数据是否正确? 如果正确,请仔细检查数据处理部分的代码。
比较了的,中断中只做接收是没有问题的。

 if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
 {
     usart_buff[count++]=USART_ReceiveData(USART1);
    if(count>8)
    {
        usart_flag=1;
    }
 
  }
但我在实际使用过程中,串口确实需要对不同长度的数据进行处理。 现在 我将接收数据内容放到中断里面实现。如下面的代码所示。请问这种情况下,有没有好的方法来实现。

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);         
   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;
        }   
  
}

27,372

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧