当前位置: 代码迷 >> 单片机 >> 串口时灵时不灵,该如何解决
  详细解决方案

串口时灵时不灵,该如何解决

热度:119   发布时间:2016-04-28 14:54:52.0
串口时灵时不灵
本帖最后由 yule_169 于 2014-07-01 15:00:49 编辑
通过串口助手(9600-8-0-1)发送三个字节,如果首字节为0x34,则返回两个字节0x03、0x00,继续等待接受新输入;如果首字节不是0x34,则不作应答,等待接受新输入。调试发现如果连续手动输入34 01 02返回结果正确,可一旦输入首字节不是34(如01 02 03),则再输入34 01 02也没有反应了。通过观察窗发现最后输的34 01 02没有被读进数组receive。然后加入else那一段,即首字节不是34的话就返回ff,这样两种情况都正常返回,且可以连续输入。看上去好像要再接受字符的话必须要先发送字符?没道理啊,请各位帮帮忙。
我用的是C8051F310。本来是在编modbus从机端程序如果从机号不对的话就不响应,结果也是不能接受新的命令帧了。。

#include "initial.h"
#include <string.h>
typedef unsigned char  byte;

byte send[20];        //用于存放发送的数据 
byte receive[20];    //用于存放接收的数据 
byte rec_ptr;           //用于给接收到的数据编号
byte rec_flag;         //rec_flag=1时表示已接收到一帧数据,对数据帧解析完rec_flag被置为0 
byte rec_bytes;      //接收的字节数  

main(void)
{      
    byte i;
byte *ssd;
rec_ptr = 0;
rec_flag = 0; 
PCA0MD &= ~0x40;          // 关闭看门狗
    Init();//单片机初始化
EA=1;  //允许所有中断 
         
  while(1)
  { //等待中断接受完3个字节rec_flag置1
while (rec_flag==1)
   {
send[0]= rec_bytes;
send[1]= 0x00;
ssd = send;
    if(receive[0] == 0x34)
{
for(i=0;i<2;++i)
{          
SBUF0=*ssd++;
while(TI0==0);
     TI0=0;
  }
}
/* else
{
SBUF0=0xff;
while(TI0==0);
     TI0=0;
} */
rec_flag=0;
}
  }
}

void uart0(void) interrupt 4 
{
        if(RI0)
{
      RI0=0;
        receive[rec_ptr++] = SBUF0;         // rec_ptr初始值为0,每接受一个数据便自增1

    if (rec_ptr==3 )
{
          rec_bytes = rec_ptr;
rec_ptr = 0;               
rec_flag = 1;
}
    }
}

------解决方案--------------------
程序加上一段超时控制,通讯超时后rec_ptr复位就可以用了
------解决方案--------------------
引用:
Quote: 引用:

程序加上一段超时控制,通讯超时后rec_ptr复位就可以用了

这个超时控制的意思是不是说多少时间没有收到新输入了就判断一帧接受完毕了?

是的 可以这样理解
------解决方案--------------------
引用:
Quote: 引用:

Quote: 引用:

Quote: 引用:

程序加上一段超时控制,通讯超时后rec_ptr复位就可以用了

这个超时控制的意思是不是说多少时间没有收到新输入了就判断一帧接受完毕了?

是的 可以这样理解

换了个串口助手软件就可以了..坑

串口软件很多 但质量参差不齐
比如有一个名字叫串口调试助手,它的奇偶校验就是假的
------解决方案--------------------
还是要加超时清除功能,否则任何干扰误接收都会造成问题。要让程序健壮(Robust)
------解决方案--------------------
判断如果不是的话   要清空接收的数组         单步调试    这问题容易解决   
  相关解决方案