打印

串口接收一串数据丢失问题

[复制链接]
11486|23
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jiangjiajun|  楼主 | 2013-3-7 10:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
zhaoyu2005| | 2013-3-7 10:21 | 只看该作者
重点检查串口接收程序和配置

使用特权

评论回复
板凳
jiangjiajun|  楼主 | 2013-3-7 14:33 | 只看该作者
我把程序贴一下吧,比如我第一次发了01 02 03 04 05 06,串口只接收到01,后面的数据就没有了

#include <reg52.h>

#define uchar unsigned char
#define uint unsigned int


uchar buf[6];
uchar recbuf[6];


void Init_Com(void)   //初始化串口
{
        TMOD = 0x20;
        PCON = 0x00;
        SCON = 0x50;
        TH1 = 0xFd;
        TL1 = 0xFd;
        TR1 = 1;
}



void delay(uint count) //延时子函数
{
        uint i;
        while(count)
        {
                i=100;
                while(i>0)
                i--;
                count--;
        }
}


void combyte(uchar ch) //发送一个字节
{
       
        SBUF=ch;       
        while(TI==0);       
        TI=0;                       
}

void comstring(uchar *str, uint len) //发送一个字符串
{
       
        uint k=0;
        do
        {
                combyte(*(str+k));
                k++;
        }
        while(k<len);
}



void recvbuf(uchar *rec, uint lenth)  //接收串口数据
{
    uint i;

    for(i=0;i<lenth;i++)
        {

       while(RI==0);
          
           rec[i]=SBUF;
           RI=0;
    combyte(rec[i]);
            
        }

}


void main() //主函数
{

        Init_Com(); //初始化串口

    RI=0;
        TI=0;
   
        do
        {

        delay(30);

      if(RI==1)
      {
         
                  recvbuf(recbuf,6);
              comstring(recbuf,6);               
      }
     
        }
        while(1);   
}

使用特权

评论回复
地板
jiangjiajun|  楼主 | 2013-3-7 14:34 | 只看该作者
zhaoyu2005 发表于 2013-3-7 10:21
重点检查串口接收程序和配置

这两个应该没什么问题。。麻烦你看一下程序吧~我贴出来了

使用特权

评论回复
5
jiangjiajun|  楼主 | 2013-3-7 14:35 | 只看该作者
qingx 发表于 2013-3-7 11:46
连接呢?

程序在下面~

使用特权

评论回复
6
zhaoyu2005| | 2013-3-8 09:18 | 只看该作者
暂时从程序和配置上看不出问题,你的单片机型号、串口波特率、晶振频率、电路板和电脑是否共地

使用特权

评论回复
7
jiangjiajun|  楼主 | 2013-3-8 13:02 | 只看该作者
zhaoyu2005 发表于 2013-3-8 09:18
暂时从程序和配置上看不出问题,你的单片机型号、串口波特率、晶振频率、电路板和电脑是否共地 ...

单片机是STC89C52,串口波特率是9600,晶振是11.0592,这些应该都没问题,我现在怀疑串口接收一长串数据时候的接收机制是不是和我编程有什么不对的地方?

使用特权

评论回复
8
chunyang| | 2013-3-8 17:37 | 只看该作者
典型的程序编制问题,对于异步串口通讯,注意当前串口数据必须在下一字节到来前处理完毕,否则必然会丢失信号。

使用特权

评论回复
9
dqyubsh| | 2013-3-8 19:09 | 只看该作者
至少要写个带缓冲区的程序,这样弄过于简单了,在工程上难以应付。如果想稳定运行,建议参照MODBUS协议。

使用特权

评论回复
10
jiangjiajun|  楼主 | 2013-3-8 20:36 | 只看该作者
370024526 发表于 2013-3-8 17:18
这样肯定会丢失数据的

我用的是查询方式,while里面有判断RI的。

使用特权

评论回复
11
jiangjiajun|  楼主 | 2013-3-8 20:41 | 只看该作者
chunyang 发表于 2013-3-8 17:37
典型的程序编制问题,对于异步串口通讯,注意当前串口数据必须在下一字节到来前处理完毕,否则必然会丢失信 ...

