搜索
bottom↓
回复: 29

485总线竞争的问题(江湖救急)

[复制链接]

出0入0汤圆

发表于 2017-3-22 14:23:58 | 显示全部楼层 |阅读模式
最近在采用轮训的方式采用一主多从的模式(探寻或者点叫),本不应该出现总线的竞争问题,但是还是出现了,数据不能被主机呼叫时,立刻回来数据,要等到下次呼叫该从机,才会把上次数据传过来,这样的现象程序逻辑上应该做和判断,请前辈不吝赐教。
主机端该如何延长超时判断?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

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

如果想吃一顿饺子,就得从冰箱里取出肉,剁馅儿,倒面粉、揉面、醒面,擀成皮儿,下锅……
一整个繁琐流程,就是为了出锅时那一嘴滚烫流油的热饺子。

如果这个过程,禁不住饿,零食下肚了,饺子出锅时也就不香了……《非诚勿扰3》

出0入0汤圆

发表于 2017-3-22 14:25:37 | 显示全部楼层
協議沒做好?Modbus 加 CRC校驗應該不會出現這樣的情況。

出0入42汤圆

发表于 2017-3-22 14:29:20 | 显示全部楼层
这是你从机的程序问题了,
要把从机通讯优先级适当提高,程序一定不能写成阻塞的
不然几百个从机的网络还怎么用
主机超时根据实际波特率和从机响应速度来决定,不能无限制的等下去,通讯效率很重要的

出0入0汤圆

 楼主| 发表于 2017-3-22 16:14:22 | 显示全部楼层
ccstc 发表于 2017-3-22 14:29
这是你从机的程序问题了,
要把从机通讯优先级适当提高,程序一定不能写成阻塞的
不然几百个从机的网络还怎 ...

谢谢前辈,确实是从机的问题,我从机处理的数据比较多,但是我不知道该如何下手修改;另附从机的代码(它是在接收中断里发送的数据我觉得这种方式也不太好,但是没有更好的替代方法?)求更好的处理方法


#pragma interrupt_handler uart0_rx_isr:iv_USART0_RXC
void uart0_rx_isr(void)                                //接收中断
{
unsigned char ERROR=0;
if( UCSRA&4 || UCSRA&16 ) ERROR=1;         //记录奇偶效验错误或者帧错误 0x04 = 0000 0100  0x10 = 0001 0000
inbox[n]=UDR;                                         //把接收到的数据保存到收件箱
n++;                                                       //记忆接收的次数
if(ERROR)                                                 //如果通讯有错....
{
  n=0;                                                      //接收计数清0
  inbox[0]=0;                                            //把地址改为无效地址0
  UCSRA|=0x01;                                        //重新打开接收器的地址帧筛选功能
}

//如果地址匹配本机或者是广播地址就关闭地址筛选(多机通讯)功能
if(inbox[0]==address ||inbox[0]==255) UCSRA&=254;      //254=0xfe =1111 1110
if(n==amount)                                                             //接收到amount个数据以后...
{
  n=0;                                                                          //接收计数清0
  UCSRA|=0x01;                                                            //重新打开接收器的地址帧筛选功能
  if(inbox[amount-1]==crc8(inbox,amount-1))                   //如果crc8校验正确就...
  {
   if(inbox[0]==address)                                                 //如果地址匹配本机就回复数据
   {
    send[0]=1;                                                               //发件箱地址指向主机
        send[2]=Read_KeyBoard();                                      //获取按键的操作
    send[amount-1]=crc8(send,amount-1);                         //产生发件箱的crc8校验码
        usart_out(send,amount);                                         //发送发件箱的数据包send[]
                                                                                   //请在这里备份你的收件箱信息
   }
   if(inbox[0]==255)                                                      //如果是广播地址就...
   {
    //请在这里添加你的代码
    //收到广播数据请不要回复
   }
  }
}
}

出0入0汤圆

 楼主| 发表于 2017-3-22 16:28:16 | 显示全部楼层
ccstc 发表于 2017-3-22 14:29
这是你从机的程序问题了,
要把从机通讯优先级适当提高,程序一定不能写成阻塞的
不然几百个从机的网络还怎 ...

