湖北大学 单片机实验6 串口通信系统设计

实验目的:

甲机通过串口控制乙机 LED

甲单片机负责向外发送控制命令字符“A”、“B”、“C”,或者停止发送,乙机根据所接收到的字符完成 LED1 闪烁、LED2 闪烁、双闪烁、或停止闪烁

实验器材:

Protues、keil

实验原理(给出硬件电路图):

实验步骤:

  • 原理分析

1.1串行通信使用配置

(1)设置T1的工作方式(编程TMOD寄存器)

(2)计算T1的初值,装载TH1、TL1

如果我们用9600波特率的
SMOD 通常不用到,如果给它赋予1或0,计数的波特率会翻倍,如果不使用,默认为0.
9600 = 11.0592 / 32* 12 * (256-T初)
得T初 = 253 = 0xfd
TH1 = 0xfd
TL1 = 0xfd

(3)启动T1(编程TCON中的TR1位)

TR1=1

(4)确定串行口控制(编程SCON寄存器)

程序代码及实验结果(含汇编语言代码和C语言代码):

甲机C语言:

/*  甲单片机负责向外发送控制命令字符“A”、“B”、“C”,或者停止发送,乙机根据所接收到的字符
完成 LED1 闪烁、LED2 闪烁、双闪烁、或停止闪烁。*/
 
#include<reg51.h>
 

//定义
sbit LED1=P0^0;  //P0.0口控制LED1 
 
sbit LED2=P0^3;//P0.3口控制LED3
 
sbit K1=P1^0; //P1.0口控制按键K1

//延时程序
void DelayMS(unsigned int ms)
 
{
 
unsigned char i;
 
while(ms--) for(i=0;i<120;i++);
 
}


//向串口发送字符
 
void Send( unsigned char C)
 
{
 
SBUF=C;//向SBUF(收发缓冲寄存器)写入字符“C”

 //当数据发送完之后(TI==1),while语句不成立,跳出while,执行TI=0
while(TI==0);
 
TI=0; //软件清0
 
}
 
 
 
//主程序
 
void main()
 
{
 
 unsigned char Data=0;
SCON=0x50; //SCON(定义串行口的工作方式),定义串行口工作在工作方式1(10位异步接收/发送),并且设置REN=1(允许数据的接收)
 
TMOD=0x20; //TMOD(定义定时器/计数器的工作方式),定义T1工作在工作方式2(8位定时器/计数器)
 
PCON=0x00; //PCON(串行口波特率倍增位)定义为0000 0000,波特率不倍增
//设置波特率,晶振频率是11.0592M,波特率9600 
TH1=0xfd;//将宏计算的T1初值放到TH1中
 
TL1=0xfd;//将宏计算的T1初值放到TL1中
 
TI=0;//TI在发送数据前必须由软件清零
 
TR1=1;//启动T1开始计数
	

	
//一个死循环,实现功能
while(1)
 
{
 
//设置控制字符的变量	
if(K1==0) //按下 K1 时选择操作代码 0,1,2,3
 
{ 
 
while(K1==0); 
 
Data=(Data+1)%4; //对Data+1的值取4的余数,即取值范围在0-3之间的数,然后再把这个余数赋给Data变量
 
} 


 //switch语句判断Data的值
switch(Data) //根据操作代码发送 A/B/C 或停止发送
 
{ 
 //停止闪烁
case 0: LED1=LED2=1;
 
break; 
 //LED1闪烁
case 1:Send('A');
 
LED1=~LED1;LED2=1;
 
break; 
 //LED2闪烁
case 2:Send('B');
 
LED2=~LED2;LED1=1;
 
break; 
//双闪烁 
case 3:Send('C');
 
LED1=~LED1;LED2=LED1;
 
break; 
 
} 
 
DelayMS(100);
 
  }
 
}





 甲机汇编语言:

; 甲单片机负责向外发送控制命令字符“A”、“B”、“C”,或者停止发送


KEY1 EQU P1.0 ;做等价替换使用
ORG  0000H
LJMP START 
ORG  0030H

