真正實現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()什麼的,這裏不要弄混了。不同從機改變一下地址編號即可。

       行吧,大體就是這樣了,希望可以幫到大家。有什麼疑問可以直接留言,我看到會及時回覆!也歡迎大家給我指正!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章