单片机双机通信

2019-04-15 12:40发布

单工通信

主机控制从机。

主机工作方式

/********************初始化串口 bps为波特率**********************************/ void uart_init(unsigned int bps) { unsigned char t; SCON=0x50;//(0101)工作方式一:8位异步收发,波特率可变,允许接收数据 PCON=0x00;//SMOD=0 TI=0;//软件清零,表示未发送完成 EA=1;//开总中断 ES=1; //开串口中断 TMOD=0x20;//8位自动装载模式 switch(bps) { case 1200:t=0xe8;break; case 2400:t=0xf4;break; case 4800:t=0xfa;break; case 9600:t=0xfd;break; } TH1=t; TL1=t; TR1=1;//开启T1 }

发送数据

/********************循环发送数据 ch为数据口**********************************/ void uart_send(unsigned char ch) { ES=0; //关串口中断 SBUF=ch;//发送s数组至sbuf,电脑串口助手接收 while(TI==0);//等待发送完成 TI=0; //清除中断标记 ES=1; //开串口中断 } main中直接发送P0口的数据给SBUF,等待从机接收 void main() { uart_init(9600);//初始化串口,并设置波特率为9600 while(1) { uart_send(P0); //循环发送P0口数据 } }

从机工作方式

1、设定工作方式
2、读取数据 void main() { uart_init(9600);//初始化串口,并设置波特率为9600 while(1) { if(RI==1)//接收中断标志位 RI=1,表示一帧数据接收完毕 { P0=SBUF; RI=0;//接收中断标志位置零 } while(RI==0);//等待接收完成 } } 或中断接收 void main() { uart_init(9600);//初始化串口,并设置波特率为9600 while(1) { while(RI==0);//等待接收完成 } } void receive() interrupt 4 { if(RI==1) { RI=0; P0=SBUF; } }

双机通信

这里写图片描述
单片机既是接收端也是发送端
1、设定工作方式
2、接收发送 void main(void) { init();//设定工作方式 while(1) { SBUF=P1;//sbuf接收 while(!TI)//发送中断标志位TI=1,表示一帧数据发送结束。 { SBUF=P1;//sbuf接收数据 } TI=0; temp=SBUF;//单片机取值 while(!RI) { temp=SBUF;//单片机取sbuf数据 } RI=0; } } 此时sbuf值已经接收到,在数码管上进行显示。字符格式需进行转换。 //字符格式转换函数 unsigned char transfer(unsigned char dat) { unsigned char endData=0; endData=dat%16;//16进制的转换 return endData; }

上代码

#include #define u8 unsigned char #define u16 unsigned int void init(){ PCON=0x80; SCON=0x90; //1001,工作方式3 ES=1; EA=1; TMOD=0x20; } void main(){ init(); while(1){ SBUF=P1; while(TI==0){ SBUF=P1; } TI=0; P0=SBUF; while(RI==0){ P0=SBUF; } RI=0; } }

多机通信

设定工作方式 void init() { SCON=0xF0;//设定UART工作在MODE3,SM2=1,REN=1,允许接收 PCON=0;//SMOD=0 TMOD=0x20;//TIMER1工作在MODE2 TH1=0xF3;//波特率2400 TR1=1;//启动TIMER1 IE=0x90;//EA=1、ES=1,CPU、UART中断使能 } KEY1=0xFF;//键盘口设为输入状态 if(keydata1 != KEY1)//判断指拨开关1有没有变化? { keydata1 = KEY1;//不同则读入指拨开关1 TB8=1;//设TB8=1,准备发送地址 ACK_flag=0;//清主机发送结束标志 SBUF=0x01;//发出01H地址(89C51-B) while(!ACK_flag);//发送完毕否?,没有就等待 TB8=0;//设TB8=0,准备发送数据 ACK_flag=0;//清主机发送结束标志 SBUF = keydata1;//发送指拨开关1的数据 while(!ACK_flag);//发送完毕否?,没有就等待 } if(keydata2 != KEY2)//判断指拨开关2有没有变化? { keydata2 = KEY2;//不同则读入指拨开关2 TB8=1;//设TB8=1,准备发送地址 ACK_flag=0;//清主机发送结束标志 SBUF=0x02;//发出02H地址(89C51-C) while(!ACK_flag);//发送完毕否?,没有就等待 TB8=0;//设TB8=0,准备发送数据 ACK_flag=0;//清主机发送结束标志 SBUF = keydata2;//发送指拨开关2的数据 while(!ACK_flag);//发送完毕否?,没有就等待 } UARTI() interrupt 4 //串行接收中断程序 { if(TI)//是否发送中断?TI=1时,发送中断标志位 TI =1,表示一帧数据发送结束。 { TI=0;//发送中断,清除TI=0 ACK_flag=1;//设定应答标志 } else RI=0;//是接收中断,则清除RI=0 }

上代码

这里写图片描述

主机

#include #define KEY1 P1//定义输入开关1 #define KEY2 P2//定义输入开关2 unsigned char keydata1;//存储指拨开关1的值 unsigned char keydata2;//存储指拨开关2的值 bit ACK_flag;//主机发送结束标志 //**************************************************** void init() { SCON=0xF0;//设定UART工作在MODE3,SM2=1,REN=1,允许接收 PCON=0;//SMOD=0 TMOD=0x20;//TIMER1工作在MODE2 TH1=0xF3;//波特率2400 TR1=1;//启动TIMER1 IE=0x90;//EA=1、ES=1,CPU、UART中断使能 } //**************************************************** void main() { init(); keydata1 = 0xFF;//设置指拨开关1初始值 keydata2 = 0xFF;//设置指拨开关2初始值 while(1) { KEY1=0xFF;//键盘口设为输入状态 if(keydata1 != KEY1)//判断指拨开关1有没有变化? { keydata1 = KEY1;//不同则读入指拨开关1 TB8=1;//设TB8=1,准备发送地址 ACK_flag=0;//清主机发送结束标志 SBUF=0x01;//发出01H地址(89C51-B) while(!ACK_flag);//发送完毕否?,没有就等待 TB8=0;//设TB8=0,准备发送数据 ACK_flag=0;//清主机发送结束标志 SBUF = keydata1;//发送指拨开关1的数据 while(!ACK_flag);//发送完毕否?,没有就等待 } if(keydata2 != KEY2)//判断指拨开关2有没有变化? { keydata2 = KEY2;//不同则读入指拨开关2 TB8=1;//设TB8=1,准备发送地址 ACK_flag=0;//清主机发送结束标志 SBUF=0x02;//发出02H地址(89C51-C) while(!ACK_flag);//发送完毕否?,没有就等待 TB8=0;//设TB8=0,准备发送数据 ACK_flag=0;//清主机发送结束标志 SBUF = keydata2;//发送指拨开关2的数据 while(!ACK_flag);//发送完毕否?,没有就等待 } } } UARTI() interrupt 4 //串行接收中断程序 { if(TI)//是否发送中断? { TI=0;//发送中断,清除TI=0 ACK_flag=1;//设定应答标志 } else RI=0;//是接收中断,则清除RI=0 }

从机1

#include #define LEDOUT P0//定义输出指示灯 //**************************************************** void main() { SCON=0xf0;//设定UART工作在MODE3,SM2=1,REN=1,允许接收 PCON=0;//SMOD=0 TMOD=0x20;//TIMER1工作在MODE2 TH1=0xF3;//波特率2400 TR1=1;//启动TIMER1 IE=0x90;//EA=1、ES=1,CPU、UART中断使能 while(1); } //=============================== UARTI() interrupt 4 //串行接收中断程序 //要么收到地址,要么收到数据,地址不对的是不会接收数据的,也不会产生中断 { unsigned char a;// if(RI)//是否产生接收中断? { RI=0;//接收中断,清除RI=0 a = SBUF;//将SBUF载入 if(SM2)//SM2=1接收地址, { if(a==1)//是否89C51-B的地址 SM2=0;//是则清除SM2=0,准备接收数据 } else {LEDOUT = a;//SM2=0则将接收数据输出至P2 SM2 = 1; }//设SM2=1,准备下一次接收地址 } else TI=0;//是发送中断,则清除TI=0 }

从机二

#include #define LEDOUT P0//定义输出指示灯 //***************************************************** void main() { SCON=0xf0;//设定UART工作在MODE3,SM2=1,REN=1,允许接收 PCON=0;//SMOD=0 TMOD=0x20;//TIMER1工作在MODE2 TH1=0xF3;//波特率2400 TR1=1;//启动TIMER1 IE=0x90;//EA=1、ES=1,CPU、UART中断使能 while(1); } //=============================== UARTI() interrupt 4 //串行接收中断程序 { unsigned char a;// if(RI)//是否产生接收中断? { RI=0;//接收中断,清除RI=0 a = SBUF;//将SBUF载入 if(SM2)//SM2=1接收地址, {if(a==2)//是否89C51-C的地址 SM2=0;//是则清除SM2=0,准备接收数据 } else {LEDOUT = a;//SM2=0则将接收数据输出至LED显示 SM2 = 1;//设SM2=1,准备下一次接收地址 } } else TI=0;//是发送中断,则清除TI=0 }