搜索
bottom↓
回复: 33

485通讯最后一帧数据错误的疑惑,大家是怎么处理的?

[复制链接]

出0入0汤圆

发表于 2013-5-31 17:24:38 | 显示全部楼层 |阅读模式
本帖最后由 hack3er 于 2013-6-1 11:07 编辑

这里不局限于某种单片机

不知大家在调485通讯的时候有没有遇到过最后一帧数据发送错误的情况。

这种情况是接收处理后的发送数组都正确,但是发送之后会发现,最后一帧不是你预期要发送的值。
这一般是因为485的控制端切换成接收过快导致。

通常的做法是在最后一帧加一些延时。
但是我觉得,延时有很多不稳定因数在里面。

这个帖子中9楼的lcofjp讲的不错:http://www.amobbs.com/thread-5297717-1-1.html
加延时或许能解决问题,但是1.延时过短,问题不能解决,2.延时过长,浪费CPU时间。3.延时正好:那是不可能的。

最近在调485,没有用延时

我是这样处理的。
现在假设要发 20个数据。
20个数据进20次中断,
当进21次中断时,因为大于了20,所以这时候处理改485控制管脚。
按理说第21次进中断时,前20帧的数据已经发送玩了,
但是为什么在第21次中断中处理了485控制管脚后,发送后的数据最后一帧还是不对呢 ?
有点不解,想看看各位遇到这个问题,除了用延时外,是怎么处理的 ?



=============================我是低调的分割线=======================================
下面是各位网友的分析,我觉得不错,不过咱不会把他们的回复顶上楼主位, 所以就整理了一下放上面,方便后来人。。

先是Louis_Bright的分析,注意看第二点分析,Louis_Bright:


第一,这个确实是因为最后一个byte数据错误引起的,也就是485切换到接收状态过早。

第二,我们首先要明白的是:你用的单片机是几级缓冲?
比如51就只有一级缓冲,也就是当有TI标志的时候,就意味着SBUF中为空,
你可以继续往里面填写数据,如果是这种情况,485最有一个字节是不会错的,
但是,如果你监测发送信号会发现,两个byte之间会有时间间隔(也许你很快,但理论上确实存在);
现在单片机大部分采用的是二级缓冲,比如AVR,STM8,STM32,msp430。
二级缓冲会有两个中断,一个称之为“发送FIFO为空”,一个是“发送完毕”,这种二级缓冲,你监测发送信号会发现两个byte之间是没有间隔的。
在硬件处理上,我们写的寄存器是第一级缓冲,硬件会立即转存到二级缓冲,然后二级缓冲再发出去,这个时候,一级缓冲就为空了,
就会产生一个中断,你可以继续往里面填写数据,由于二级缓冲里面的数据还没有发出去,所以一级缓冲里面的数据不会立即移位到二级缓冲中,
如果二级缓冲发送完毕而一级缓冲中又没有数据,那么就会产生一个“发送完毕”的中断。

第三,对于那种有二级缓冲的单片机,解决这个485的问题就非常简单了。正常情况,发送FIFO为空就去看有没有数据要再填写,发送完毕中断就把485切换到接收状态即可(当然,实际情况,为了健壮性会写得更加完善一点)

第四,比较恶心的是有些单片机,它确实是二级缓冲,但它只有一个 发送FIFO为空的中断,这种情况处理起来就比较麻烦,我能想到的也就只有延时,但这个延时也可以做得比较精确并且效率挺高,我的做法是参考 Linux的delaywork的方法。



还有zchong网友的:

兄弟,搞清楚原因你就要去找解决办法,看手册是必须的
“完成标志”是个模糊的概念,具体是什么完成了,移位寄存器全部移出完成就不会出现你说的问题


其他网友的分析也不错,这里就不整理了,在这里感谢,想了解的可以继续看帖。。

