真正实现Arduino UNO+RS485+轮询+一主“多”从通讯,自己编辑通讯协议

关于rs485的一主多从通讯,网上浏览量比较多的几篇CSDN大部分都是说的一主一从通讯(截止到我写稿为止),如果你想让自己的单片机群真正实现一主多从,那么这篇正是你所需要的!

        我还需要声明一下,我是做大创的时候,需要用主机去接收不同从机上超声波传感器的信息,查了很多相关资料都没查到。有很多资料说要用modbus协议的,其实那个是工业上完整的数据通信协议,如果只是做个比赛或者项目来接收数据的话,用不到那么复杂,完全可以自己写,具体怎么写,我会在下面详细说。主要方式呢就是主机通过轮询,使对应的从机发送数据,然后主机接收。这也是我第一次写博客,希望大家多支持哈!

       1、首先我需要假定你已经看过并大致了解了rs485的一些简单通讯方法,如一主一从。那么现在来说一些干货吧。485是两根线,会抑制共模误差,高电平发送数据,低电平接收,可以理解成水从高处往低处流,并且每次只能一个单片机处于高电平,但是所有处于低电平的单片机都可以接收到总线的数据。所以我们的主路线:

      ①我们首先给从机编好地址:0、1、2……(自己随便编就好);

      ②然后让主机先处于高电平,从机处低电平;

      ③之后主机发送某个从机的地址(比如主机想看第0个从机的信息,那就发送0)后拉低,每一个从机接收到主机发送后的数据后(比如0)和自己的地址进行对比,如果相等,拉高,把相应数据发到总线上,发完拉低;若不相等,则不动作。所以每次只会有一个从机会给主机回应消息;

      ④等主机接收到信息后开始询问下一个从机,若在一段时间内未收到消息则再重发该地址进行询问。

      2、贴出来主机代码:

/*==========master============*/
#include <SoftwareSerial.h>
SoftwareSerial Master(10, 11); 
char val[5]={'0','0','N','N','N'};              //定义一个数组,用来将从机地址和信息匹配
char address;                                   //定义从机地址
int DE_RE=2;
 
void setup() {
  Serial.begin(9600);                         //初始化
  Serial.println("Master is ready!");
  Master.begin(38400);
  pinMode(DE_RE,OUTPUT);  
  digitalWrite(DE_RE,LOW); 
}
 
void loop() 
{ 
  for(int i = 49 ; i < 51 ; i++)              //用来对每个从机进行一次大轮询
  {
//==========发送车位序号i=============================================//
      digitalWrite(DE_RE,HIGH);               //将主机设为发送状态
      address = i;                            //给从机发地址,此时是字符式,49对应1的字符串
      Master.write(address);                  //传唤对应号码的从机
      digitalWrite(DE_RE,LOW);                //然后立马换成接收状态 
      delay(500);                             //等一下从机反应,之前没有delay, 
                                              //maste.available还没反应过来,就过去了,加个 
                                              //delay刚刚好
                                              //或许等从机加了超声波,还得调delay的时间
                                    
//==========接收车位信息到数组val里===================================//  
      while(Master.available())               //等从机把数据发过来
      { 
          val[i-49] = Master.read();          //读车位信息到数组val
      }
      delay(1000);                            //小循环
  }                                           //整个for循环结束

  for(int a = 0 ; a < 5 ; a++)                //然后把整个字符串打印出来进行观察
  {
      Serial.print(a+1);
      Serial.print(val[a]); 
  }
 
  delay(2000);                                //最后一整个过程结束后,多等两秒钟
}

  其次一主多从之间进行通讯时采用软串口,因为TX、RX要用到串口显示(此处是借鉴了一主一从博主的经验)。另外主机发完地址后,需要delay一会,要不然程序很快就会去拉低+接收,这样从机还没来得及发消息,主机就做去询问下一个了,以致于错过数据。我这里delay500那里是为了等从机的超声波传感器测数据。具体要多久可以自行测试。还有一点,这是数据通信,传的是字符,如果想传1,那还得换算成ASCII码,好像是49吧。

       3、贴出来从机代码:

/*      Slave     */
#include <SoftwareSerial.h>
SoftwareSerial Slave(10, 11);  
char val; 
int DE_RE=2;


void setup() {
  Serial.begin(38400);   
  Serial.println("Slave is ready!");
  Slave.begin(38400); 
  pinMode(DE_RE,OUTPUT);   
  digitalWrite(DE_RE,LOW);
  
}

void Distance_test()      // 量出前方距离 
{
  //pass
}  

void loop() 
{  
  while(Slave.available()) 
  {
    val = Slave.read();         //在rs485中读串口
    Serial.write(val);          //把地址写到串口中去
    if(val=='1')                //如果确定为自己的地址
    {
      Distance_test();          //测距离
      digitalWrite(DE_RE,HIGH); //拉高
      if(Distance < 35)   
      Slave.write("Y");         //判断
      else Slave.write("N");    //判断
    }
  } 
}

主从机之间读取信息是master.read、master.available、Slave.read、Slave.available,而串口的都是Serial.read()什么的,这里不要弄混了。不同从机改变一下地址编号即可。

       行吧,大体就是这样了,希望可以帮到大家。有什么疑问可以直接留言,我看到会及时回复!也欢迎大家给我指正!

发布了9 篇原创文章 · 获赞 16 · 访问量 6622

猜你喜欢

转载自blog.csdn.net/weixin_38133509/article/details/83578518