一、实验项目:
串口通信系统设计
二、实验目的:
本系统设计的目的是使学生掌握单片机的串行通信技术。深刻理解单片机串行通信系统的功能和运行原理,掌握单片机软硬件系统开发的技巧。具体要求两片单片机都工作于串口模式1,甲单片机的K1按键每按一下可通过串口分别依次控制乙单片机的LED1闪烁,LED2闪烁,LED1和LED2同时闪烁,关闭所有LED。要求在Proteus中设计出仿真硬件电路,在keil uvision中分别设计出汇编语言和C语言的源程序,然后用Proteus来进行整体系统仿真运行。
三、实验原理:
这个实验的原理是通过串口通信来控制另一个单片机的LED灯。具体步骤如下:
1. 首先,在两个单片机中都设置串口工作模式为模式1,即可以接收控制位。
2. 甲单片机通过按键控制发送不同的控制字符到乙单片机,控制乙单片机的LED灯的亮灭。
3. 乙单片机接收甲单片机发送的控制字符,并根据控制字符控制LED灯的亮灭。
4. 在Proteus中设计出仿真电路,包括两个单片机、串口通信模块、LED灯等组成。
5. 在Keil uVision中分别编写汇编语言和C语言的源程序,实现串口通信和LED灯的控制。
6. 运行仿真电路,测试两个单片机之间的串口通信和LED灯的控制。
四、硬件原理图:
五、C语言代码:
//发射机:
#include <REGX51.H>
#define uchar unsigned char
#define uint unsigned int
char i=3;
char send=0;
void delay(uint t)
{
uchar i;
while(t--)
for(i=0;i<200;i++);
}
void light(char x){ //LED闪烁模式选择,使用Switch语句进行选择
switch(x){ //0则全灭
case 'A': //A只有LED1闪烁
P0_0=0;
delay(100);
P0_0=1;
delay(100);
break;
case 'B': //B只有LED2闪烁
P0_3=0;
delay(100);
P0_3=1;
delay(100);
break;
case 'C': //LED1,2一起闪烁
P0_0=0;
P0_3=0;
delay(100);
P0_0=1;
P0_3=1;
delay(100);
break;
case 'D':
P0_0=1;
P0_3=1;
delay(100);
break;
}
}
void main(void)
{
SCON=0X50; //串行口工作方式一,串行口接收允许位
TMOD=0x20; //T1十六位计数模式
PCON=0x00;
TH1=0xFD; //9600波特率
TL1=0xFD;
TR1=1; //开定时器T1
ET1=1; //开T1中断
ES=0; //串口中断允许
EA=1; //开总中断
i=3;
while(1){
if(P1_0==0)
{ //按下按键
while(P1_0==0);
i++;
if(i==4)
i=0;
}
switch(i)
{ //按下按键则进入下一个状态
case 0:send='A';break;
case 1:send='B';break;
case 2:send='C';break;
case 3:send='D';break;
}
if(send!=0)
{
SBUF=send; //接收缓冲器 SBUF,数据发送完毕会自动置位TI,接收完毕
while(TI==0); //中断标志不为0结束此语句
TI=0;
light(send); //点亮LED
}
}
}
//接收机:
#include <REGX51.H>
#define uchar unsigned char
#define uint unsigned int
char receive=0;
void delay(uint t)
{
uchar i;
while(t--)
for(i=0;i<200;i++);
}
void light(char x){ //LED闪烁模式选择,使用Switch语句进行选择
switch(x){ //0则全灭
case 'A': //A只有LED1闪烁
P0_0=0;
delay(100);
P0_0=1;
delay(100);
break;
case 'B': //B只有LED2闪烁
P0_3=0;
delay(100);
P0_3=1;
delay(100);
break;
case 'C': //LED1,2一起闪烁
P0_0=0;
P0_3=0;
delay(100);
P0_0=1;
P0_3=1;
delay(100);
break;
case 'D':
P0_0=1;
P0_3=1;
delay(100);
break;
}
}
void main(void){
SCON=0X50; //串行口工作方式一,串行口接收允许位
TMOD=0x20; //T1十六位计数模式
PCON=0x00;
TH1=0xFD; //9600波特率
TL1=0xFD;
TR1=1; //开定时器T1
ET1=1; //开T1中断
ES=0; //串口中断允许
EA=1; //开总中断
while(1){
while(RI==0); //接受位RI非零则进行下一语句
RI=0;
receive=SBUF; //接收数据
if(receive!=0){
light(receive); //点亮对应的接收
}
}
}
六、汇编代码:
;发射机:
ORG 0000H
LJMP MAIN
ORG 0030H
MAIN:MOV SCON,#40H ;工作方式1,波特率可变,定时器控制
MOV PCON,#00H ;波特率不不倍增
MOV TMOD,#20H ;定时器1,工作方式2,自动重新装入计数初值的8位
MOV TH1,#0FDH ;9600波特率
MOV TL1,#0FDH
SETB ES ;串行口中断允许
SETB EA ;总中断允许
SETB TR1 ;启动定时器
LP0:JNB P1.0,$ ;松手检测
ACALL DELAY
ACALL SEND ;发送都灭信号
SETB P0.0 ;LED1灭
SETB P0.3 ;LED2灭
JNB P1.0,LP1 ;按下按键转移
SJMP LP0
LP1:JNB P1.0,$ ;松手检测
ACALL DELAY
ACALL SEND1 ;发送LED1亮,LED2灭信号
CPL P0.0 ;取反,LED1亮
SETB P0.3 ;LED2灭
JNB P1.0,LP2 ;再次检查按键
SJMP LP1
LP2:JNB P1.0,$ ;松手检测
ACALL DELAY
ACALL SEND2 ;发送LED2亮,LED1灭信号
CPL P0.3 ;取反,LED2亮
SETB P0.0 ;LED1灭
JNB P1.0,LP3 ;再次检查按键
SJMP LP2
LP3:JNB P1.0,$ ;松手检测
ACALL DELAY
ACALL SEND3 ;发送都亮信号
CPL P0.0 ;LED1亮
CPL P0.3 ;LED2亮
JNB P1.0,LP0 ;再次检查按键
SJMP LP3
SEND:MOV SBUF,#'A'
JNB TI,$ ;等待发送完成
CLR TI ;发送完成后清零
RET
SEND1:MOV SBUF,#'B'
JNB TI,$ ;等待发送完成
CLR TI ;发送完成后清零
RET
SEND2:MOV SBUF,#'C'
JNB TI,$ ;等待发送完成
CLR TI ;发送完成后清零
RET
SEND3:MOV SBUF,#'D'
JNB TI,$ ;等待发送完成
CLR TI ;发送完成后清零
RET ;为了更好的观察LED闪烁情况,使用延时程序
DELAY:MOV R1,#250
D1: MOV R2,#250
D2: DJNZ R2,D2
DJNZ R1,D1
RET
END
;接收机:
ORG 0000H
LJMP MAIN
ORG 0023H
LJMP RECIVE ;跳转到串口中断处理程序
ORG 0030H ;指定中断向量表中定时器1中断的入口地址为30H
MAIN:MOV SCON,#50H ;工作方式1,开REN允许接收控制位
MOV PCON,#00H ;波特率不倍增
MOV TMOD,#20H ;工作方式2,计数器1
MOV TH1,#0FDH ;将计时器1的重载值设为0FDH,即波特率为9600
MOV TL1,#0FDH
SETB ES ;开串口中断
SETB EA ;开总中断
SETB TR1 ;开计时器1
LOOP:SJMP LOOP ;循环等待甲机发送信号
RECIVE:
MOV A,SBUF ;接送信号
CJNE A,#'A',L1 ;相等顺序执行,不相等跳转
LCALL LP1 ;相等跳转到LP1,两只都灭
L1: CJNE A,#'B',L2
LCALL LP2 ;相等跳转到LP2,一亮一灭
L2: CJNE A,#'C',L3
LCALL LP3 ;相等跳转到LP3,一亮一灭
L3: CJNE A,#'D',L4
LCALL LP4 ;相等跳转到LP4,都亮
L4: CLR RI ;接收标志位清零
RETI
LP1:SETB P0.0 ;将P0.0置位,即LED1亮
SETB P0.3 ;将P0.3置位,即LED2亮
RET ;子程序返回
LP2:CPL P0.0 ;将P0.0取反,即LED1熄灭或亮
SETB P0.3 ;将P0.3置位,即LED2亮
RET ;子程序返回
LP3:CPL P0.3 ;将P0.3取反,即LED2熄灭或亮
SETB P0.0 ;将P0.0置位,即LED1亮
RET ;子程序返回
LP4:CPL P0.0 ;将P0.0取反,即LED1熄灭或亮
CPL P0.3 ;将P0.3取反,即LED2熄灭或亮
RET ;子程序返回
END