求助多个51单片机串口通讯问题

时间:2022-11-10 17:55:51
各位大虾,我现在想用一个51单片机做主机,很多51单片机做从机,将从机的TX和RX串联起来做成一个串口总线,连接在主机的串口引脚上,不知道一个主机能带多少从机(越多越好,需求大概是50个上下)。

20 个解决方案

#1


TX和RX串联起来?用RS485,并联。9位数据。

#2


因为我需要传输的数据很少,只是一个信号,主要是要求高可靠性,不知用什么结构可靠性高一点,请稍微说具体一点,谢谢

#3


只是一个 什么信号

#4


就是一个字节0或者1
之后从机再反馈一个信号0或者1

#5


主机先发信号然后从机反馈?每次只跟一个从机通讯?主机与从机距离多少?

#6


是主机先发信号然后从机反馈,每次只跟一个从机通讯,主机与从机距离1米以内,主要是从机数量过多,可能有100个,所以我比较担心

#7


1、建议用RS485来实现1主多从的通信形式,联机数量由RS485芯片允许的数量决定,大多支持32个或64个从机。在有的工程项目中,我甚至测试过一个参数32从机的MAX485芯片连接了96个从机,性能还非常稳定,但是不建议这么做。
2、在成本严格限制的情况下,可以采用主机TxD连接每个从机的RxD,每个从机的TxD通过1N4148等二极管连接到主机的RxD,连接数量由主机TxD驱动能力来确定。
3、1主多从模式下,采用轮询的方式不停检测从机状态,完成主机和从机之间的信息交换,具体处理方法类似于令牌环网的工作原理。
4、系统的可靠性可以通过设计较为完善的通信协议来保证,如错误重发机制,还有校验机制等。大多数情况下,能够保证通信的成功率,而且当协议有一定复杂度的时候基本可以保证没有错误。

#8


建议采用I2C总线来做,直接连接时钟和数据总线,做好抗干扰

#9


呵呵 有创意 关注!

#10


7楼相当不错

#11


感觉用RS485来做程序应该很好写,就是硬件方面的抗干扰问题哪位提点一下。

#12


如果仅仅读取一个电平,距离很近,不考虑扩展的话,没有必要做一个通信协议,
如果主从机共地,直接把电平线引过去也应该可以的,主机用一个cpld汇总,
至于可靠性的要求,采用软件延时防抖的办法多次读取就可以,

上一个通信协议,软件的复杂程度会增加,而且主机轮询50个从机的时间也很长,实时性不好。。。

#13


好。。。。。。。。。。。。。

#14


can咋样?

#15


不懂,学习。。。

#16


引用 7 楼 nut_cz 的回复:
1、建议用RS485来实现1主多从的通信形式,联机数量由RS485芯片允许的数量决定,大多支持32个或64个从机。在有的工程项目中,我甚至测试过一个参数32从机的MAX485芯片连接了96个从机,性能还非常稳定,但是不建议这么做。
2、在成本严格限制的情况下,可以采用主机TxD连接每个从机的RxD,每个从机的TxD通过1N4148等二极管连接到主机的RxD,连接数量由主机TxD驱动能力来确定。
……


赞一个,兄弟看来入行很久了,从我的测试经验来说,使用数据报文格式加上校验和主机控制通信模式,出错率非常的低,但是通信速度也随着从机的增加而降低很厉害。

#17


其实可以从通讯数据包和数据协议着手,这样支持多少个从机都不是问题。
这个有两种方案:
1、被动式请求处理
   完全由主机决定与哪个从机通讯或哪个从机与从机之间的通讯。这个较为简单
2、主动试请求处理
   由从机主动向主机提出通讯申请,然后等待主机分配任务。这个就涉及到比较复杂的数据包交换过程,
   逻辑上稍微有点复杂。不过效率和能源损耗上要比上一个方案强,特别是用到太阳能和无限通讯领域。