但是如果系统只有一个主机和一个从机的时候 就可以做到实时收发,就是发送就会有接收。

出0入0汤圆

发表于 2017-3-22 16:29:56 | 显示全部楼层
用状态机啊

出0入42汤圆

发表于 2017-3-22 16:36:36 | 显示全部楼层
这下位机的程序太糟糕了。把处理程序放到大循环里面,中断只负责接收数据。连发送数据都在接受中断里处理,我汗。另外要做一个串口超时复位,要不万一出现一次错误,你的程序要等待老天安排重来。

出0入42汤圆

发表于 2017-3-22 17:01:48 | 显示全部楼层
像楼上说的:
1、中断做最少的事情,主要任务放在主函数里
2、多用状态标识(状态机),不要让CPU等待,尤其是没有最长时间限制的等待
3、关于你的“从机处理的数据比较多”,计算你的最长工作循环,如果确实超出你的一帧数据长度了,要么降低通信速率,要么提高工作主频

出0入0汤圆

发表于 2017-3-22 17:18:34 | 显示全部楼层
程序的问题 超时这个问题 是主机要做的 从机要做的就是几层判断与及时回传数据

出0入0汤圆

发表于 2017-3-22 17:40:45 | 显示全部楼层
如果从机工作太复杂造成时间很长或者时间不定的话,可以定协议的时候有忙状态,查询的时候返回忙状态,主机来决定过多少时间再次查询。

出0入0汤圆

 楼主| 发表于 2017-3-23 08:34:20 | 显示全部楼层

请教前辈一下状态机的思路,我扫描按键是用马老师的状态机,但是485多机通信用状态机的思路前辈可否指点一二?

出0入0汤圆

 楼主| 发表于 2017-3-23 08:37:02 | 显示全部楼层
n0831 发表于 2017-3-22 16:36
这下位机的程序太糟糕了。把处理程序放到大循环里面,中断只负责接收数据。连发送数据都在接受中断里处理, ...

受教了,我今天会修改,但是串口超时的思路,前辈可以说一下嘛?

出0入42汤圆

发表于 2017-3-23 08:41:17 | 显示全部楼层
ywlzh 发表于 2017-3-22 17:18
程序的问题 超时这个问题 是主机要做的 从机要做的就是几层判断与及时回传数据 ...

丛机也要超时判断的,比如收到一幀数据的中间,上位机不传了。这就需要超时处理。

出0入0汤圆

 楼主| 发表于 2017-3-23 08:44:59 | 显示全部楼层
ccstc 发表于 2017-3-22 17:01
像楼上说的:
1、中断做最少的事情,主要任务放在主函数里
2、多用状态标识(状态机),不要让CPU等待,尤 ...

真的很感谢前辈的指点,对于1、2、这两点我能理解,但是如何得知我从机最大循环时间?我用的ICCAVR的编译环境,芯片是ATmega16的片子,这个我不知道如何获取从机一个循环的时间。烦请您给细说一下,谢谢!

出0入8汤圆

发表于 2017-3-23 08:47:46 | 显示全部楼层
在接收中断里发送数据确实不妥哦

出0入213汤圆

发表于 2017-3-23 09:06:43 来自手机 | 显示全部楼层
从机回应超时就让从机取消此次发送

出0入0汤圆

 楼主| 发表于 2017-3-23 11:07:34 | 显示全部楼层
pillar2060 发表于 2017-3-22 16:28
但是如果系统只有一个主机和一个从机的时候 就可以做到实时收发,就是发送就会有接收。 ...

发两次收一次的原因是因为第一次是寻址,第二次是要数据?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入85汤圆

发表于 2017-3-23 13:13:41 | 显示全部楼层
主机查询一个从机,一个从机都没回应正常就查询下个从机了?

出0入0汤圆

发表于 2017-3-23 13:15:08 | 显示全部楼层
8楼说的太好了,尤其是最后说的超时处理,需要你较精确的计算的,我是感觉这里比较麻烦些

