打印

请教大家--串口接收大家一般是如何写的呀?

[复制链接]
2422|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zyboy|  楼主 | 2009-5-20 23:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
串口通信的无外乎两种方式:查询和中断
例如通信协议格式:AB + LEN  + DATA1......+DATAN + SUM  

LEN (DATA1.....SUM)

SUM(AB..........DATAN)

 

1.查询方式的应用:

   

bit WaitUART()    
{
 unsigned int xdata wait_j;
   for(wait_j=0;wait_j<4000;wait_j++) 
   {          
       if(RI1==1)
          {
    ClearRI1
              return 1;
          }
   }
   return 0;
}

 

void  uart1_isr() interrupt 20  using 3                      //UART1 INTERRUPT 

    register unsigned char Redata;
 unsigned char m;
    unsigned char CheckReSum=0;
    
    EA = 0;                //disable all interrupt;

    if(!WaitUART()) goto Exit;
 Redata = SBUF1; 
    if(Redata != 0xab)           // check receive flag
    { 
     goto Exit;
    }

    if(!WaitUART()) goto Exit;
    Redata = SBUF1; 
    if(Redata == 0)   
    {
     goto Exit;
    }
    iCmddata[0]=Redata;     //data length
    
    CheckReSum = 0xef + iCmddata[0];
    for(m=1;m<iCmddata[0];m++)             
 { 
    if(!WaitUART()) goto Exit;
       Redata = SBUF1; 
       iCmddata[m] = Redata;
       CheckReSum += Redata;
 } 
      
    if(!WaitUART()) goto Exit;
    Redata = SBUF1;
    iCmddata[m] = Redata;         //sum 
    
    if(CheckReSum != iCmddata[m])   //check transdata sum
    {
   goto Exit;
 }

 ProcessOrder();

 Exit:
   EA = 1;          //enable all interrupt
}

上面查询这个方法就是感觉很耗CPU,毕竟CPU总在等数据。


2.中断方式(采用队列)

   (1)定义的一个数组用来接收数据,数据满的时候,最前面的数据会被最新的数据替换。

   (2)有两个指针,一个头指针,由用户控制,用来查找符合包格式的数据包;一个尾指针永远指向队列的末尾处

 

 如何查找:当发现头指针和尾指针不相等时,说明有新的数据,头指针向后移动,取出数据。

               (1)如果数据不符合格式,头指针回到最初的位置+1

               (2)如果数据符合格式,但未接收完,当头指针和尾指针相等,头指针返回最初的位置。

 

优点: 不占用CPU资源

缺点:  出现包误判。

问题:

   假设发送 (1)第一个包发送 AB   (错误包)

             (2)第二个包发送 AB 02 10 01  (正确包)

  队列的数据就为

               AB AB 02 10 01

 由于队列只是将接收的数据依次放在队列中,并不知道包和包间隔。当在队列取数据的时候,当取出AB后,会将后面的AB当成LEN,当取到最后值01时候,头指针会回到当初的EF头处 (认为数据没接收完),这样对第二个包就没有响应了。一直等到后面有AB个数据之后,才会再重新往后取第二个AB头。

大家是一般是怎么写的呀?谢谢!

相关帖子

沙发
耕在此行| | 2009-5-21 08:17 | 只看该作者

我来说说

如果第一字节出现AB 第二字节再从头一帧数据,那程序肯定无法判断,这是避免不了的。
但如果发一字节AB后间隔一断时间,可以用定时器限制来判断,接收到字节时开始计时,如果超过一定时间,定时器中断对接收队列指针回0。

使用特权

评论回复
板凳
zq1987731| | 2009-5-21 08:19 | 只看该作者

帧头改用2字节结构,并用状态机程序结构分析数据包内容

    或者连同帧头+长度在内简单校验一下,校验码跟在后面,最后对数据段再校验下然后才+帧尾。当然这样是比较保险的。

使用特权

评论回复
地板
zyboy|  楼主 | 2009-5-21 09:06 | 只看该作者

多谢楼上两位!两种方法都很好

我的协议是客户定制不能改,决定采纳耕在此行方法!随便想调查一下大家常用的一般是用什么方法?谢谢!

使用特权

评论回复
5
icecut| | 2009-5-21 09:59 | 只看该作者

中断发送.中断接收

使用特权

评论回复
6
myfaith| | 2009-5-21 16:04 | 只看该作者

如果AB和LEN,DATA,SUM等都是二进制,则可能

在LEN,DATA,SUM等中出现AB字符,误判为起始,解决办法是AB用二进制,后面的用ASII码,但这样速度将降低一倍.对于这个问题有何良策?

使用特权

评论回复
7
xwj| | 2009-5-21 16:16 | 只看该作者

很简单,通讯规约上要求起始字节前必须有N毫秒的空闲即可

发送数据前必须侦测总线,至少要有N毫秒空闲才允许发送

使用特权

评论回复
8
古道热肠| | 2009-5-21 16:24 | 只看该作者

过去写过查询的,发现不太可靠,要加重发机制才保险

觉得接收用中断,发送用查询较合适,发送数据的时间是有限的,接收数据是随机的.包头用1B 10.

使用特权

评论回复
9
xzq1019| | 2009-5-21 19:32 | 只看该作者

用状态机的方法可避免你说的情况

RcvState1
RcvState2
RcvState3
...

使用特权

评论回复
10
myfaith| | 2009-5-22 11:11 | 只看该作者

7楼,加空闲时间可靠吗

接收的数据也不一定就是在N毫秒内连续的啊,而且接收使用中断+对列,也无法
知道起始字节前有N毫秒
-----------------------------------
很简单,通讯规约上要求起始字节前必须有N毫秒的空闲即可 

发送数据前必须侦测总线,至少要有N毫秒空闲才允许发送
 
 

使用特权

评论回复
11
enjoy21cn| | 2009-5-24 14:36 | 只看该作者

继续观注!

继续观注!

使用特权

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

本版积分规则

101

主题

356

帖子

0

粉丝