RS485一主机两个下位机,上位机通过发送下位机地址查询下位机两个按钮的状态,仿真时同时在P1口和P2口显示按钮状态
一、原理图
/* 延时t毫秒 */
void delay(uint t)
{
uint i;
while(t--)
{
/* 对于11.0592M时钟,约延时1ms */
for (i&#61;0;i<125;i&#43;&#43;)
{}
}
}
void SendCMD(unsigned char Dbyte)//UART0发送一个字节
{
RS487wr&#61;1;
TI &#61; 0;
TB8 &#61; 0; // 发送数据帧
SBUF &#61; Dbyte; // 发送长度
while(!TI);
TI &#61; 0;
}
void SendADDR(unsigned char Dbyte)//UART0发送一个字节
{
RS487wr&#61;1;
TI &#61; 0;
TB8 &#61; 1; // 发送地址帧
SBUF &#61; Dbyte; // 发送长度
while(!TI);
TI &#61; 0;
}
uchar ReciveUart(void)
{ uchar temp;
RS487wr&#61;0;
REN&#61;1;
RI &#61; 0;
while(!RI);
temp &#61; SBUF;
RI &#61; 0;
return temp;
}
void init_serial()
{ TMOD &#61; 0x20;
SCON &#61; 0xd0;
TH1 &#61; 0xfd;
TL1 &#61; 0xfd;
TR1 &#61; 1;
PCON &#61; 0x00; // SMOD&#61;0
}
/* 主程序 */
void main()
{
uchar i &#61; 0;
uchar addr_tmp;
uchar data_tmp;
init_serial(); // 串口初始化
EA &#61; 1; // 开所有中断
/* 发送地址帧并接收应答信息&#xff0c;如果接收的信号与发送的地址信息不同&#xff0c;则重新发送地址帧 */
while(1) //这段程序无效
{
addr&#61;BASE_ADDR; //下位机地址初值(第一个下位机地址)
addr_tmp &#61; addr-1;
while(addr_tmp!&#61;addr)
{
/* 发送从机地址 */
SendADDR(addr);
/* 接收从机应答 */
addr_tmp&#61;ReciveUart();
}
SendCMD(DataCMD); //给下位机发送 传输端口状态信息
data_tmp&#61;ReciveUart();//接收下位机端口信息
P1&#61; data_tmp;
addr&#61;BASE_ADDR&#43;1; //下位机地址2初值(第2个下位机地址)
addr_tmp &#61; addr-1;
while(addr_tmp!&#61;addr)
{
/* 发送从机地址 */
SendADDR(addr);
/* 接收从机应答 */
addr_tmp&#61;ReciveUart();
}
SendCMD(DataCMD); //给下位机发送 传输端口状态信息
data_tmp&#61;ReciveUart();//接收下位机端口信息
P2&#61;data_tmp;
}
}
2)下位机程序
#include "main_host.h"
/* 延时t毫秒 */
void delay(uint t)
{
uint i;
while(t--)
{
/* 对于11.0592M时钟&#xff0c;约延时1ms */
for (i&#61;0;i<125;i&#43;&#43;)
{}
}
}
void SendCMD(unsigned char Dbyte)//UART0发送一个字节
{
RS487wr&#61;1;
TI &#61; 0;
TB8 &#61; 0; // 发送数据帧
// delay(20);
SBUF &#61; Dbyte; // 发送长度
while(!TI);
TI &#61; 0;
}
void SendADDR(unsigned char Dbyte)//UART0发送一个字节
{
RS487wr&#61;1;
TI &#61; 0;
TB8 &#61; 1; // 发送地址帧
delay(20);
SBUF &#61; Dbyte; // 发送长度
while(!TI);
TI &#61; 0;
}
uchar ReciveUart(void)
{ uchar temp;
RS487wr&#61;0;
REN&#61;1;
RI &#61; 0;
// delay(20);
while(!RI);
temp &#61; SBUF;
RI &#61; 0;
// delay(20);
return temp;
}
/* 串口初始化函数 */
void init_serial()
{
TMOD &#61; 0x20;
SCON &#61; 0xd0;
TH1 &#61; 0xfd;
TL1 &#61; 0xfd;
TR1 &#61; 1;
PCON &#61; 0x00; // SMOD&#61;0
}
/* 主程序 */
void main()
{
uchar i &#61; 0;
uchar addr_tmp;
uchar data_tmp;
init_serial(); // 串口初始化
EA &#61; 0; // 关闭所有中断
/* 发送地址帧并接收应答信息&#xff0c;如果接收的信号与发送的地址信息不同&#xff0c;则重新发送地址帧 */
P0&#61;0xff;
addr&#61;P0; //下位机地址初值(第一个下位机地址)
P1&#61;addr;
/* 进入设备应答 */
while(1)
{
SM2 &#61; 1; // 只接收地址帧
/* 如果接收到的地址帧不是本机地址&#xff0c;则继续等待 */
addr_tmp &#61; addr-1;
while (addr_tmp!&#61;addr)
{
addr_tmp&#61;ReciveUart();
}
/* 发送本机地址作为应答信号&#xff0c;准备接收数据 */
SendCMD(addr);
SM2 &#61;0; ///接受命令
data_tmp&#61;ReciveUart();
if(data_tmp&#61;&#61;DataCMD)
{
SendCMD(P2);
}
else //错误信息的话进入地址监听
{
SendCMD(0xff);
}
}
} if(addr&#61;&#61;BASE_ADDR)
P1&#61; data_tmp&0x03;
else
P2&#61; data_tmp&0x03;
}
addr&#43;&#43;;
}
}
}
3)main_host.h文件程序
#ifndef _main_houst_H // 防止.h被重复引用
#define _main_houst_H
#include
#include
#define uchar unsigned char
#define uint unsigned int
/* 握手信号宏定义 */
#define DataCMD 0x55 // 接收成功
#define ERR 0xaa // 接收错误
#define BASE_ADDR 0x51 //下位机地址基址
#define LOWMCU 2 //下位机节点数量 &#xff0c;则下位机的地址范围&#xff1a;0x51~0x53
uchar addr;
#define RS485w 1
#define RS485r 0
sbit RS487wr&#61;P3^2;
sbit LED1&#61;P2^3;
#endif