=============================我是低调的分割线=======================================

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2013-5-31 17:40:23 | 显示全部楼层
是最后一个直接 而不是最后一帧吧
兄弟你得仔细看UART寄存器里面的标志啊 有发送完成标志啊 只有发送完成标志置位 才可以确认这个字节发送完毕啊

出0入0汤圆

 楼主| 发表于 2013-5-31 17:50:41 | 显示全部楼层
HadesHe 发表于 2013-5-31 17:40
是最后一个直接 而不是最后一帧吧
兄弟你得仔细看UART寄存器里面的标志啊 有发送完成标志啊 只有发送完成标 ...

既然用中断发送,那还需要判断这些标志?
既然进了中断,那就说明前一次已经完成。
一般查询法的时候才要判断这些标志吧。

其实,UART发出的数据应该都是对的,包括最后一帧。
这个错误应该是485切换控制管脚的时候导致的。。

出0入31汤圆

发表于 2013-5-31 18:24:57 来自手机 | 显示全部楼层
移位寄存器移完后会有标志,用这个触发中断就没问题了

出110入0汤圆

发表于 2013-5-31 18:48:59 | 显示全部楼层
用发送完成中断就OK了,这个不算问题吧

出0入0汤圆

发表于 2013-5-31 19:27:05 | 显示全部楼层
拿台示波器监视TX和EN脚,是什么问题一目了然

出0入4汤圆

发表于 2013-5-31 19:38:21 | 显示全部楼层
做协议的时候,帧头和帧尾加前导和配置字,这样错了也不怕,这几个字节就是让它错的,^_^

出0入0汤圆

 楼主| 发表于 2013-6-1 07:52:48 | 显示全部楼层
zchong 发表于 2013-5-31 18:24
移位寄存器移完后会有标志,用这个触发中断就没问题了

触发发送中断,除了完成标志外还有别的标志?
进入进了发送中断,那表示上一帧数据已经发送完成。
不知你有没有做过485。
这个问题是在485之前的数据都是对的,但是经过485后的数据会错最后一帧。。

出0入0汤圆

 楼主| 发表于 2013-6-1 08:00:44 | 显示全部楼层
Flyback 发表于 2013-5-31 18:48
用发送完成中断就OK了,这个不算问题吧

触发发送中断,除了完成标志外还有别的标志?
进入进了发送中断,那表示上一帧数据已经发送完成。
问题没有你说的这么简单吧。
这个问题是在485之前的数据都是对的,但是经过485后的数据会错最后一帧。。

出0入0汤圆

 楼主| 发表于 2013-6-1 08:01:33 | 显示全部楼层
SNOOKER 发表于 2013-5-31 19:27
拿台示波器监视TX和EN脚,是什么问题一目了然

这个的出来的结果就是发完最后一帧,你需要延时一会。。

出0入0汤圆

 楼主| 发表于 2013-6-1 08:04:27 | 显示全部楼层
chendaon 发表于 2013-5-31 19:38
做协议的时候,帧头和帧尾加前导和配置字,这样错了也不怕,这几个字节就是让它错的,^_^ ...

如果自己定协议,那还好说,但是如果做MODBUS这些标准协议呢?

出0入264汤圆

发表于 2013-6-1 08:21:48 | 显示全部楼层
hack3er 发表于 2013-6-1 08:00
触发发送中断,除了完成标志外还有别的标志?
进入进了发送中断,那表示上一帧数据已经发送完成。
问题没 ...

用发送完成中断就好了。就没有这些事情了。
发送有几个过程,一个是数据写入到串口发送数据寄存器,一个是数据从发送寄存器移位完毕,即发送完成。这两个过程都有标志产生的。
在发送完成中断或者中断中判断发送完成标志来控制收发方向以及是否写入下一个数据。

出0入31汤圆

发表于 2013-6-1 09:50:55 | 显示全部楼层
hack3er 发表于 2013-6-1 07:52
触发发送中断,除了完成标志外还有别的标志?
进入进了发送中断,那表示上一帧数据已经发送完成。
不知你 ...

