




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第8章基于Proteus的51单片机一般应用8.1基本输入输出的仿真与应用8.2键盘扫描的仿真与应用8.3LCD的仿真与应用8.4中断优先级的仿真与应用8.5定时器的仿真与应用8.6单片机串行通信的仿真与应用本章小结
本章系统叙述在Proteus环境中51单片机一般应用系统的设计与仿真分析方法。
本章共分六节,分别介绍了单片机基本输入输出的仿真与应用、键盘扫描的仿真与应用、LCD的仿真与应用、中断优先级的仿真与应用、定时器的仿真与应用、单片机串口通信的仿真与应用。内容提要
8.1.1仿真电路
创建单片机输入输出仿真电路,如图8-1所示。8.1基本输入输出的仿真与应用
图8-1单片机输入输出仿真电路输入为四个开关(SW1~SW4),输出为四个LED二极管(D1~D4),LED二极管接成灌电流形式。要求:当开关SW1切换至上触点时,D1发光;当开关SW1切换至下触点时,D1不发光。同理,开关SW2对应D2,开关SW3对应D3、开关SW4对应D4。8.1.2控制程序
汇编源程序:
ORG0000H
LJMPMAIN
MAIN:
MOVA,P1 ;读P1口数据(即获取开关状态)
CPLA ;P1口数据取反(因LED接成灌电流形式)
MOVP0,A ;送P0口
JMPMAIN
END
C语言源程序:
#include<reg51.h> //编译器中包含对51单片机的定义
#defineucharunsignedchar
voidmain()
{
ucharled; //无符号字符,值域范围为0~255
while(1)
{
led=P1; //读P1口数据
led=~led; //P1口数据取反
P0=led; //送P0口
}
}
注:C语言程序中的变量P0、P1要大写。8.1.3仿真分析
在Proteus中加载单片机控制程序(HEX文件),单击仿真按钮,则单片机输入输出电路的仿真结果如图8-1所示。仿真时,用鼠标控制开关SW1~SW4的切换,以观察LED发光管的亮灭情况。
8.2.1仿真电路
创建键盘扫描仿真电路,如图8-2所示。单片机的P3口产生键盘的行列信号,P0口接数码管,显示键盘编号。单片机时钟设置为12MHz。
键盘扫描的原理是采用行列扫描法。首先判断有无键按下,在有键按下的情况下,使一条行线输出为低电平,若该行线上有键按下,则相应的列线状态也为低电平。由行线号和列线号即可得到对应按键的编号。8.2键盘扫描的仿真与应用图8-2键盘扫描仿真电路8.2.2控制程序
键盘扫描程序流程图如图8-3所示。图8-3键盘扫描程序流程图汇编源程序:
ORG 0000H
LJMPMAIN
MAIN: MOVP0,#00H ;P0口初始化
LOOP1: MOVR3,#0F7H ;置行扫描初值
MOVR1,#00H ;置键码地址初值
LOOP2: MOVA,R3 ;行扫描值送行扫描线
MOVP3,A
MOVA,P3 ;行扫描值送R4存储
MOVR4,A
SETBC
MOVR5,#04H ;列扫描数
LOOP3: RLCA ;列扫描值带进位左移
JNCKEYIN ;C=0,跳转至按键输入程序
INCR1 ;键码地址加1
DJNZ
R5,LOOP3 ;4列扫描完毕?
MOVA,R3 ;置行扫描值,扫描下一行
SETBC ;当右移时移入“1”
RRCA
MOVR3,A
JC LOOP2 ;行扫描完毕?
JMP LOOP1
KEYIN: MOVR7,#10 ;延时去抖动
D2: MOVR6,#240
DJNZ
R6,$
DJNZ
R7,D2
D3: MOVA,P3
XRL A,R4
JZ D3 ;按键是否松开?
MOVA,R1 ;取键码,送P0口显示
MOVDPTR,#TABLE
MOVCA,@A+DPTR
MOVP0,A
JMP LOOP1
TABLE: DB 4FH,5BH,06H,3FH,07H,7DH,6DH,66H;七段数码管显示代码表
DB 7CH,77H,6FH,7FH,71H,79H,5EH,39H
END
C语言源程序:
#include<reg51.h>
#include<intrins.h>
#include<absacc.h>
#defineucharunsignedchar
#defineuintunsignedint
ucharcodea[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07, //七段数码管显示代码表
0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
voiddelay(uinti) //延时子程序
{uintj;
for(j=0;j<i;j++);
}
ucharcheckkey() //检测有无按键子程序
{uchari,j;
j=0x0F;
P3=j;
i=P3;
i=i&0x0F;
if(i==0x0F)return(0); //表示没有按键合上
elsereturn(0xFF); //表示有按键合上
}
ucharkeyscan() //键盘扫描子程序
{
ucharscancode; //扫描代码
ucharcodeaddr; //键码地址
uchara;
ucharm=0;
uchark;
uchari,j;
if(checkkey()==0)return(0xFF);
else
{delay(100); //延时去抖动
if(checkkey()==0)return(0xFF); //没有按键合上
else
{
scancode=0xF7; //从上到下的第一条行线置低电平
m=0x00; //m表示列线数量
for(i=1;i<=4;i++) //行扫描
{
k=0x10;
P3=scancode;
a=P3;
for(j=0;j<4;j++) //列扫描
{
if((a&k)==0) //若有按键合上,对应的列线为低电平
{
codeaddr=m+j;
while(checkkey()!=0);
return(codeaddr);
}
k=k<<1; //检测下一列
}
m=m+4; //表示列线数量为4
scancode=~scancode; //扫描码右移时,右移的数为1
scancode=scancode>>1;
scancode=~scancode;
}
}
}
}
voidmain()
{
intn;
P0=0x00; //P0口初始化
while(1)
{
if(checkkey()==0x00)continue; //若没有按键合上,转向下一次循环
else
{
n=keyscan(); //得到键码地址
P0=a[n]; //取键码送P0口显示
delay(100);
}
}
}8.2.3仿真分析
在Proteus中加载单片机控制程序(HEX文件),单击仿真按钮,则单片机键盘扫描电路的仿真结果如图8-2所示。仿真时,用鼠标控制开关(为瞬态开关)的切换,数码管显示对应按键的编号。16个开关从左到右、从上到下依次编号为0~F。
8.3.1仿真电路
创建LCD1602液晶显示仿真电路,如图8-4所示。单片机的P1.0检测按键信号,P3口接LCD的数据线,LCD的控制信号由P2.5、P2.6、P2.7产生。LCD1602在Proteus中的名称为LM016L,所属类为Optoelectronics,位于DISPLAY库。8.3LCD的仿真与应用图8-4LCD1602液晶显示仿真电路仿真要求:LCD第一行显示“LM1602TESTNOW!”,第二行显示按键的计数值(即按键每合上一次,计数值加1)。8.3.2LCD1602简介
LCD1602字符型显示器是2行
×
16个字符的液晶显示器。该器件由32个字符点阵组成,可以显示ASCII码表中的所有可显示字符。
1.LCD1602的引脚功能
(1)
VSS:供电电源地。
(2)
VDD:供电电源输入端(接
+5V)。
(3)
VEE:LCD对比度调整。接正电源时,对比度最弱;接地时,对比度最强。使用时可用一个电位器调整其对比度。
(4)
RS:寄存器选择输入端。
RS=0,选择指令寄存器,可以写指令、读LCD忙标志和地址计数器。
RS=1,选择数据寄存器,可以写或读数据。
2.LCD1602指令集
LCD1602字符型显示器模块内部有两种寄存器:指令寄存器和数据寄存器。LCD1602在应用时,首先要对LCD进行初始化操作(单片机向指令寄存器写不同的指令数据),然后确定显示字符的地址,最后将待显示的字符写入LCD的数据寄存器中。LCD1602的指令集如表8-1所示。
表8-1LCD1602的指令集表8-1中的字符说明:
X:0或1。
I/D:显示地址计数器模式选择。I/D=0,减1模式;I/D=1,加1模式。
S:显示屏移动控制位。S=0,显示屏不移动;S=1,如果I/D=1且有字符写入时显示屏左移,否则右移。
D:显示屏开关控制位。D=1,显示屏开;D=0,显示屏关。
C:光标开关控制位。C=1,光标开;C=0,光标关。
B:光标闪烁控制位。B=1,光标闪烁;B=0,光标不闪烁。
S/C:显示屏/光标移位选择。S/C=1,显示屏移位;S/C=0,光标移位。
R/L:移位方向选择。R/L=1,右移;R/L=0,左移。
DL:传输数据有效位长度选择。DL=1,有效位为8位;DL=0,有效位为4位。
N:显示器行数选择。N=1,双行显示;N=0,单行显示。
F:字符点阵块的点阵选择。F=1,选择5
×
10点阵;F=0,选择5
×
7点阵。
BF:忙标志位。BF=1,LCD忙;BF=0,LCD就绪。
CGRAM:字符发生器RAM。用户自编程的字符或图形存储器。
DDRAM:显示数据RAM。
LCD1602的显示数据存储器DDRAM与显示屏上的字符显示位置是一一对应的。DDRAM的地址与字符显示位置的对应关系如表8-2所示。当主控制器需要将字符显示在屏幕的某一位置时,首先将对应位置的DDRAM的地址写至地址计数器(指令寄存器)中,再将该字符的ASCII码写入DDRAM中,这样即可完成一个字符的显示。
表8-2DDRAM的地址与字符显示位置的对应关系8.3.3控制程序
主程序流程图如图8-5所示。图8-5LCD1602液晶显示主程序流程图汇编源程序:
KEY BITP1.0
RS BITP2.5
RW BITP2.6
E BITP2.7
ORG0000H
LJMP MAIN
MAIN: MOV R2,#00H
INIT: MOV R0,#01H ;清屏
CALL WRITE_COMM
MOV R0,#38H ;DL=1(8位数据),N=1(双行显示)
CALL WRITE_COMM
MOV R0,#0FH ;D=1(显示屏开),C=1(显示光标),B=1(光标闪烁)
CALL WRITE_COMM
MOV R0,#06H ;I/D=1(加1),S=0(显示屏不移动)
CALL WRITE_COMM
MOV R0,#080H ;LCD第1行地址
CLR F0 ;PSW.5=0(用户自定义位)
CALL WRITE_COMM
MOV DPTR,#TABLE1 ;在LCD第1行显示字符串
CALL WRITE_STR
KEY0: MOV R7,#0 ;R7为检测按键计数器
KEY1: JB KEY,$ ;等待按键合上
CALL DELAY ;延时去抖动
INC R7 ;计数器加1
CJNE R7,#255,KEY2 ;是否计满?
JNB KEY,$ ;等待按键松开
JMP KEY0 ;计满,则跳转至KEY0,将计数器清0
KEY2: CALL DIVIDE ;调用计数值分离子程序
CALL WRITE_CHAR ;在LCD第2行显示计数值对应的字符
JNB P1.0,$ ;等待按键松开
LJMP KEY1
DIVIDE:MOV A,R7 ;计数值分离子程序,三位计数值分离后分别存入;显示缓冲区40H、41H、42H
MOV B,#64H
DIV AB
MOV 40H,A
MOV A,B
MOV B,#0AH
DIV AB
MOV 41H,A
MOV 42H,B
RET
BUSY: MOV P3,#0FFH ;LCD忙检测
SETB E
CLR RS
SETB RW
NOP
NOP
BUSY0:MOV A,P3
JNB ACC.7,BUSY1
CLR E
NOP
SETB E
NOP
SJMP BUSY0
BUSY1:CLR E
RET
ENABLE:
SETB E ;LCD命令使能子程序
CALL DELAY
CLR E
RET
WRITE_COMM:CALLBUSY ;写命令子程序
MOV P3,R0
CLR RS
CLR RW
CALL ENABLE
RET
WRITE_DATA:CALLBUSY ;写数据子程序
MOV P3,R0
SETB RS
CLR RW
CALL ENABLE
INC R2
CJNE R2,#10H,WRITE3
WRITE1:CPL F0
JNB F0,WRITE2
MOV R0,#0C0H
CALL WRITE_COMM
ANL 02H,#0FH
SJMP WRITE3
WRITE2:MOV R0,#80H
CALL WRITE_COMM
ANL 02H,#0FH
WRITE3:RET
WRITE_STR:MOV R1,#00H ;写字符串至LCD子程序
LOOP1:MOV A,R1
MOVC A,@A+DPTR
MOV R0,A
CALL WRITE_DATA
INC R1
CJNE R0,#0C0H,LOOP1
RET
;写计数值对应的字符子程序
WRITE_CHAR:MOVR2,#3 ;计数值为3位
MOV P3,#0C0H ;LCD第2行地址
CLR RS
CLR RW
CALL ENABLE
MOV R1,#40H ;显示缓冲区首址
W1: MOV A,@R1
MOV DPTR,#TABLE2
MOVC A,@A+DPTR
MOV P3,A
SETB RS
CLR RW
CALL ENABLE
INC R1
DJNZ R2,W1
RET
DELAY: MOV R4,#05 ;延时子程序
LOOP2:MOV R5,#0FFH
DJNZ R5,$
DJNZ R4,LOOP2
RET
TABLE1:DB 'LM1602TESTNOW!'
TABLE2:DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39H;0~9的ASCII码表
END
C语言源程序:
#include<reg51.h>
#include<intrins.h>
#include<absacc.h>
#include<stdio.h> //含sprinf函数定义
sbitkey=P1^0; //端口定义
sbitRS=P2^5;
sbitRW=P2^6;
sbitE=P2^7;
#defineucharunsignedchar
#defineuintunsignedint
#defineBUSY0x80
voiddelay_LCD(ucharm) //延时程序
{
uinti,j;
for(i=0;i<m;i++)
{
for(j=0;j<60;j++);
}
}
void test_LCDbusy() //检测忙程序
{
P3=0xFF;
E=1;
RS=0;
RW=1;
_nop_();
while(P3&BUSY) //LCD的DB7=1,循环等待
{
E=0;
_nop_();
E=1;
_nop_();
}
E=0;
}
voidwrite_LCDcomm(ucharComm) //写命令
{
test_LCDbusy();
RS=0;
RW=0;
E=0;
_nop_();
P3=Comm;
_nop_();
E=1;
_nop_();
E=0;
}
voidwrite_LCDdata(ucharData) //写数据
{
test_LCDbusy();
P3=Data;
RS=1;
RW=0;
E=1;
_nop_();
E=0;
}
voidinit_LCD(void) //LCD初始化
{
write_LCDcomm(0x38);
delay_LCD(5);
write_LCDcomm(0x01);
delay_LCD(5);
write_LCDcomm(0x06);
delay_LCD(5);
write_LCDcomm(0x0F);
delay_LCD(5);
}
voiddisplayOneChar(ucharX,Y,Data) //显示一个字符,X、Y表示位置
{
Y=Y&0x01;
X=X&0x0F;
if(Y) //若Y=1,则显示第2行
X=X|0x40; //第2行地址码为第1行+0x40
X=X|0x80; //指令码为地址码+0x80
write_LCDcomm(X);
write_LCDdata(Data);
}
voiddisplay_LCD(ucharX,Y,uchar*Data) //显示字符串
{
ucharDataLength=0;
Y=Y&0x01;
X=X&0x0F;
while(X<16)
{
displayOneChar(X,Y,Data[DataLength]);
DataLength++;
X++;
}
}
voidmain() //主程序
{
ucharData[]="LM1602TESTNOW!";
intCount=0; //Count为计数器,检测按键次数
ucharstr[16];
ucharDisp_Buffer[]="";
delay_LCD(15);
init_LCD();
display_LCD(0,0,Data); //在LCD第1行显示字符串
delay_LCD(200);
delay_LCD(200);
delay_LCD(200);
while(1)
{
while(key==1) //等待按键合上
{;}
if(key==0)
{
delay_LCD(10);
Count=Count+1; //计数器加1
sprintf(str,"%s%d",Disp_Buffer,Count);//将整型数转换为字符串,存入str[16]
delay_LCD(15);
display_LCD(0,1,str); //在LCD第2行显示计数结果
delay_LCD(20);
while(key==0) //等待按键松开
{;}
}
}
}程序说明:
(1)汇编程序对按键计数值的显示,是要将计数值各位分离,并分别找到其对应的ASCII码显示。
(2)
C语言程序对按键计数值的显示,只要将按键计数值转换为字符串,调用相应的函数即可。8.3.4仿真分析
在Proteus中加载单片机控制程序(HEX文件),单击仿真按钮,则LCD1602液晶显示器的仿真结果如图8-4所示。LCD1602的第1行显示字符串“LCD1602TESTNOW!”;用鼠标控制按键(为瞬态开关)的切换,LCD1602第2行显示按键的计数值。
8.4.1仿真电路
创建中断优先级仿真电路,如图8-6所示。单片机的P0口接LED数码管(并外接上拉电阻,原因是P0口为漏极开路输出,接拉电流负载时需外接上拉电阻),显示主程序计数值;单片机的P1口接LED数码管,显示INT0(高优先级)中断程序计数值;单片机的P2口接LED数码管,显示INT1(低优先级)中断程序计数值。P3.2、P3.3接开关,产生外部中断(INT0、INT1)信号。8.4中断优先级的仿真与应用
图8-6中断优先级仿真电路仿真要求:
(1)执行主程序时,数码管均依次显示01→02→……→3E→3F→40并循环。
(2)
INT0、INT1中断程序执行时,数码管均依次显示01→02→……→3E→3F→40并退出。
(3)当有INT1(低优先级)中断请求时,能中断主程序的执行,但不能中断INT0(高优先级)程序的执行。
(4)当有INT0(高优先级)中断请求时,能中断主程序和INT1程序。8.4.2控制程序
汇编源程序:
LJMPINIT
ORG0003H ;INT0中断入口
LJMPEXT0
ORG0013H ;INT1中断入口
LJMPEXT1
LJMPMAIN
INIT:MOV SP,#20H ;设置堆栈指针
LCALL CLR_LED ;单片机端口初始化
LCALL INT_ENABLE ;中断设置与启动
;主程序
MAIN:MOV R5,#00H ;主程序计数器赋初值
M1:
INC R5 ;计数器加1
MOV P0,R5 ;计数值送P0口显示
LCALL DELAY ;延时
CJNE R5,#40H,M1 ;计数值等于40H,从初值开始重新计数
JMP MAIN
;INT0中断服务程序
EXT0:MOV R6,#00H
E0:INC R6
MOV P1,R6
LCALL DELAY
CJNE R6,#40H,E0
RETI
;INT1中断服务程序
EXT1:
MOVR7,#00H
E1:INC R7
MOV P2,R7
LCALL DELAY
CJNE R7,#40H,E1
RETI
;单片机端口初始化子程序
CLR_LED:
MOV P0,#00H
MOV P1,#00H
MOV P2,#00H
RET
;中断设置与启动子程序
INT_ENABLE:SETBIT0 ;设置为下降沿触发
SETBEX0 ;启动INT0
SETBPX0 ;INT0设置为高优先级
SETBIT1 ;设置为下降沿触发
SETBEX1 ;启动INT1
SETBEA ;开放总中断
RET;延时子程序
DELAY: MOV A,#0FFH
D1: MOV R0,#0FFH
DJNZ R0,$
DEC A
JNZ D1
RET
END
C语言源程序:
#include<reg51.h>
#defineucharunsignedchar
#defineuintunsignedint
voidDelay(uintx) //延时程序
{
uchart;
while(x--)for(t=0;t<120;t++);
}
voidInterrupt_Init() //中断初始化程序
{
IT0=1; //下降沿触发
EX0=1; //启动INT0中断
IT1=1; //下降沿触发
PX0=1; //设置INT0为高优先级
EX1=1; //启动INT1中断
EA=1; //开放总中断
}
voidmain() //主程序
{
ucharCount0; //主程序计数器
Interrupt_Init(); //中断初始化
P0=0x00; //单片机端口初始化
P1=0x00;
P2=0x00;
while(1)
{
Count0=0; //主程序计数器赋初值
while(Count0<0x40) //计数值小于40H时加1
{
Count0++;
Delay(200);
P0=Count0;
}
}
}
voidEX_INT0()interrupt0 //INT0中断服务程序(“0”为INT0的中断号)
{
ucharCount1=0;
while(Count1<0x40)
{
Count1++;
Delay(200);
P1=Count1;
}
}
voidEX_INT1()interrupt2 //INT1中断服务程序(“2”为INT1的中断号)
{
ucharCount2=0;
while(Count2<0x40)
{
Count2++;
Delay(200);
P2=Count2;
}
}8.4.3仿真分析
在Proteus中加载单片机控制程序(HEX文件),单击仿真按钮,则数码管循环显示主程序计数值。
当低优先级按键合上(INT1有中断请求)时,主程序中断计数,INT1中断计数器开始加1计数(从“0”加1至“40”),直至INT1中断服务程序结束后,主程序从中断点继续计数并循环。
在INT1计数的过程中,若高优先级按键合上(INT0有中断请求),则INT1中断服务程序中断计数,INT0中断计数器开始加1计数(从“0”加1至“40”),直至INT0中断服务程序结束后,INT1中断服务程序从中断点继续加1计数直至退出,主程序再从中断点继续计数并循环。
从仿真过程可以看出,高优先级可中断低优先级和主程序,低优先级可中断主程序但不能中断高优先级。仿真结果很好地演示了中断的概念。
8.5.1创建电路
创建定时器仿真电路(秒表),如图8-7所示。单片机的P0口接LED数码管(并外接上拉电阻,原因是P0口为漏极开路输出,接拉电流负载时需外接上拉电阻)的段显信号,P2.0、P2.1、P2.2分别接数码管的位显信号,P2.7接开关。LED数码管选用7SEG-MPX4-CA-BLUE(属于Optoelectronics类,共阳数码管)。8.5定时器的仿真与应用
图8-7定时器应用仿真电路(秒表)设计要求:用单片机定时器T0设计秒表,秒表精度为0.1秒。仿真开始后,第一次按键,秒表开始计时,最大计时时间为20秒;第二次按键,秒表停止计时,并显示计时时间;第三次按键,秒表清零,为下一次计时作准备。
定时器T0(50ms)初值计算:当T0作定时器用时,计数脉冲来自单片机内部,即每个机器周期产生一个计数脉冲,也即每个机器周期计数器加“1”。由于一个机器周期等于12个振荡器的脉冲周期,因此计数频率为振荡频率的1/12。单片机时钟频率为12MHz,则计数脉冲频率为1MHz(周期为1µs)。要产生50ms定时溢出,则需要计数50000次。当T0设置为十六进制定时器时,计数初值为216-50000
=15536
=
3CB0H。8.5.2控制程序
定时器应用(秒表)主程序流程图如图8-8所示。50ms定时中断服务程序流程图如图8-9所示。
图8-8定时器应用(秒表)主程序流程图
图8-950ms定时中断服务程序流程图汇编源程序:
KEY BITP2.7 ;按键端口定义
ORG 0000H
LJMP MAIN
ORG 000BH ;T0中断入口地址
LJMP TIMER0
ORG 0040H ;主程序存放地址
MAIN:
MOV TMOD,#00000001B ;T0为十六进制定时器/计数器
MOV TH0,#3CH ;定时器赋初值,定时时间为50ms
MOV TL0,#0B0H
SETB ET0 ;定时器T0允许
SETB EA ;开放总中断
MOV R0,#00H ;以50ms为单位的计数次数
MOV R1,#00H ;计时时间值(单位为0.1ms)
A0: JB KEY,A00 ;判断第一次按键是否合上
CALL DELAY
JB KEY,A00
SETB TR0 ;第一次按键合上,启动定时器T0
SETB EA
JNB KEY,$ ;等待按键松开
SJMP A1
A00: CALL DISPLAY
SJMP A0
A1: CALL DISPLAY
JB KEY,A1 ;判断第二次按键是否合上
CALL DELAY
JB KEY,A1
A2: CALL DELAY
JB KEY,A1
CLR EA ;第二次按键合上,T0停止
CALL DISPLAY
JNB KEY,$
A3: JB KEY,A33 ;判断第三次按键是否合上
CALL DELAY
JB KEY,A33
MOV R1,#00H ;第三次按键合上,计时值清零
JNB KEY,$
SJMP A0
A33: CALL DISPLAY
SJMP A3
;显示程序
DISPLAY:
MOV A,R1
MOV B,#100 ;分离计时值的百位,并调用相应的代码显示
DIV AB
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV P0,A
SETB P2.0 ;百位位显信号有效
CALL DELAY
CLR P2.0
MOV A,B ;余数(整除100后的余数存至B中)送至A,整除
;10以后,可分离计时值的十位
MOV B,#10
DIV AB
MOV DPTR,#TAB_DOT
MOVC A,@A+DPTR
MOV P0,A
SETB P2.1 ;十位位显信号有效
CALL DELAY
CLR P2.1
MOV A,B ;余数(整除10后的余数存至B中)即为个位
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV P0,A
SETB P2.2 ;十位位显信号有效
CALL DELAY
CLR P2.2
RET
;延时程序
DELAY:MOV R7,#20
D0:MOV R6,#250
DJNZ R6,$
DJNZ R7,D0
RET
;T0中断服务程序
TIMER0: MOV TH0,#3CH
MOV TL0,#0B0H
INC R0
CJNE R0,#02,D1 ;计满两次为0.1s
MOV R0,#00H
INC R1 ;每隔0.1s,计时值加1
CJNE R1,#200,D1
MOV R1,#00H
D1: RETI
TAB_DOT:DB40H,79H,24H,30H,19H,12H,02H,78H,00H,10H ;带小数点的显示码(共阳)
TAB: DB0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H;不带小数点的显示码
END
C语言源程序:
#include<reg51.h>
#defineucharunsignedchar
sbitkey=P2^7; //按键端口定义
sbitlow=P2^2; //位显信号定义
sbitmiddle=P2^1;
sbithigh=P2^0;
uchartime=0,count=0;
ucharcodedis_char[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //段显码
ucharcodedis_add_dot[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //段显码
//(带小数点)
voiddelay(ucharM) //延时程序
{
uchari,j;
for(i=0;i<M;i++)
for(j=0;j<125;j++);
}
voiddisplay(void) //显示程序
{
P0=dis_char[time/100]; //计时值的百位送LED显示
high=1;
delay(3);
high=0;
P0=dis_add_dot[(time%100)/10]; //计时值的十位送LED显示
middle=1;
delay(3);
middle=0;
P0=dis_char[time%10]; //计时值的十位送LED显示
low=1;
delay(3);
low=0;
}
voidmain() //主程序
{
TMOD=0x01; //T0为十六进制定时器/计数器
TH0=0x3C; //设置计数初值
TL0=0xB0;
IE=0x82; //允许T0中断、开放总中断
while(1)
{
while(key==1)
display();
while(key==0) //按键第一次合上,启动T0中断
display();
TR0=1;
EA=1;
while(key==1)
display();
while(key==0) //按键第二次合上,T0中断停止
{
display();
EA=0;
}
while(key==1)
display();
while(key==0) //按键第三次合上,计时值清零
display();
while(key==1)
{
display();
time=0;
}
}
}
voidTIMER0_INT()interrupt1 //T0中断服务程序
{
count++;
if(count==2) //计满两次为0.1s
{
time++; //每隔0.1s,计时值加1
count=0;
if(time==200)
time=0;
}
TH0=0x3C;
TL0=0xB0;
}8.5.3仿真分析
在Proteus中加载单片机控制程序(HEX文件),单击仿真按钮,则数码管显示“00.0”。
按键第一次合上,数码管开始计时,计时精度为0.1s,最大计时时间为20.0s;第二次按键合上,计时停止,并显示计时时间;第三次按键合上,计时时间清零,为下一次继续计时作准备。
读者可在此基础上,通过设定定时器的定时溢出时间,将计时精度提高到0.01秒。
8.6.1双机单向通信
双机单向通信即单工通信,是指主机发送数据或指令,从机接收数据或指令,信号为单方向传输。本例用一个单片机(甲机)作主机,另一个单片机(乙机)作从机,主机发送命令来控制从机。8.6单片机串行通信的仿真与应用设计要求:
(1)主机接开关,通过开关发送相应的指令给从机,从机接收主机指令,执行相应的操作。
(2)仿真开始后,按键第一次合上,控制从机发光管D1闪烁;按键第二次合上,控制从机发光管D2闪烁;按键第三次合上,控制从机发光管D1、D2均闪烁;按键第四次合上,控制从机发光管D1、D2均熄灭。
(3)主机发光管D1、D2同从机一样,按相同的流程亮与灭。
1.创建电路
创建单片机串行通信(单工方式)仿真电路,如图8-10所示。MAX232用来实现电平转换,即将单片机输出的数字电平转换为RS-232C接口电平。
图8-10单片机串行通信(单工方式)仿真电路
2.控制程序
1)编程思路
(1)由于主机与从机分别执行不同的任务,主机负责发送命令或停止发送命令,而从机则接收命令,因此,主机与从机的控制程序要分别编写。
(2)本处的两单片机均工作于串口模式1(即10位异步通信模式),主机程序和从机程序均需进行初始化设置,包括设置串口模式(SCON)、设置定时器T1的工作方式(TMOD)、给定时器T1赋初值、启动定时器T1。
(3)串口模式1传输波特率的计算公式为
波特率
=
(2SMOD/32)
×
定时器T1的溢出率
T1的初值TH1
=
TL1
=
0xFD(即253),T1的溢出率
=
fosc/(C12
×
(256
-
TH1)),fosc为单片机的晶振。PCON=0x00,SMOD为PCON的最高位,则SMOD
=
0。设单片机的晶振为11.0592MHz,代入上述表达式,得到波特率为9600b/s。
(4)主机和从机的串口通信均采用查询方式。主机程序通过查询发送标志TI,检测一帧数据是否发送完毕,当一帧数据发送完毕后,由硬件自动置TI=1;从机程序通过查询接收标志RI,检测一帧数据是否接收完毕,当一帧数据接收完毕后,由硬件自动置RI=1。注意在每次收发数据时,都要通过软件将RI、TI清零,为继续收发数据作准备。
(5)如果串口工作在中断方式,还要设置IE允许ES中断,并编写相应的中断服务程序。
2)控制程序流程图
单片机串行通信控制程序流程图(主机)如图8-11所示。单片机串行通信控制程序流程图(从机)如图8-12所示。图8-11单片机串行通信控制程序流程图(主机)图8-12单片机串行通信控制程序流程图(从机)
3)汇编源程序
主机控制程序:
D1BIT P0.0 ;发光管端口定义
D2BIT P0.1
KEY BITP3.5 ;按键端口定义
ORG 0000H ;主程序存放地址
LJMPMAIN
MAIN: MOV SCON,#40H ;(主机)串口工作方式1,禁止接收
MOV TMOD,#20H ;定时器T1工作方式2,8位自动重装初值
MOV PCON,#00H ;波特率不倍增
MOV TH1,#0FDH ;T1赋初值(波特率为9600b/s)
MOV TL1,#0FDH
CLR TI ;发送中断标志清零
SETB TR1 ;启动T1
LOP0: SETB D1 ;D1、D2熄灭
SETB D2
CALL DELAY
JB KEY,LOP0 ;检测按键第1次合上
JNB KEY,$ ;等待按键松开
LOP1:MOV R1,#1 ;发送“1”至串口
CALL PUTC_TO_PORT
CPL D1 ;D1闪烁、D2熄灭
SETB D2
CALL DELAY
JB KEY,LOP1 ;检测按键第2次合上
JNB KEY,$
LOP2: MOV R1,#2 ;发送“2”至串口
CALL PUTC_TO_PORT
SETB D1 ;D1熄灭、D2闪烁
CPL D2
CALL DELAY
JB KEY,LOP2 ;第3次检测按键合上
JNB KEY,$
LOP3: MOV R1,#3 ;发送“3”至串口
CALL PUTC_TO_PORT
CPL D1 ;D1、D2均闪烁
CPL D2
CALL DELAY
JB KEY,LOP3;第4次检测按键合上
JNB KEY,$
MOV R1,#4 ;发送“4”至串口
CALL PUTC_TO_PORT
AJMP LOP0
DELAY: MOV R7,#20 ;延时程序
DELAY1:
MOV R6,#250
DJNZ R6,$
DJNZ R7,DELAY1
RET
PUTC_TO_PORT:MOVSBUF,R1 ;发送数据至串口程序
JNB TI,$ ;等待一帧数据发送完(一帧数据发送完以后,
;由硬件置TI=1)
CLR TI ;TI清零(为继续发送数据作准备)
RET
END
从机控制程序:
D1BITP0.0 ;发光管端口定义
D2BITP0.1
ORG0000H
LJMPMAIN
MAIN: MOV SCON,#50H ;(从机)串口工作方式1,允许接收
MOV TMOD,#20H ;定时器T1工作方式2,8位自动重装初值
MOV PCON,#00H ;波特率不倍增
MOV TH1,#0FDH ;T1赋初值(波特率为9600b/s)
MOV TL1,#0FDH
CLR RI ;清除接收中断标志位
SETB TR1 ;启动T1
SETB D1 ;D1、D2均熄灭
SETB D2
LOP0:JNB RI,$ ;查询接收标志(等待一帧数据传送完)
CLR RI ;RI清零(为接收下一帧数据作准备)
MOV R0,SBUF ;将接收缓冲区的数据存入R0
CJNE R0,#1,LOP1 ;判断接收的数据是否为“1”
CPL D1 ;D1闪烁、D2熄灭
SETB D2
CALL DELAY
AJMP LOP0 ;跳转至LOP0(循环查询接收标志)
LOP1:CJNE R0,#2,LOP2 ;判断接收的数据是否为“2”
SETB D1 ;D1熄灭、D2闪烁
CPL D2
CALL DELAY
AJMP LOP0
LOP2: CJNE R0,#3,LOP3 ;判断接收的数据是否为“3”
CPL D1 ;D1、D2均闪烁
CPL D2
CALL DELAY
AJMP LOP0
LOP3: SETB D1 ;若接收的数据不是1、2、3中的一个,则D1、D2熄灭
SETB D2
AJMP LOP0
DELAY:MOV R7,#20 ;延时程序
DELAY1:MOV R6,#250
DJNZ R6,$
DJNZ R7,DELAY1
RET
END
4)
C语言源程序
主机控制程序:
#include<reg51.h>
#defineucharunsignedchar
#defineuintunsignedint
sbitD1=P0^0; //发光管端口定义
sbitD2=P0^1;
sbitKEY=P3^5; //按键端口定义
voiddelay(uintm) //延时程序
{
uchari;
while(m--)for(i=0;i<120;i++);
}
voidputchar_to_port(ucharc) //发送数据至串口程序
{
SBUF=c; //待发送数据存入发送缓冲区
while(TI==0); //等待一帧数据发送完(发送一帧数据后,由硬件置TI=1)
TI=0; //TI由软件清零(为继续发送数据作准备)
}
voidmain() //主程序
{
ucharkey_count=0; //按键合上次数
SCON=0x40; //(主机)串口方式1,禁止接收
TMOD=0x20;
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 无人机物流技术发展趋势-全面剖析
- 三年级数学因数中间或末尾有零的乘法综合检测题带答案
- 水准路线施工方案
- 英语绘本阅读行业跨境出海战略研究报告
- 陶瓷与雕塑展企业制定与实施新质生产力战略研究报告
- 阅读理解辅助行业深度调研及发展战略咨询报告
- 商业银行信贷AI应用行业跨境出海战略研究报告
- 逻辑思维训练中心行业深度调研及发展战略咨询报告
- 精神病人睡眠障碍护理
- 乙烯-丙烯酸丁酯橡胶行业跨境出海战略研究报告
- 2-山东工业技师学院申报国家级高技能人才培训基地项目申报书
- 常用消毒剂的分类、配制及使用课件演示幻灯片
- GB 45069-2024悬崖秋千安全技术要求
- 员工反恐怖协议
- 2025年高考政治一轮复习知识清单必修四《哲学与文化》重难点知识
- 2021年4月17日江苏事业单位考试《综合知识和能力素质》(管理岗客观题)
- 《临床技术操作规范-放射医学检查技术分册》
- 生活中的魔法数学名师公开课获奖课件百校联赛一等奖课件
- 2024年同等学力申硕英语考试真题
- 江苏省南京市六校2024-2025学年高一上学期期中联合调研 化学试题
- 儿科基础临床知识题库单选题100道及答案解析
评论
0/150
提交评论