其实无论是哪个方案,都是基于数据包和数据包的校验重发过程,关键在任务的委派和任务的队列处理部分。
比如我用个简单的数据包来说明:
0xB2   //数据包头,固定的
0x01   //机号,这里用 1 个字节,意思说支持256个机号,换做2字节、4字节、6字节(可以是MAC地址了)
0x01   //命令,这里用 1 个字节,当然可以更多,不过通常够256个任务命令已经很多了
0x00   //参数1,根据不同的命令设置不同的参数长度或个数
0x00   //参数2
0x00   //参数3
0x00   //参数4
0xB2   //异或校检码,简单的话用异或校检数据包就可以了,当然也可以用CRC16或CRC32等方法,自己喜欢
0xB3   //数据包结尾

当有了完整的数据包结构,做数据包分析和弃包处理就是很简单的事了,即使再多的从机,
只要判断机号不是自己的,就做弃包处理,只有机号与自己的相同才去处理这个包的数据。
下面是个大致的数据包分析过程

void COM_Event () interrupt 4 
{
BYTE dat = 0;
if(RI == 1)
{
dat = SBUF;
RI = 0;
switch(Approach){
case 0: //根据步骤,等待包头的出现,若不是包头数据就继续等待包头
if(dat==0xB2){
Approach = 1;
dataXOR = 0xB2;
}else{
Approach = 0;
}
break;
case 1: //根据步骤,判断机号是否与自己的一致
if(dat==P1){   //P1是机号的IO口
Approach = 2;
dataXOR = dataXOR ^ dat;
}else{
//弃包
Approach = 0;
}
break;
//... 以下步骤省略 ....
case 200: //接收异或校检码
NowXOR = dat;
if(dataXOR!=NowXOR){
Approach = 0;
}else{
Approach = 201;
}
break;
case 201: //接收包尾
if(dat==0xB3){
//操作过程在主程序中执行,这里是设置执行过程的参数
//当这个参数为1时主程序的执行过程才开始运作
IsReadOver = 1;
}else{
IsReadOver = 0;
}
Approach = 0;
break;
}
}else{
TI = 0;
}
}


#18


参考DALLAS的单总线原理!1wire

#19


8楼的方法可行

#20


asdfghjkl;'

#1


TX和RX串联起来?用RS485,并联。9位数据。

#2


因为我需要传输的数据很少,只是一个信号,主要是要求高可靠性,不知用什么结构可靠性高一点,请稍微说具体一点,谢谢

#3


只是一个 什么信号

#4


就是一个字节0或者1
之后从机再反馈一个信号0或者1

#5


主机先发信号然后从机反馈?每次只跟一个从机通讯?主机与从机距离多少?

#6


是主机先发信号然后从机反馈,每次只跟一个从机通讯,主机与从机距离1米以内,主要是从机数量过多,可能有100个,所以我比较担心

#7


1、建议用RS485来实现1主多从的通信形式,联机数量由RS485芯片允许的数量决定,大多支持32个或64个从机。在有的工程项目中,我甚至测试过一个参数32从机的MAX485芯片连接了96个从机,性能还非常稳定,但是不建议这么做。
2、在成本严格限制的情况下,可以采用主机TxD连接每个从机的RxD,每个从机的TxD通过1N4148等二极管连接到主机的RxD,连接数量由主机TxD驱动能力来确定。
3、1主多从模式下,采用轮询的方式不停检测从机状态,完成主机和从机之间的信息交换,具体处理方法类似于令牌环网的工作原理。
4、系统的可靠性可以通过设计较为完善的通信协议来保证,如错误重发机制,还有校验机制等。大多数情况下,能够保证通信的成功率,而且当协议有一定复杂度的时候基本可以保证没有错误。

#8


建议采用I2C总线来做,直接连接时钟和数据总线,做好抗干扰

#9


呵呵 有创意 关注!

#10


7楼相当不错

#11


感觉用RS485来做程序应该很好写,就是硬件方面的抗干扰问题哪位提点一下。

#12