兄弟,搞清楚原因你就要去找解决办法,看手册是必须的
“完成标志”是个模糊的概念,具体是什么完成了,移位寄存器全部移出完成就不会出现你说的问题

出0入0汤圆

发表于 2013-6-1 10:03:46 | 显示全部楼层
另外,可以看下是不是你的硬件电路有问题。上拉,下拉,匹配电阻,双绞线这些都弄好没

出0入0汤圆

 楼主| 发表于 2013-6-1 10:08:05 | 显示全部楼层
zchong 发表于 2013-6-1 09:50
兄弟,搞清楚原因你就要去找解决办法,看手册是必须的
“完成标志”是个模糊的概念,具体是什么完成了, ...

谢谢,确实是模糊了概念,又查了下资料,问题解决了。。

不过网上的例程几乎都是查询的方法,用发送中断的太少了,而且都是抄来抄去,确实被误导了。。。

出0入0汤圆

 楼主| 发表于 2013-6-1 10:10:34 | 显示全部楼层
mcu_mouse 发表于 2013-6-1 10:03
另外,可以看下是不是你的硬件电路有问题。上拉,下拉,匹配电阻,双绞线这些都弄好没 ...

硬件没有问题的。。

成熟的产品。。

出0入0汤圆

发表于 2013-6-1 10:10:49 | 显示全部楼层
哥知道是怎么回事,因为哥也遇到过,听哥详细道来!

出0入0汤圆

发表于 2013-6-1 10:11:43 | 显示全部楼层
第一,这个确实是因为最后一个byte数据错误引起的,也就是485切换到接收状态过早。

出0入0汤圆

 楼主| 发表于 2013-6-1 10:12:19 | 显示全部楼层
Louis_Bright 发表于 2013-6-1 10:10
哥知道是怎么回事,因为哥也遇到过,听哥详细道来!

搬个小马扎,听大师讲经。。

出0入0汤圆

发表于 2013-6-1 10:17:39 | 显示全部楼层
hack3er 发表于 2013-6-1 10:12
搬个小马扎,听大师讲经。。

那按那大哥说的,在切换485的收发的时候先等5毫秒再进行数据的操作

出0入0汤圆

发表于 2013-6-1 10:18:33 | 显示全部楼层
第二,我们首先要明白的是:你用的单片机是几级缓冲?比如51就只有一级缓冲,也就是当有TI标志的时候,就意味着SBUF中为空,你可以继续往里面填写数据,如果是这种情况,485最有一个字节是不会错的,但是,如果你监测发送信号会发现,两个byte之间会有时间间隔(也许你很快,但理论上确实存在);现在单片机大部分采用的是二级缓冲,比如AVR,STM8,STM32,msp430。二级缓冲会有两个中断,一个称之为“发送FIFO为空”,一个是“发送完毕”,这种二级缓冲,你监测发送信号会发现两个byte之间是没有间隔的。在硬件处理上,我们写的寄存器是第一级缓冲,硬件会立即转存到二级缓冲,然后二级缓冲再发出去,这个时候,一级缓冲就为空了,就会产生一个中断,你可以继续往里面填写数据,由于二级缓冲里面的数据还没有发出去,所以一级缓冲里面的数据不会立即移位到二级缓冲中,如果二级缓冲发送完毕而一级缓冲中又没有数据,那么就会产生一个“发送完毕”的中断。

出0入0汤圆

发表于 2013-6-1 10:19:37 | 显示全部楼层
发送可以采用查询法,然后再略加延时 即可解决

出0入0汤圆

发表于 2013-6-1 10:20:36 | 显示全部楼层
第三,对于那种有二级缓冲的单片机,解决这个485的问题就非常简单了。正常情况,发送FIFO为空就去看有没有数据要再填写,发送完毕中断就把485切换到接收状态即可(当然,实际情况,为了健壮性会写得更加完善一点)