START:   ;主程序开始 
     
   SETB EA ;打开总中断
   SETB ET1;定时器1中断允许
   MOV SCON ,#50H;设定串行口工作方式1,且准备接收信号
   MOV TMOD,#20H;定时器1为工作方式2
   MOV PCON ,#00H;保证 SMOD 为0,波特率不加倍
   MOV TH1,#0FdH; 设定波特率
   MOV TL1,#0FdH
   SETB TR1;启动定时器1
   MOV P0,#0FFH ;灯的起始状态为灭
   MOV R5,#00H;用R5存放待发送的数,若为0则表示不发送
   MOV R4,#00H;控制 LED 现象的标志变量
    
;判断按键是否按下
SCAN:
   
   JB KEY1, LOOP ;K1=1,未按就跳转到灯灭的状态
   LCALL DELAY;按键消抖 
   JB KEY1, LOOP ;K1=1,未按就跳转到灯灭的状态,按下则顺序执行
 
;R4实现加1的功能,执行不同的现象   
D1:
   MOV A,P1 ;此时开关已按下,P1=0FEH
   CJNE A,#0FFH,D1 ;死循环,直到松开开关
   INC R4 ;松开开关后R4加1


;全灭的状态   
LOOP:
    CJNE R4,#00H,LOOP1 
    MOV P0,#0FFH
	LCALL DELAY
	SJMP SCAN
	
	
	
	;第一种状态:LED1亮
LOOP1:
   CJNE R4,#01H,LOOP2 
   JNB KEY1,$;松手监测,key1=0,就向下执行
  CLR P0.0;点亮LED1
  LCALL DELAY;延时100
  SETB P0.0;熄灭LED1
  LCALL DELAY ;延时100ms
   MOV R5,#'A';将 A ->R5
   SJMP SEND ;发送
    
;第二种状态:LED2亮   
LOOP2:
      CJNE R4,#2,LOOP3 
   JNB KEY1,$;松手监测,k1=0,就向下执行
	    CLR P0.3;点亮LED2
  LCALL DELAY;延时100ms 
  SETB P0.3;熄灭LED2
  LCALL DELAY;延时100ms
   MOV R5,#'B'
    SJMP SEND ;发送
  
;LED1、LED2全亮   
LOOP3:
      CJNE R4,#3,LOOP4 
   JNB KEY1,$;松手监测,k1=0,就向下执行
	    CLR P0.0;点亮LED1
  CLR P0.3;点亮LED2
  LCALL DELAY;延时100ms  
  SETB P0.0 ;熄灭LED1
  SETB P0.3 ;熄灭LED2
  LCALL DELAY ;延时100ms
   MOV R5,#'C'
   SJMP SEND ;发送
  
   
LOOP4:
     JNB KEY1,$;松手监测,k1=0,就向下执行
     MOV R4,#0;控制 LED 变量归零

   

;判断是否发送完毕
SEND:      
     MOV SBUF ,R5 ;发送r5中的字符“A”“B”“C”
   JNB TI ,$;等待发送完毕, TI 为1表示发送结束
   CLR TI ;允许再发送,将 TI 位进行清零
   ;LCALL DELAY
   SJMP SCAN;继续扫描按键
 
DELAY:
     MOV R5,#0FFH
        D2:
     MOV R6,#0FFH
     DJNZ R6,$     ;减1不为0则原地跳
     DJNZ R5,D2
      RET 
     RET
	 END
	 
	 
	

乙机C语言:

/*  乙机程序接收甲机发送字符并完成相应动作,说明:乙机接收到甲机发送的信号后,根据相应信号控制 LED 完成不同闪烁动作。*/
 
#include<reg51.h>
 

 
sbit LED1=P0^0;  //P0.0口控制LED1 
 
sbit LED2=P0^3;//P0.3口控制LED2

//延时程序 
void DelayMS(unsigned int ms)
 
{
 
unsigned char i;
 
while(ms--) for(i=0;i<120;i++);
 
}

//主程序
 