出0入0汤圆

 楼主| 发表于 2017-3-23 14:41:36 | 显示全部楼层
marshallemon 发表于 2017-3-23 13:13
主机查询一个从机,一个从机都没回应正常就查询下个从机了?

现在的现象是这样的,但是只有一个从机的时候就能够做到实时发送,这个是为什么?

出0入0汤圆

 楼主| 发表于 2017-3-23 14:42:15 | 显示全部楼层
mvpgpz 发表于 2017-3-23 13:15
8楼说的太好了,尤其是最后说的超时处理,需要你较精确的计算的,我是感觉这里比较麻烦些 ...

前辈可以给我分享一下,超时判断的思路吗?

出0入22汤圆

发表于 2017-3-23 21:33:59 来自手机 | 显示全部楼层
处理数据较多,可以尝试用空闲cpu时间处理好,放在缓冲区里面,主机查询的时候,直接从缓冲区读取即可。另外,状态机就是多用if,不要用delay

出0入42汤圆

发表于 2017-3-23 21:39:04 | 显示全部楼层
关于时间的计算,基本就两个方法:
1、仿真,根据两次中断间的cpu计数差和主频计算出来
2、在用一个空闲IO做状态输出,用示波器测量

出0入476汤圆

发表于 2017-3-23 23:03:32 | 显示全部楼层
485总线冲撞的话很容易烧片子,注意!

出0入0汤圆

发表于 2017-3-24 08:59:55 | 显示全部楼层
主机要求从机响应速度快,但从机实际响应速度慢,这就是明显的矛盾

解决好其中一方即可,比如主机加上超时等待从机作相应,超时再重发第二帧

出0入17汤圆

发表于 2017-3-24 11:23:06 | 显示全部楼层
1. 协议太弱了,假如丢了第一个字节,以后的判断都错。同步字,长度,校验等都需要有
2. 如上面各位说的,接收中断里尽量简单,负责接收数据并置标志位。主循环里面,发现标志位有效,则应答

出0入0汤圆

发表于 2017-3-25 11:21:30 | 显示全部楼层
搭车问一下,如何避免 一个从机485模块损坏造成的整个总线挂掉.

出0入0汤圆

发表于 2017-3-31 21:22:40 | 显示全部楼层
本帖最后由 thomascao 于 2017-3-31 21:31 编辑

1,主机
  发送完1条完整查询指令后,开定时中断(在不影响主机功能前提下,再根据从机回复数据需要的时间,进行确定时间)用于判断数据回复超时
  如超时再查询几次,到达查询上限次数后还无回复数据,判断节点故障。作相应提醒等处理。
2,从机
  回复数据时最好有适当延迟 再回复,接收完一条有效指令开定时中断,
  指令处理超时要判断,要和主机的超时判断一致或略小。
  准备回复时查是否已过延迟,且没超时。没到延迟等延迟到再回复数据,超时等下条有效指令再回复。刚好过延迟且没超时 立即回复。

下面这些语句不要放中断里
crc8(inbox,amount-1)) CRC校验比较耗时
Read_KeyBoard(); 怀疑里边有消颤语句 耗时
usart_out(send,amount);  回复更加不要放接收中断里
if(inbox[amount-1]==crc8(inbox,amount-1))                   //如果crc8校验正确就...
  {
   if(inbox[0]==address)                                                 //如果地址匹配本机就回复数据
   {
    send[0]=1;                                                               //发件箱地址指向主机
        send[2]=Read_KeyBoard();                                      //获取按键的操作
    send[amount-1]=crc8(send,amount-1);                         //产生发件箱的crc8校验码
        usart_out(send,amount);                                         //发送发件箱的数据包send[]
                                                                                   //请在这里备份你的收件箱信息
   }
   if(inbox[0]==255)                                                      //如果是广播地址就...
   {
    //请在这里添加你的代码
    //收到广播数据请不要回复
   }

出500入109汤圆

发表于 2017-3-31 22:55:31 来自手机 | 显示全部楼层
从机接受中断加时间戳,发送的时候判断,超时了就取消发送,稳健的通信需要很多地方都要做处理
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-3-28 23:55

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

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