打印

关于串口接收问题

[复制链接]
2219|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
dai_22|  楼主 | 2010-5-12 11:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 dai_22 于 2010-5-12 12:05 编辑

当上位机以下面格式发送数据给下位机,下位机接收程序该怎样写才不会出现死循环?


报头

长度

逻辑地址

命令

参数内容

校验

结束符

1Byte

1Byte

1Byte

1Byte

nByte

1Byte

1Byte

固定0x40

逻辑地址开始到结束符的字节总数。

硬件4Bit拨码开关设置或由通讯设置。

参考命令列表

参考命令列表的详细数据内容

从报头开始到校验前的所有字节异或。

固定

0x0D



这是我的程序,使用了串口中断接收。
//***************************
//串行中断,接收上位机数据
//***************************
seri_int () interrupt 4 using 1
{
   unsigned char i, j;
   unsigned char rece_data = SBUF;//接收串口数据
   unsigned char verify = 0;//保存校验码
   if (RI)
   {   
       RI = 0;
       if (g_bReceBe)
      {
          i = g_cReceNum++;
         g_cReceBuf[i] = rece_data;
     }
     else
     {   
        if((g_cReceNum==0) && (rece_data==0x40))//接收协议头
        {
             g_bReceBe = 1;
             i = g_cReceNum++;
             g_cReceBuf[i] = rece_data;
        }
    }
    if ((g_cReceNum == g_cReceBuf[1] + 2) && ( g_cReceBuf[1]!= 0 )) //判断数据是否接收完
       {   
            for (j=0; j<g_cReceNum-1; j++)//校验验证码
            {   verify ^= g_cReceBuf[j];    }
            if (!verify)
           {   
                g_bReceOk  = 1;
                g_cCommand = g_cReceBuf[3];
                ES = 0;
            }
            g_bReceBe  = 0;
            g_cReceNum = 0;
        }
        if (g_cReceNum >= 24)//最长一条协议为23字节
        {
            g_cReceNum = 0;  
            g_bReceBe  = 0;
        }
    }
    else if(TI)
    { TI = 0;   }




相关帖子

沙发
ejack| | 2010-5-12 12:31 | 只看该作者
围绕着g_cReceNum的错误不少,LZ还需要慢慢修改。
另外LZ还需要考虑健壮性问题,比如说一帧中间丢了1个字节怎么处理……等等

使用特权

评论回复
板凳
dai_22|  楼主 | 2010-5-12 12:56 | 只看该作者
本帖最后由 dai_22 于 2010-5-12 12:57 编辑

LS
谢谢前辈指点,晚辈悟性低,不知g_cReceNum中的错误在哪里?

使用特权

评论回复
地板
mohanwei| | 2010-5-12 14:31 | 只看该作者
报头0x40和包尾0x0d在报文中会出现么?是否有转义?有转义的话,检测到包尾0x0d即可认为接收结束,再加上缓冲区溢出检测,可以认为是非常健壮的了。

如果没有转义,那就只能用状态机来接收了,需要很多的容错处理,做起来很麻烦。

使用特权

评论回复
5
dai_22|  楼主 | 2010-5-12 14:38 | 只看该作者
4# mohanwei
0x40和0x0d都会出现,但是没有转义。

使用特权

评论回复
6
teddeng| | 2010-5-12 15:46 | 只看该作者
不是复杂应用,原来没成功弄过多机通讯建议参考MODBUS,两种方式都简单实用。

使用特权

评论回复
7
ejack| | 2010-5-12 18:54 | 只看该作者
LZ的协议是变长的,若以目前程序无时序辅助的机制,一旦丢失字节将会影响后续帧。最恶劣情况下连续破坏4帧的接收。

使用特权

评论回复
8
ejack| | 2010-5-12 18:58 | 只看该作者
校验是否包括该字节本身?

使用特权

评论回复
9
928315| | 2010-5-12 21:20 | 只看该作者
楼主,一个字节的包头,感觉有点少。推荐一种状态机的写法
#pragma vector=USART0RX_VECTOR
__interrupt void Uart0_Rx (void)
{  
    INT8U i;
    i = RXBUF0;
       
        switch(uart0_rx_state)
        {
        case 0:
                if(i == 0xff)
                        uart0_rx_state++;
                else
                        uart0_rx_state = 0;
                break;
        case 1:
                if(i == 0x00)
                        uart0_rx_state++;
                else
                        uart0_rx_state = 0;
                break;
        case 2:
                if(i == 0x66)
                        uart0_rx_state++;
                else
                        uart0_rx_state = 0;
                break;
        case 3:
                if(i == 0x55)
                        uart0_rx_state++;
                else
                        uart0_rx_state = 0;
                break;
        case 4://SN
                uart0_rx_state++;
                break;
        case 5://SN
                uart0_rx_state++;
                break;
        case 6://SN
                uart0_rx_state++;
                break;
        case 7://SN
                uart0_rx_state++;
                break;
        case 8://CRC
                uart0_rx_state++;
                recDataNum = 0;//初始化计数
                break;
        case 9://数据
                Proc_Data(i);
                break;
        default:
                uart0_rx_state = 0;
                if(i == 0xff)
                        uart0_rx_state++;
                break;
        }
}

使用特权

评论回复
10
928315| | 2010-5-12 21:21 | 只看该作者
感觉你的IF ELSE 让我头都昏了。。。

使用特权

评论回复
11
928315| | 2010-5-12 21:29 | 只看该作者
大家还有什么写法,都探讨下啊。这种通讯协议解析很常用的啦。。。

使用特权

评论回复
12
dai_22|  楼主 | 2010-5-13 08:56 | 只看该作者
8# ejack
顶7楼,从报头开始到校验前一个字节的所有字节异或,不包括校验本身。

使用特权

评论回复
13
dai_22|  楼主 | 2010-5-13 09:03 | 只看该作者
9# 928315
谢谢你的建议,小弟悟性低,不知道这样写有什么优势,我的协议是变长的,也能这样写吗?

使用特权

评论回复
14
dai_22|  楼主 | 2010-5-13 09:07 | 只看该作者
弱弱的问一下:是不是所给的分数会影响回帖率?

使用特权

评论回复
15
yuyetufu| | 2010-5-15 16:02 | 只看该作者
弱弱的问一下:是不是所给的分数会影响回帖率?
dai_22 发表于 2010-5-13 09:07
不会,大伙儿都是无私的,不会看分数

使用特权

评论回复
16
dengm| | 2010-5-15 16:16 | 只看该作者
最好 1. 转义  2.  校验用2bytes----CRC8 + SUM8

使用特权

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

本版积分规则

0

主题

20

帖子

1

粉丝