void main()
 
{
 
SCON=0x50; //SCON(定义串行口的工作方式)定义为0101 0000,定义串行口工作在工作方式1(10位异步接收/发送)
//接受过程在RI=0且REN=1条件下启动的
 
TMOD=0x20; //TMOD(定义定时器/计数器的工作方式)定义为0010 0000,定义T1工作在工作方式2(8位定时器/计数器)
 
PCON=0x00; //波特率不倍增
	
 //设置波特率,晶振频率是11.0592M,波特率9600 
TH1=0xfd; 
TL1=0xfd;
 
RI=0;//接受数据的时候软件清零
 
TR1=1;//启动T1开始计数
 
LED1=LED2=1;//设置LED灯的起始状态
 
while(1)
 
{
  //RI为接收中断标志位
 //若RI为1,即接收到数据,执行if语句内容;若RI为0,即未接收到数据,不执行if语句内容。
//if从句表示接收到数据后的操作
if(RI) 
 
{ 
 
RI=0; //软件清零
 
switch(SBUF) //根据所收到的不同命令字符完成不同动作
 
{ 
 
case 'A': LED1=~LED1;LED2=1;break; //LED1 闪烁
 
case 'B': LED2=~LED2;LED1=1;break; //LED2 闪烁
 
case 'C': LED1=~LED1;LED2=LED1;break;  //双闪烁
 
} 
 
 
 } 
 else LED1=LED2=1;     //停止闪烁
 
DelayMS(100);
 
    }
 
} 

乙机汇编语言:

;;; 乙单片机根据所接收到的字符完成 LED1 闪烁、LED2 闪烁、双闪烁、或停止闪烁
ORG 0000H
LJMP START
ORG 0030H
START:     ;主程序开始
  SETB EA ;打开总中断
  SETB ET1 ;定时器1中断允许
  MOV TMOD ,#20H;定时器1为工作方式2
  MOV PCON ,#00H;保证 SMOD 为0,波特率不加倍
  MOV TH1,#0FdH;调整定时器时间,设置波特率为9600bps
  MOV TL1,#0FdH
  SETB TR1;启动定时器1
  MOV SCON ,#50H;设定串行口工作方式1,且准备接收信号
 
;接收程序 
 RECEIVE:     
  JNB  RI,$;等待接收信号RI,RI=1表示接受完数据
  CLR RI ;允许再接收
  MOV A , SBUF;将接收到的数据读到 A 中 
  CJNE A ,#0,LED1;如果接收的不是0,则跳到第一种灯效
  MOV P0,#0FFH;如果接收到的是0,则全灭
  SJMP RECEIVE 

LED1:     ;第一种灯效,LED1闪
  CJNE A ,#'A',LED2;若不是 A ,则跳转到第二种灯效 
  CLR P0.0;点亮LED1
  LCALL DELAY;延时100ms 
  SETB P0.0;熄灭LED1
  LCALL DELAY ;延时100ms
  SJMP RECEIVE ;继续接收
  

  LED2:    ;第二种灯效,LED2闪
     CJNE A ,#'B',LED3;若不是 B ,则跳转到第三种灯效 
  CLR P0.3;点亮LED2
  LCALL DELAY;延时100ms 
  SETB P0.3;熄灭LED2
  LCALL DELAY;延时100ms
  SJMP RECEIVE ;继续接收

LED3:           ;第三种灯效,LED1和LED2同时闪
  CJNE A ,#'C',RECEIVE ;若不是 C ,则重新接收
  CLR P0.0;点亮LED1
  CLR P0.3;点亮LED2
  LCALL DELAY;延时100ms  
  SETB P0.0 ;熄灭LED1
  SETB P0.3 ;熄灭LED2
  LCALL DELAY ;延时100ms
  SJMP RECEIVE ;继续接收

DELAY:
     MOV R5,#0FFH 
        D2:
     MOV R6,#0FFH
     DJNZ R6,$     ;减1不为0则原地跳
     DJNZ R5,D2
      RET 
     RET 

  END
  
;

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值