实验6 基于51单片机的串口通信系统设计

该实验项目旨在让学生掌握单片机串行通信技术,通过Proteus设计仿真硬件电路,使用KeiluVision编写汇编和C语言程序。两片单片机在模式1下工作,甲机按键控制乙机LED灯闪烁,实现了不同模式的灯光控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、实验项目:

串口通信系统设计

二、实验目的:

本系统设计的目的是使学生掌握单片机的串行通信技术。深刻理解单片机串行通信系统的功能和运行原理,掌握单片机软硬件系统开发的技巧。具体要求两片单片机都工作于串口模式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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无名氏AA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值