出0入0汤圆

发表于 2013-6-1 10:21:30 | 显示全部楼层
Louis_Bright 发表于 2013-6-1 10:18
第二,我们首先要明白的是:你用的单片机是几级缓冲?比如51就只有一级缓冲,也就是当有TI标志的时候,就意 ...

+1                  

出0入0汤圆

发表于 2013-6-1 10:23:35 | 显示全部楼层
第四,比较恶心的是有些单片机,它确实是二级缓冲,但它只有一个 发送FIFO为空的中断,这种情况处理起来就比较麻烦,我能想到的也就只有延时,但这个延时也可以做得比较精确并且效率挺高,我的做法是参考 Linux的delaywork的方法。

出0入0汤圆

 楼主| 发表于 2013-6-1 10:48:39 | 显示全部楼层
mcu_mouse 发表于 2013-6-1 10:17
那按那大哥说的,在切换485的收发的时候先等5毫秒再进行数据的操作

工业上使用,你觉得用延时的方法可靠么?

假如遇到波特率可设置的情况,不同波特率的延时也是不同的。。

而且就如我上面提到的lcofjp网友说的那样:

加延时或许能解决问题,但是1.延时过短,问题不能解决,2.延时过长,浪费CPU时间。3.延时正好:那是不可能的。

我觉得,延时这种方法是下下策,

就如Louis_Bright朋友所分析的那样,遇到的那种“第四,比较恶心的是有些单片机,它确实是二级缓冲,但它只有一个 发送FIFO为空的中断”的时候不得已才用。。。

出0入0汤圆

 楼主| 发表于 2013-6-1 10:50:44 | 显示全部楼层
dadongleilei 发表于 2013-6-1 10:19
发送可以采用查询法,然后再略加延时 即可解决

我觉得,查询的方法没有中断的效率高。。

而且,我觉得,延时的处理方法是下下策。。

就如Louis_Bright分析的那种“第四,比较恶心的是有些单片机,它确实是二级缓冲,但它只有一个 发送FIFO为空的中断”

出0入0汤圆

 楼主| 发表于 2013-6-1 10:52:17 | 显示全部楼层
Louis_Bright 发表于 2013-6-1 10:18
第二,我们首先要明白的是:你用的单片机是几级缓冲?比如51就只有一级缓冲,也就是当有TI标志的时候,就意 ...

大师的第一,二,三,四分析的很好。

应该是遇到过这种问题后总结出来的。。

出0入0汤圆

发表于 2013-6-1 10:54:06 | 显示全部楼层
Louis_Bright 发表于 2013-6-1 10:23
第四,比较恶心的是有些单片机,它确实是二级缓冲,但它只有一个 发送FIFO为空的中断,这种情况处理起来就 ...

大师,讲下Linux的delaywork的方法吧

出0入0汤圆

发表于 2013-6-1 11:09:38 | 显示全部楼层
单片机 不上操作系统,我觉得串口发送时用查询比用中断好,接收肯定是中断了,当然这只是我的使用习惯

出0入0汤圆

 楼主| 发表于 2013-6-1 11:10:19 | 显示全部楼层
将各位不错的总结整理到了楼主位了,方便后来人。。

出0入0汤圆

发表于 2013-6-1 12:11:23 | 显示全部楼层
我是用硬件解决的,把485接成不需要使能的电路。

出0入0汤圆

发表于 2013-6-1 12:50:20 | 显示全部楼层
485半双工,发送完延时切换对系统运行影响并不大,方便易行,不同波特率可以考虑配置不同延时

出0入0汤圆

发表于 2013-6-7 16:28:16 | 显示全部楼层
1.- 硬件解决,使用收发自动控制电路。
2.- 软件解决,有TC中断就用TC中断关485_DE,没TC中断就在最后1字节发送TE中断时,开一个Timer,在Timer中断中关485_DE和Timer自身。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-13 07:19

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表