打印
[51单片机]

通讯时如何判断接收到的是帧头还是中间数据?

[复制链接]
8152|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
any_014|  楼主 | 2015-5-26 16:46 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 any_014 于 2015-5-26 16:56 编辑

再做个51modbus从机设备,基本上只接受03命令吗。
自己是这么写的:
首先判断帧头标志,如果没有接收到帧头,则先判断接收到的字节是否是帧头?是的话,置个标志位;
接受下个字节时,仍做帧头标志判断,因为已经置位了,所以直接放到后面的数组里;
问题是:
帧头比如是01,发一串数,中间也有用01,那么我接收的时候,就有时正确有时错位。
比较奇怪的是:
发一串数,明明应该判断第一个字节是否帧头,可碰到的大部分是判断中间接收到的字节是否是帧头,然后把先接收到的数循环到后面去了。

看了两个51modbus的。
一个是本论坛吴鉴鹰老师帖子里的modbus例子,他是接受8个字节,然后统一处理。
另一个是先到的显控的51modbus例子,用个定时器做超时判断。
uchar Rece_buf[20];
uchar Send_buf[10];
/**********************串口接收处理****************************/
//站号 | 命令 | 首地址 | 字节数 | 校验高低
//01    | 03    | 00 00  | 00 01   | 0A 84
void Rx_Process(void)
{
        uint crc_end, data_len, send_len;
        SendData(0x33);
        SendData(Rece_buf[0]);
        SendData(Rece_buf[1]);
        SendData(Rece_buf[2]);
        SendData(Rece_buf[3]);
        SendData(Rece_buf[4]);
        SendData(Rece_buf[5]);
        SendData(Rece_buf[6]);
        SendData(Rece_buf[7]);
        if(0x03 == Rece_buf[1])
        {
                SendData(0x55);
               
                crc_end = crc16(Rece_buf, 6);
                if(crc_end == (Rece_buf[6]<<8 | Rece_buf[7]))
                {
                        begin_address = Rece_buf[2]<<8|Rece_buf[3];
                        data_len = Rece_buf[4]<<8|Rece_buf[5];
                        Send_buf[0] = Rece_buf[0];
                        Send_buf[1] = Rece_buf[1];
                        Send_buf[2] = data_len*2;
                        for(send_len = 0; send_len < data_len*2; send_len++)
                        {
                                if(!(send_len%2))
                                        Send_buf[send_len+3] = temp_value / 256;
                                else
                                        Send_buf[send_len+4] = temp_value % 256;
                        }
                        crc_end = crc16(Send_buf, send_len + 3);
                        Send_buf[send_len + 3] = crc_end % 256;
                        Send_buf[send_len + 4] = crc_end >> 8;
//                        Send_word(Send_buf, data_len*2 + 5);
                }
        }
}

我现在是让单片机把接收到的数据直接发回来。
电脑发送:03 00 00 00 01 0A 84 电脑接收:33 01 0A 84 03 00 00 00 01 (33是我为了区分加上的)
-------------------------------------------------------------------
晕,发现自己发错了,少发一位...


相关帖子

沙发
whtwhtw| | 2015-5-26 16:55 | 只看该作者
自己定义协议呀,比如接收到帧头01,然后把后面固定长度字节作为数据存入数据缓冲区,这样作为一帧数据;然后再监测帧头。

使用特权

评论回复
板凳
any_014|  楼主 | 2015-5-26 17:24 | 只看该作者


单片机串口接高速光耦隔离,然后是RS485电路。单片机串口也预留排针插口,方便调试。
现在是用电脑发命令经RS232转TTL连到单片机串口,发送接收正确;
通过RS485口经高速光耦到单片机串口,返回来的数是00...

发现用串口时,平时没接受数据时,RX是高电平,有效信号过来后,才被拉低;
街上RS485总线后,总线上AB差在无有效信号时,也被拉开,貌似是A>B,这样485芯片接收管脚输出低电平,光耦导通,单片机那侧RX管脚被拉低。虽然RS485收发时,RX管脚也有规整的高低电平,但TX出来的不对。

使用特权

评论回复
地板
my8804| | 2015-5-26 17:25 | 只看该作者
通信协议没有定好!

使用特权

评论回复
5
ayb_ice| | 2015-5-26 17:26 | 只看该作者
一般先判断帧头,后面接收有效负载数据,然后重新开始

有效负载数据中间不考虑帧头,

如果命令有限,可以直接发送ASCII字符串,挺方便的,而且直观,比如“START”,“STOP”,

使用特权

评论回复
6
any_014|  楼主 | 2015-5-26 17:39 | 只看该作者
接收数据错位问题已解决。
是我同电脑发数的时候少发了一个字节,把站号落了,当然是按中间接收到的01做帧头了...
处理部分应该还是有问题,中间接收到01当作帧头,这帧剩下部分已不够8个字节了,结果到下一帧时把帧头放到后面去了。确实应该加上超时判断功能。

现在的问题貌似是硬件问题了。就是RS485总线平时总是高电平,这样单片机的RX管脚一直被拉低。我现在用TTL电平直接控制单片机串口收发是正确的。
用RS485电路的话,发回来的数是33 00 00 00 00....就是单片机接收错误,全是0了。

使用特权

评论回复
7
ningling_21| | 2015-5-26 17:42 | 只看该作者
any_014 发表于 2015-5-26 17:39
接收数据错位问题已解决。
是我同电脑发数的时候少发了一个字节,把站号落了,当然是按中间接收到的01做帧 ...

电路的问题

使用特权

评论回复
8
any_014|  楼主 | 2015-5-27 10:41 | 只看该作者

是我AB搞烦了。
以前都是从左到右,D-D+,这次画图能成了D+D-了。

使用特权

评论回复
9
chunyang| | 2015-5-27 12:16 | 只看该作者
帧头应该采用至少两字节,这样重合的几率就会大幅下降,同时配合严格的通迅协议,就算遇到巧合也不会有错误反应。建议去看看Modbus协议规范。

使用特权

评论回复
10
diweo| | 2015-5-27 12:38 | 只看该作者
本帖最后由 diweo 于 2015-5-27 12:40 编辑
any_014 发表于 2015-5-26 17:39
接收数据错位问题已解决。
是我同电脑发数的时候少发了一个字节,把站号落了,当然是按中间接收到的01做帧 ...

我的格式是这样的:帧头+D0+D1..+CRC+帧尾。
因为协议是我自己定的。所以收到帧头就可以判断剩下应该接收多少字节.把收到的数据重新计算CRC,与收到的CRC作比较,如果匹配,则继续处理数据。如果不匹配,则丢弃整朕内容,并复位相关标记位。
如果因为某种原因,帧头夹到中间了。那么剩下的n个字节,肯定CRC不匹配。接下来的m个数据,因为不是帧头,所以也丢弃。直到下一个帧头出现,就又是新的循环了。

加入超时功能当然也是可以的。
还可以用转义字符。就是说如果内容中间的字符刚好是帧头字符,那要在它前面加一个特定的转义字符。

使用特权

评论回复
11
fruitbee| | 2015-5-27 13:28 | 只看该作者
modbus规范有ASCII模式的

使用特权

评论回复
12
yangxf1217| | 2015-5-27 13:43 | 只看该作者
讨论的不错,学习了。

使用特权

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

本版积分规则

17

主题

132

帖子

3

粉丝