如果仅仅读取一个电平,距离很近,不考虑扩展的话,没有必要做一个通信协议,
如果主从机共地,直接把电平线引过去也应该可以的,主机用一个cpld汇总,
至于可靠性的要求,采用软件延时防抖的办法多次读取就可以,

上一个通信协议,软件的复杂程度会增加,而且主机轮询50个从机的时间也很长,实时性不好。。。

#13


好。。。。。。。。。。。。。

#14


can咋样?

#15


不懂,学习。。。

#16


引用 7 楼 nut_cz 的回复:
1、建议用RS485来实现1主多从的通信形式,联机数量由RS485芯片允许的数量决定,大多支持32个或64个从机。在有的工程项目中,我甚至测试过一个参数32从机的MAX485芯片连接了96个从机,性能还非常稳定,但是不建议这么做。
2、在成本严格限制的情况下,可以采用主机TxD连接每个从机的RxD,每个从机的TxD通过1N4148等二极管连接到主机的RxD,连接数量由主机TxD驱动能力来确定。
……


赞一个,兄弟看来入行很久了,从我的测试经验来说,使用数据报文格式加上校验和主机控制通信模式,出错率非常的低,但是通信速度也随着从机的增加而降低很厉害。

#17


其实可以从通讯数据包和数据协议着手,这样支持多少个从机都不是问题。
这个有两种方案:
1、被动式请求处理
   完全由主机决定与哪个从机通讯或哪个从机与从机之间的通讯。这个较为简单
2、主动试请求处理
   由从机主动向主机提出通讯申请,然后等待主机分配任务。这个就涉及到比较复杂的数据包交换过程,
   逻辑上稍微有点复杂。不过效率和能源损耗上要比上一个方案强,特别是用到太阳能和无限通讯领域。

其实无论是哪个方案,都是基于数据包和数据包的校验重发过程,关键在任务的委派和任务的队列处理部分。
比如我用个简单的数据包来说明:
0xB2   //数据包头,固定的
0x01   //机号,这里用 1 个字节,意思说支持256个机号,换做2字节、4字节、6字节(可以是MAC地址了)
0x01   //命令,这里用 1 个字节,当然可以更多,不过通常够256个任务命令已经很多了
0x00   //参数1,根据不同的命令设置不同的参数长度或个数
0x00   //参数2
0x00   //参数3
0x00   //参数4
0xB2   //异或校检码,简单的话用异或校检数据包就可以了,当然也可以用CRC16或CRC32等方法,自己喜欢
0xB3   //数据包结尾

当有了完整的数据包结构,做数据包分析和弃包处理就是很简单的事了,即使再多的从机,
只要判断机号不是自己的,就做弃包处理,只有机号与自己的相同才去处理这个包的数据。
下面是个大致的数据包分析过程

void COM_Event () interrupt 4 
{
BYTE dat = 0;
if(RI == 1)
{
dat = SBUF;
RI = 0;
switch(Approach){
case 0: //根据步骤,等待包头的出现,若不是包头数据就继续等待包头
if(dat==0xB2){
Approach = 1;
dataXOR = 0xB2;
}else{
Approach = 0;
}
break;
case 1: //根据步骤,判断机号是否与自己的一致
if(dat==P1){   //P1是机号的IO口
Approach = 2;
dataXOR = dataXOR ^ dat;
}else{
//弃包
Approach = 0;
}
break;
//... 以下步骤省略 ....
case 200: //接收异或校检码
NowXOR = dat;
if(dataXOR!=NowXOR){
Approach = 0;
}else{
Approach = 201;
}
break;
case 201: //接收包尾
if(dat==0xB3){
//操作过程在主程序中执行,这里是设置执行过程的参数
//当这个参数为1时主程序的执行过程才开始运作
IsReadOver = 1;
}else{
IsReadOver = 0;
}
Approach = 0;
break;
}
}else{
TI = 0;
}
}


#18


参考DALLAS的单总线原理!1wire

#19


8楼的方法可行

#20


asdfghjkl;'

#21