OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5581|回复: 17

485多机通信问题

[复制链接]

42

主题

297

帖子

0

精华

高级会员

Rank: 4

积分
994
金钱
994
注册时间
2016-7-22
在线时间
318 小时
发表于 2017-11-28 09:32:48 | 显示全部楼层 |阅读模式
1金钱
   各位,请教一个问题,现在我用三个485设备 设备A 设备B 设备C 连接在一起,使用串口调试助手发送数据,三个设备都可以接收。
   现在我调试助手发送一条指令,让设备A,B,C分别把自己的地址发给上位机。设备在进行回复的时候,打开了串口IDLE(空闲中断),用来判断当前总线是否有其他通信,确保总线只被一个设备使用
   但是这么做还是只能收到一个设备的回复,有时候俩,都是随机的。。。。
  (前提:不知道总线上挂了多少设备,更不知设备地址。)

    请路过的大神给个思路



最佳答案

查看完整内容[请看2#楼]

设计思路请参考:主机先发送一条联机协议,下面若干台485设备(一般最大能支持到32路)同时接收,每台485设备可以各自产生一随机数,间隔N毫秒后(比如有的间隔40ms,有的间隔200ms后发出)各自带自己CID码的信息,里面带有各自唯一的CID码。 主机收到一帧协议(自己定义协议字节个数,并带有校验码)后,首先验证协议是否正确(因为还是存在有2台或若干台从机同时发送协议的可能,这样主机收到的协议经检验后肯定是不对的),若正 ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
97
金钱
97
注册时间
2014-2-10
在线时间
18 小时
发表于 2017-11-28 09:32:49 | 显示全部楼层
设计思路请参考:主机先发送一条联机协议,下面若干台485设备(一般最大能支持到32路)同时接收,每台485设备可以各自产生一随机数,间隔N毫秒后(比如有的间隔40ms,有的间隔200ms后发出)各自带自己CID码的信息,里面带有各自唯一的CID码。 主机收到一帧协议(自己定义协议字节个数,并带有校验码)后,首先验证协议是否正确(因为还是存在有2台或若干台从机同时发送协议的可能,这样主机收到的协议经检验后肯定是不对的),若正确则给发送一条配置地址的协议,所有从机收到后验证CID码是否为自己的CID码,若是就接收主机配置的地址。这样就能依次给所有的从机自动分配地址了。
下面是我的一小段程序可供参考。
void FS_BJXX(void)//^^^^发送本机信息 (包括本机的CID 共补还是分补 各个电容的容值)
{
        u8  i;
        u8  zancun=0; //8位无符号数计算校验值
        u16 zancun1=0;//累加16位CID码生成随时数种子。
        USART_TX_BUF[0]=0x68;USART_TX_BUF[1]=0x78;USART_TX_BUF[2]=0x88;//帧头为68 78 88
        for(i=0;i<12;i++)USART_TX_BUF[i+3]=idmzc_8bit[i];//12个idm字节
        USART_TX_BUF[15]=0x00;//代表共补型
        USART_TX_BUF[16]=drrz[0];USART_TX_BUF[17]=drrz[1];USART_TX_BUF[18]=0;//共补只有前两路有容值,第三个默认为0.分补才有容值。
        for(i=0;i<19;i++)zancun+=USART_TX_BUF[i];USART_TX_BUF[19]=zancun;// 最后一个字节存放CRC校验值。
        fssj_len=20;//需发送总的字节个数
        uart2_tx_SendIndex=0;//发送索引       
        for(i=0;i<6;i++)zancun1+=idmzc_16bit[i];zancun1+=SysTick->VAL;srand(zancun1);//idm累加并和当前systic计数器值累加生成种子。
        rs485_fsyszc=(rand()%50+1)*7000;//生成随机数(1-50)*70ms
        rs485_fsysbz=1;rs485_fsysjs=0;
}
回复

使用道具 举报

70

主题

6763

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
13122
金钱
13122
注册时间
2012-11-26
在线时间
3813 小时
发表于 2017-11-28 10:06:08 | 显示全部楼层
像这种硬件方式,最好不要问一句,所有机器都应答,因为有可能造成设备同时判定空闲,一起发送。至于挂了多少设备,设备地址,那是人的管理问题
回复

使用道具 举报

42

主题

297

帖子

0

精华

高级会员

Rank: 4

积分
994
金钱
994
注册时间
2016-7-22
在线时间
318 小时
 楼主| 发表于 2017-11-28 10:20:38 | 显示全部楼层
现在的问题是总线判忙,每个设备都是一样的代码,都使用空闲中断判忙,当调试助手发送命令之后,所有设备都判断到总线空闲了,所有会有一台设备随机性占用总线,其他两台设备就拿不到总线的使用权,但是串口并不知道,所以调试助手只收到一台设备的回复
回复

使用道具 举报

42

主题

297

帖子

0

精华

高级会员

Rank: 4

积分
994
金钱
994
注册时间
2016-7-22
在线时间
318 小时
 楼主| 发表于 2017-11-28 10:23:35 | 显示全部楼层
有一个新思路 使用带方向自动控制的485芯片,芯片可以自动判断总线是不是有数据,有数据 485自动置为接收状态 所以在设备发送的时候 可以保证每次只有一个设备占用总线 这也是判忙的一种方法
回复

使用道具 举报

42

主题

297

帖子

0

精华

高级会员

Rank: 4

积分
994
金钱
994
注册时间
2016-7-22
在线时间
318 小时
 楼主| 发表于 2017-11-28 10:40:02 | 显示全部楼层
主机发送广播(请求总线上设备的id):
1. A B C收到广播之后,只有一台设备可以抢到总线的使用权 进行回复 主机收到之后 保存id
2. 主机再发送广播,如果还是收到A的回复 再广播 (收到的回复是随机的)
3. 收到B的回复,保存id,再广播
4. 收到C的回复,保存id
如果不知设备数量的情况下,连续发送广播三次 如果收到的都是已经识别的id 那么搜索设备id的任务完成
回复

使用道具 举报

42

主题

297

帖子

0

精华

高级会员

Rank: 4

积分
994
金钱
994
注册时间
2016-7-22
在线时间
318 小时
 楼主| 发表于 2017-11-28 10:41:52 | 显示全部楼层
jermy_z 发表于 2017-11-28 10:06
像这种硬件方式,最好不要问一句,所有机器都应答,因为有可能造成设备同时判定空闲,一起发送。至于挂了多 ...

如果真有这种需求 那么尝试下吧
回复

使用道具 举报

70

主题

6763

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
13122
金钱
13122
注册时间
2012-11-26
在线时间
3813 小时
发表于 2017-11-28 11:04:40 | 显示全部楼层
hi我歌月徘徊 发表于 2017-11-28 10:41
如果真有这种需求 那么尝试下吧

换can吧 呵呵
学无止境
回复

使用道具 举报

42

主题

297

帖子

0

精华

高级会员

Rank: 4

积分
994
金钱
994
注册时间
2016-7-22
在线时间
318 小时
 楼主| 发表于 2017-11-28 12:29:32 | 显示全部楼层

can是抢占式的 倒是没有这个问题
但是can一帧只能8个字节 这数据量太小了,那要发送大量的话,就要分包发,收到之后再组装,也好麻烦啊~~~
我没用过,只是了解一下,can有没有像modbus那样的协议呢?
回复

使用道具 举报

36

主题

124

帖子

0

精华

初级会员

Rank: 2

积分
197
金钱
197
注册时间
2016-4-28
在线时间
263 小时
发表于 2017-11-28 13:05:14 | 显示全部楼层
可否考虑   主机呼叫A -> A发主机 -> 主机呼叫B -> B发主机 -> 主机呼叫C -> C发主机。
这样分时操作,会不会稳定性好?
回复

使用道具 举报

70

主题

6763

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
13122
金钱
13122
注册时间
2012-11-26
在线时间
3813 小时
发表于 2017-11-28 13:27:25 | 显示全部楼层
orta 发表于 2017-11-28 13:05
可否考虑   主机呼叫A -> A发主机 -> 主机呼叫B -> B发主机 -> 主机呼叫C -> C发主机。
这样分时操作,会 ...

他都不知道地址了  呼叫个毛。。。
学无止境
回复

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2017-11-28 16:13:08 | 显示全部楼层
jermy_z 发表于 2017-11-28 13:27
他都不知道地址了  呼叫个毛。。。

可以地址从1开始,一直不停的尝试
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复

使用道具 举报

7

主题

105

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1028
金钱
1028
注册时间
2016-1-28
在线时间
135 小时
发表于 2017-11-28 17:16:56 | 显示全部楼层
个人觉得这个题目本身就有问题。每台子设备如果程序都一样,都仅判断总线为空的话,就发送自己的ID的话。那几乎永远是距离最近,第一个接收到命令的子设备回复的ID。
回复

使用道具 举报

119

主题

439

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1185
金钱
1185
注册时间
2015-9-18
在线时间
422 小时
发表于 2017-11-28 18:09:17 | 显示全部楼层
对于485总线,似乎比较难办。

可以从modbus协议上得到一点经验:
modbus主机如果单独与某个modbus从机进行通信,从机需要回复主机数据。
modbus主机如果重复与多个modbus从机进行通信,从机做出相应动作,但是不用回复modbus主机数据。
电子爱好者
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2017-11-29 00:21:09 | 显示全部楼层
485通信,假设是modbus,应该有个地址范围,比如0~255,你可以从0开始轮询,一直到255,只有地址匹配的设备才应答,这样主机只要循环一次,就可以知道所有设备。虽然比较耗时间(假设50ms通信一次,那就需要256*50ms,才能轮询完)
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2017-11-29 00:21:12 | 显示全部楼层
485通信,假设是modbus,应该有个地址范围,比如0~255,你可以从0开始轮询,一直到255,只有地址匹配的设备才应答,这样主机只要循环一次,就可以知道所有设备。虽然比较耗时间(假设50ms通信一次,那就需要256*50ms,才能轮询完)
回复

使用道具 举报

42

主题

297

帖子

0

精华

高级会员

Rank: 4

积分
994
金钱
994
注册时间
2016-7-22
在线时间
318 小时
 楼主| 发表于 2017-12-1 13:23:53 | 显示全部楼层
正点原子 发表于 2017-11-29 00:21
485通信,假设是modbus,应该有个地址范围,比如0~255,你可以从0开始轮询,一直到255,只有地址匹配的设备 ...

我的回复咋丢了

重新回答下 我用的stm32的全球唯一识别码 这个范围就大了。。。
回复

使用道具 举报

42

主题

297

帖子

0

精华

高级会员

Rank: 4

积分
994
金钱
994
注册时间
2016-7-22
在线时间
318 小时
 楼主| 发表于 2017-12-1 13:32:43 | 显示全部楼层
m_ml 发表于 2017-11-30 22:19
设计思路请参考:主机先发送一条联机协议,下面若干台485设备(一般最大能支持到32路)同时接收,每台485设 ...

嗯嗯
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-11 06:10

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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