我还需要声明一下,我是做大创的时候,需要用主机去接收不同从机上超声波传感器的信息,查了很多相关资料都没查到。有很多资料说要用modbus协议的,其实那个是工业上完整的数据通信协议,如果只是做个比赛或者项目来接收数据的话,用不到那么复杂,完全可以自己写,具体怎么写,我会在下面详细说。主要方式呢就是主机通过轮询,使对应的从机发送数据,然后主机接收。这也是我第一次写博客,希望大家多支持哈!
1、首先我需要假定你已经看过并大致了解了rs485的一些简单通讯方法,如一主一从。那么现在来说一些干货吧。485是两根线,会抑制共模误差,高电平发送数据,低电平接收,可以理解成水从高处往低处流,并且每次只能一个单片机处于高电平,但是所有处于低电平的单片机都可以接收到总线的数据。所以我们的主路线:
①我们首先给从机编好地址:0、1、2……(自己随便编就好);
②然后让主机先处于高电平,从机处低电平;
③之后主机发送某个从机的地址(比如主机想看第0个从机的信息,那就发送0)后拉低,每一个从机接收到主机发送后的数据后(比如0)和自己的地址进行对比,如果相等,拉高,把相应数据发到总线上,发完拉低;若不相等,则不动作。所以每次只会有一个从机会给主机回应消息;
④等主机接收到信息后开始询问下一个从机,若在一段时间内未收到消息则再重发该地址进行询问。
2、贴出来主机代码:
/*==========master============*/
#include
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 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()什么的,这里不要弄混了。不同从机改变一下地址编号即可。
行吧,大体就是这样了,希望可以帮到大家。有什么疑问可以直接留言,我看到会及时回复!也欢迎大家给我指正!