也就是说如果有一串数据过来我就必须立即响应?

使用特权

评论回复
12
jiangjiajun|  楼主 | 2013-3-8 20:44 | 只看该作者
dqyubsh 发表于 2013-3-8 19:09
至少要写个带缓冲区的程序,这样弄过于简单了,在工程上难以应付。如果想稳定运行,建议参照MODBUS协议。 ...

嗯~我现在也是开始了解串口通信~刚好遇到这个问题不太明白~还有这个缓冲区是怎么开辟的?

使用特权

评论回复
13
dqyubsh| | 2013-3-8 21:28 | 只看该作者
jiangjiajun 发表于 2013-3-8 20:44
嗯~我现在也是开始了解串口通信~刚好遇到这个问题不太明白~还有这个缓冲区是怎么开辟的? ...

缓冲区实际上是实现FIFO操作。你让单片机每接受一个字节就响应一次,这不现实,效率也太低。应该是接收一包数据再分析一次。我以前用AVRLIB这个库,是基于AVR单片机的,你可以搜索一下。

使用特权

评论回复
14
jiangjiajun|  楼主 | 2013-3-8 21:54 | 只看该作者
dqyubsh 发表于 2013-3-8 21:28
缓冲区实际上是实现FIFO操作。你让单片机每接受一个字节就响应一次,这不现实,效率也太低。应该是接收一 ...

好的~谢谢~我先了解一下~有不明白的再请教您

使用特权

评论回复
15
water198617| | 2013-3-8 22:16 | 只看该作者
在while(1)前写个RI清零试试

使用特权

评论回复
16
chunyang| | 2013-3-8 22:25 | 只看该作者
jiangjiajun 发表于 2013-3-8 20:41
也就是说如果有一串数据过来我就必须立即响应?

是的,如果你的接收器本身具有硬件自动缓冲比如FIFO之类,那也要在缓冲溢出前处理完毕。

使用特权

评论回复
17
zhaoyu2005| | 2013-3-9 09:11 | 只看该作者
简单看了下程序,应该没问题,或者说从机理上说没问题。LZ采用的查询方式,一旦接收到数据,就读取数据放到数组里,然后将该数据返回,接收到6个数据后,再全部返回一次。只有返回数据地方不太合理,一直等待发送完再退出,比较合理的做法是将数据写入发送缓冲区(启动发送),然后就结束,每次发送数据前,检测上次发送是否结束。但是9600的波特率,数据的存取时间应该足够了,不应该造成丢数据,即使丢数据也不应该只接收第一个数据,其他的都丢了。
所以建议LZ加入其他指示或者通过串口发送标志数据,看看问题出在哪里,也可以用虚拟串口和模拟仿真联调,这个就和硬件仿真的差不多了,可以通过串口助手发送、接收数据,同时keil里也能看到数据和单步执行

使用特权

评论回复
18
jiangjiajun|  楼主 | 2013-3-9 09:57 | 只看该作者
water198617 发表于 2013-3-8 22:16
在while(1)前写个RI清零试试

我试过了。。还是那样

使用特权

评论回复
19
jiangjiajun|  楼主 | 2013-3-9 10:28 | 只看该作者
zhaoyu2005 发表于 2013-3-9 09:11
简单看了下程序,应该没问题,或者说从机理上说没问题。LZ采用的查询方式,一旦接收到数据,就读取数据放到 ...

我觉得返回数据的程序影响应该不大,因为我第一次给串口发送数据的时候,然后程序接收完第一个数据之后就一直死在recvbuf()函数的while(RI==0)里面,说明后面的数据都没过来,直到第二次再发送一串数据就能跳出来。

使用特权

评论回复
20
jiangjiajun|  楼主 | 2013-3-9 10:32 | 只看该作者
chunyang 发表于 2013-3-8 22:25
是的,如果你的接收器本身具有硬件自动缓冲比如FIFO之类,那也要在缓冲溢出前处理完毕。 ...

数据的发送端是不是一次性把一串数据都发送出去,只是在数据与数据之间加一个时间间隔,它也不管你SBUF里面数据有没有处理?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

20

帖子

1

粉丝