标签: 通讯工作date存储2010
2011-10-01 16:32 1140人阅读 收藏 举报
单片机多机通讯
http://blog.163.com/tianya6789@126/blog/static/140604136201061944057423/
说明:该程序为多机通讯程序,最多可以挂255个从机。
该程序主机发送端与多个从机的接收端相接,主机的接收端与多个从机的发送端相接。
该程序主要的目的为给从机发送作为命令的数据。
该程序调试成功,从机可正确接收。
//=====================================================================
// 多机通讯主机程序
//zhuji.c
//writer:谷雨 2008年3月22日于EDA实验室
//注:主机先发送地址,接收到应答后,再发送数据
//=====================================================================
#include
#define unit unsigned int
#define uchar unsigned char
#define addr1 0x31 //从机1地址
#define addr2 0x32 //从机2地址
void Uart_Init(void)
{
TMOD=0x20; //定时器T1使用工作方式2
TH1=250;
TH0=250;
TR1=1; //开始计时
PCON=0x80; //SMOD=1;
SCON=0xd0; //工作方式3,9位数据位,波特率9600bit/s,允许接收
TI=1;
RI=1;
}
uchar Receive(void) //接收数据程序
{
uchar Data;
while(!RI); //等待接受完毕
Data=SBUF; //接收数据
RI=0;
return Data;
}
void send_addr(uchar addr) //发送地址
{
uchar tem;
while(addr!=tem) //如果发送的地址与从机应答的地址不一样,则一直发送地址
{
while(!TI); //等待发送完毕
TI=0; //软件复位TI
TB8=1; //发送地址帧
SBUF=addr; //发送地址
tem=Receive();
}
}
void send_data(uchar ddata) //发送数据,但此处由于与从机的协议,禁止发送0xff
{
while(!TI); //等待发送完毕
TI=0; //软件复位TI
TB8=0; //发送数据帧
SBUF=ddata; //发送数据
while(!TI);
}
void main()
{
Uart_Init();
send_addr(addr1); //向从机1发地址
send_data(0x33);
send_addr(addr2); //向从机2发地址
send_data(0x34);
while(1);
}
//=====================================================================
// 多机通讯从机1程序
//cong1.c
//writer:谷雨 2008年3月22日于EDA实验室
//注:从机先接收地址,然后与自己的地址比较,正确了再接收数据,修改地址可挂多个从机
//=====================================================================
#include
#define unit unsigned int
#define uchar unsigned char
#define addr 0x31 //从机1地址
void Uart_Init(void)
{
TMOD=0x20; //定时器T1使用工作方式2
TH1=250;
TH0=250;
TR1=1; //开始计时
PCON=0x80; //SMOD=1;
SCON=0xd0; //工作方式3,9位数据位,波特率9600bit/s,允许接收
TI=1;
RI=1;
}
void send(uchar Data) //发送数据程序
{
while(!TI); //等待发送完毕
SBUF=Data;
TI=0;
while(!TI);
}
uchar recv_data(void) //接收数据
{
uchar date;
while(!RI); //等待接受完毕
RI=0;
if(RB8==1) //若当前接收为地址帧则返回0xff
return 0xff;
date=SBUF;
while(!RI);
return date;
}
void main()
{
uchar tem,Data;
Uart_Init();
while(1)
{
SM2=1; //只接收地址帧
//如果接收到的地址帧不是本机地址,则继续等待
while(tem!=addr)
{
while(!RI);
RI=0;
tem=SBUF;
}
//如果是本机地址,发送应答信号,并做好接受数据的准备
TB8=0; //主机不检测该位
send(addr);
SM2=0; //允许接受数据信息
//接收数据
Data=recv_data();
if(Data==0xff)
continue;
switch(Data)
{
case 0x01: //在此可以写入要完成的动作,最多可完成256个动作
break;
case 0x33:
P1=0xaa; //为方便其间,赋值给P1口,测P1口电平来检测该程序
break;
case 0x02:
break;
case 0x03:
break;
default:
break;
}
}
}
下面的资料在其他地方找的
主机和从机之间可进行双向通信,从机和从机之间的通信必须通过主机 ,此时主机相当于一个数据收发机,关于从机与从机之前的通信,请参看本公司电子与计算机系统中的其它软件,下面我们只讲主机向从机发数据的情况。
先看硬件连接,主机的发送端TXD与四台从机的接收端相连,主机的接收端与四台从机的发送端相连。
每台从机的名字都用一个8位二进制来代表,但要求所有从机的名字不能有重复,假定第一台从机就用“1”表示,即第一台从机的名字叫1,第二台从机的名字叫2,第三台从机的名字叫3,第四台从机的名字叫4。
每一台从机都将自己的名字即从机号保存在程序存储器中 。
从机和主机都工作于方式3,主机发送的数据中,
若第九位为1,则该数据为地址,若第九位为0,则该数据为数据。
单片机的串口通信过程和课堂上教师提问的过程差不多,教师提问前要先点某个学生的名字,然后所有的学生都把教师点的这个名字和他们自己的名字比较,其中必然有一个学生会发现这个名字是他的名字,然后他就从座位上站起来准备回答教师的提问 。而其它学生发现这个名字与他们无关,则他们都不用站起来。
然后教师就开始提问,教师提问的时所有的学都听见了,站起的那个学生对这个问题作出响应,当教师 问一会儿后,他可能想换一个学生提问,这里他再点一个学生的名字,则这次被点的那个学生站起来,其它的学生全坐下。
在单片机的多机通信中,同样如此,主机相当于教师,从机相当于学生,通信前,主机发送一个第九位为1的数据,相当于教师点一个学生的名字 。由于该数据的第九位为1,所以不论从机的多机通信允许位SM2为1还是为0,所有从机都接收并检测该数据,相当于所有学都听见了教师的点名,其中必然有一台从机会发现接收到的数据和它本身保存在存储器中的从机号相同,相当于其中有一个学生判断出教师要对他提问 。则该从机将其多机通信控制位SM0置0,相当于这个学生从座位上站起来,这样才能接收主机将要发送给它的第九位为0的数据,
即相当于只有站起来的学生才能回答提问,而其它从机肯定会发现它们接收到的地址与它们的从机号不相符,则这些从机都将其多机通信控制位SM2置1,相当于其它的学生全都坐下 。
主机在发出一个从机的地址后,紧接着就可以把发往该从机的数据依次发出,每个数据的第九位都为0,这相当于教师提问,每个从机都检测到了这些数据,但只有SM2为0的从机才能将这些数据装入接收缓冲器并申请CPU处理这些数据,而其它的从机将这些数据丢失,相当于只有站起来的学生才能回答提问。