实验一:方式一的应用设计
一、实验内容
单片机甲、乙双机串行通信,双机RXD和TXD相互交叉相连,甲机P1口接8个开关,乙机P1口接8个发光二极管。甲机设置为只能发送不能接收的单工方式。要求甲机读入P1口的8个开关的状态后,通过串行口发送到乙机,乙机将接收到的甲机的8个开关的状态数据送入P1口,由P1口的8个发光二极管来显示8个开关的状态。双方晶振均采用11.0592MHz。
二、实验原理及步骤
三、电路设计及调试
(1)实验电路
file:///C:/Users/zyt/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg
(2)程序设计及调试
甲机:
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
void main()
{
uchar temp=0;
TMOD=0x20; //设置定时器T1为方式2
TH1=0xfd; //波特率9600
TL1=0xfd;
SCON=0x40; //串口初始化方式1发送,不接收
PCON=0x00; // SMOD=0
TR1=1; //启动T1
P1=0xff; //设置P1口为输入
while(1)
{
while(TI==0); //如果TI=0,未发送完,循环等待
TI=0; //已发送完,把TI清0
temp=P1; //读入P1口开关的状态数据
SBUF=temp;}} //数据送串行口发送
乙机:
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
void main( )
{
uchar temp=0;
TMOD=0x20; //设置定时器T1为方式2
TH1=0xfd; //波特率9600
TL1=0xfd;
SCON=0x50; //设置串口为方式1接收,REN=1
PCON=0x00; //SMOD=0
TR1=1; //启动T1
while(1)
{
while(RI==0); // 若RI为0,未接收到数据
RI=0; // 接收到数据,则把RI清0
temp=SBUF; // 读取数据存入temp中
P1=temp;}} // 接收的数据送P1口控制8个LED的亮与灭
实验二:多机通信的应用设计
一、实验内容
实现主单片机分别与3个从单片机串行通信,原理电路见图。用户通过分别按下开关k1、k2或k3来选择主机与对应1#、2#或3#从机串行通信,当黄色LED点亮,表示主机与相应的从机连接成功;该从机的8个绿色LED闪亮,表示主机与从机在进行串行数据通信。如果断开k1、k2或 k3,则主机与相应从机的串行通信中断。
二、实验原理及步骤
1. 实现主、从机串行通信,各从机程序都相同,只是地址不同。
串行通信约定如下。
(1)3台从机的地址为01H~03H。
(2)主机发出的0xff为控制命令,使所有从机都处于SM2=1的状态。
(3)其余的控制命令:00H—接收命令,01H—发送命令。这两条命令是以数据帧的形式发送的。
(4)从机的状态字如图所示。
file:///C:/Users/zyt/AppData/Local/Temp/msohtmlclip1/01/clip_image004.jpg
其中:
ERR(D7位)=1,表示收到非法命令。
TRDY(D1位)=1,表示发送准备完毕。
RRDY(D0位)=1,表示接收准备完毕。
串行通信时,主机采用查询方式,从机采用中断方式。主机串口设为方式3,允许接收,并置TB8为1。因只有1个主机,所以主机SCON控制寄存器中的SM2不要置1,故控制字为11011000,即0xd8。
三、电路设计及调试
(1)实验电路
file:///C:/Users/zyt/AppData/Local/Temp/msohtmlclip1/01/clip_image006.jpg
(2)程序设计及调试
//主机程序
#include <reg51.h>
#include <math.h>
sbit switch1=P0^0; //定义k1与P0.0连接
sbit switch2=P0^1; //定义k2与P0.1连接
sbit switch3=P0^2; //定义k3与P0.2连接
void main() //主函数
{
EA=1; //总中断允许
TMOD=0x20; //设置定时器T1 定时方式2 自动装载定时常数
TL1=0xfd; //波特率设为9600
TH1=0xfd;
PCON=0x00; //SMOD=0,不倍增
SCON=0xd0; //SM2设为0,TB8设为0
TR1=1; //启动定时器T1
ES=1; //允许串口中断
SBUF=0xff; //串口发送0xff
while(TI==0); //判是否发送完毕
TI=0; //发送完毕,TI清0
while(1)
{
delay_ms(100);
if(switch1==0) //判是否k1按下,k1按下往下执行
{
TB8=1; //发送的第9位数据为1,送TB8,准备发地址帧
SBUF=0x01;//串口发1#从机的地址0x01以及TB8=1
while(TI==0); //判是否发送完毕
TI=0; //发送完毕,TI清0
TB8=0; //发送的第9位数据为0,送TB8,准备发数据帧
SBUF=0x00; //串口发送0x00以及TB8=0
while(TI==0); /判是否发送完毕
TI=0; //发送完毕,TI清0
}
if(switch2==0) //判是否k2按下,k2按下往下执行
{
TB8=1; //发送的第9位数据为1,发地址帧
SBUF=0x02; //串口发2#从机的地址0x02
while(TI==0); /判是否发送完毕
TI=0; //发送完毕,TI清0
TB8=0; //准备发数据帧
SBUF=0x00; //发数据帧0x00及TB8=0
while(TI==0); //判是否发送完毕
TI=0; //发送完毕,TI清0
}
if(switch3==0) //判是否k3按下,如按下,则往下执行
{
TB8=1; //准备发地址帧
SBUF=0x03; //发3#从机地址
while(TI==0); //判是否发送完毕
TI=0; //发送完毕,TI清0
TB8=0; //准备发数据帧
SBUF=0x00; //发数据帧0x00及TB8=0
while(TI==0); //判是否发送完毕
TI=0; //发送完毕,TI清0
}
}
}
void delay_ms(unsigned int i) //函数功能:延时
{
unsigned char j;
for(;i>0;i--)
for(j=0;j<125;j++)
;
}
//从机1串行通信程序
#include <reg51.h>
#include <math.h>
sbit led=P2^0; //定义P2.0连接的黄色LED
bit rrdy=0; //接收准备标志位rrdy=0,表示未做好接收准备
bit trdy=0; //发送准备标志位trdy=0,表示未做好发送准备
bit err=0; //err=1,表示接收到的命令为非法命令
void main() //从机1主函数
{
EA=1; //总中断打开
TMOD=0x20;//定时器1 工作方式2,自动装载,用于串口设置波特率
TL1=0xfd;
TH1=0xfd; //波特率设为9600
PCON=0x00; // SMOD=0
SCON=0xd0; //SM2设为0,TB8设为0
TR1=1; //启动定时器T1
P1=0xff; // 向P1写入全1,8个绿色LED全灭
ES=1; //允许串口中断
while(RI==0); //接收控制指令0xff
if(SBUF==0xff) err=0; //如果接收到的数据为0xff,err=0,表示正确
else err=1; //err=1,表示接收出错
RI=0; //接收中断标志清0
SM2=1; //多机通讯控制位,SM2置1
while(1);}
void int1() interrupt 4, //函数功能:定时器T1中断函数
{
if(RI) //如果RI=1
{
if(RB8) //如果RB8=1,表示接收的为地址帧
{
RB8=0;
if(SBUF==0x01) //如收的数据为地址帧0x01,是本从机的地址
{
SM2=0; //则SM2清0,准备接收数据帧
led=0; //点亮本从机黄色发光二极管
}
}
led=1; // 熄灭本从机黄色发光二极管
}
RI=0;
}