版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第8章基于Proteus的51單片機(jī)一般應(yīng)用8.1基本輸入輸出的仿真與應(yīng)用8.2鍵盤掃描的仿真與應(yīng)用8.3LCD的仿真與應(yīng)用8.4中斷優(yōu)先級的仿真與應(yīng)用8.5定時(shí)器的仿真與應(yīng)用8.6單片機(jī)串行通信的仿真與應(yīng)用本章小結(jié)
本章系統(tǒng)敘述在Proteus環(huán)境中51單片機(jī)一般應(yīng)用系統(tǒng)的設(shè)計(jì)與仿真分析方法。
本章共分六節(jié),分別介紹了單片機(jī)基本輸入輸出的仿真與應(yīng)用、鍵盤掃描的仿真與應(yīng)用、LCD的仿真與應(yīng)用、中斷優(yōu)先級的仿真與應(yīng)用、定時(shí)器的仿真與應(yīng)用、單片機(jī)串口通信的仿真與應(yīng)用。內(nèi)容提要
8.1.1仿真電路
創(chuàng)建單片機(jī)輸入輸出仿真電路,如圖8-1所示。8.1基本輸入輸出的仿真與應(yīng)用
圖8-1單片機(jī)輸入輸出仿真電路輸入為四個(gè)開關(guān)(SW1~SW4),輸出為四個(gè)LED二極管(D1~D4),LED二極管接成灌電流形式。要求:當(dāng)開關(guān)SW1切換至上觸點(diǎn)時(shí),D1發(fā)光;當(dāng)開關(guān)SW1切換至下觸點(diǎn)時(shí),D1不發(fā)光。同理,開關(guān)SW2對應(yīng)D2,開關(guān)SW3對應(yīng)D3、開關(guān)SW4對應(yīng)D4。8.1.2控制程序
匯編源程序:
ORG0000H
LJMPMAIN
MAIN:
MOVA,P1 ;讀P1口數(shù)據(jù)(即獲取開關(guān)狀態(tài))
CPLA ;P1口數(shù)據(jù)取反(因LED接成灌電流形式)
MOVP0,A ;送P0口
JMPMAIN
END
C語言源程序:
#include<reg51.h> //編譯器中包含對51單片機(jī)的定義
#defineucharunsignedchar
voidmain()
{
ucharled; //無符號字符,值域范圍為0~255
while(1)
{
led=P1; //讀P1口數(shù)據(jù)
led=~led; //P1口數(shù)據(jù)取反
P0=led; //送P0口
}
}
注:C語言程序中的變量P0、P1要大寫。8.1.3仿真分析
在Proteus中加載單片機(jī)控制程序(HEX文件),單擊仿真按鈕,則單片機(jī)輸入輸出電路的仿真結(jié)果如圖8-1所示。仿真時(shí),用鼠標(biāo)控制開關(guān)SW1~SW4的切換,以觀察LED發(fā)光管的亮滅情況。
8.2.1仿真電路
創(chuàng)建鍵盤掃描仿真電路,如圖8-2所示。單片機(jī)的P3口產(chǎn)生鍵盤的行列信號,P0口接數(shù)碼管,顯示鍵盤編號。單片機(jī)時(shí)鐘設(shè)置為12MHz。
鍵盤掃描的原理是采用行列掃描法。首先判斷有無鍵按下,在有鍵按下的情況下,使一條行線輸出為低電平,若該行線上有鍵按下,則相應(yīng)的列線狀態(tài)也為低電平。由行線號和列線號即可得到對應(yīng)按鍵的編號。8.2鍵盤掃描的仿真與應(yīng)用圖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存儲(chǔ)
MOVR4,A
SETBC
MOVR5,#04H ;列掃描數(shù)
LOOP3: RLCA ;列掃描值帶進(jìn)位左移
JNCKEYIN ;C=0,跳轉(zhuǎn)至按鍵輸入程序
INCR1 ;鍵碼地址加1
DJNZ
R5,LOOP3 ;4列掃描完畢?
MOVA,R3 ;置行掃描值,掃描下一行
SETBC ;當(dāng)右移時(shí)移入“1”
RRCA
MOVR3,A
JC LOOP2 ;行掃描完畢?
JMP LOOP1
KEYIN: MOVR7,#10 ;延時(shí)去抖動(dòng)
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;七段數(shù)碼管顯示代碼表
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, //七段數(shù)碼管顯示代碼表
0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
voiddelay(uinti) //延時(shí)子程序
{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); //延時(shí)去抖動(dòng)
if(checkkey()==0)return(0xFF); //沒有按鍵合上
else
{
scancode=0xF7; //從上到下的第一條行線置低電平
m=0x00; //m表示列線數(shù)量
for(i=1;i<=4;i++) //行掃描
{
k=0x10;
P3=scancode;
a=P3;
for(j=0;j<4;j++) //列掃描
{
if((a&k)==0) //若有按鍵合上,對應(yīng)的列線為低電平
{
codeaddr=m+j;
while(checkkey()!=0);
return(codeaddr);
}
k=k<<1; //檢測下一列
}
m=m+4; //表示列線數(shù)量為4
scancode=~scancode; //掃描碼右移時(shí),右移的數(shù)為1
scancode=scancode>>1;
scancode=~scancode;
}
}
}
}
voidmain()
{
intn;
P0=0x00; //P0口初始化
while(1)
{
if(checkkey()==0x00)continue; //若沒有按鍵合上,轉(zhuǎn)向下一次循環(huán)
else
{
n=keyscan(); //得到鍵碼地址
P0=a[n]; //取鍵碼送P0口顯示
delay(100);
}
}
}8.2.3仿真分析
在Proteus中加載單片機(jī)控制程序(HEX文件),單擊仿真按鈕,則單片機(jī)鍵盤掃描電路的仿真結(jié)果如圖8-2所示。仿真時(shí),用鼠標(biāo)控制開關(guān)(為瞬態(tài)開關(guān))的切換,數(shù)碼管顯示對應(yīng)按鍵的編號。16個(gè)開關(guān)從左到右、從上到下依次編號為0~F。
8.3.1仿真電路
創(chuàng)建LCD1602液晶顯示仿真電路,如圖8-4所示。單片機(jī)的P1.0檢測按鍵信號,P3口接LCD的數(shù)據(jù)線,LCD的控制信號由P2.5、P2.6、P2.7產(chǎn)生。LCD1602在Proteus中的名稱為LM016L,所屬類為Optoelectronics,位于DISPLAY庫。8.3LCD的仿真與應(yīng)用圖8-4LCD1602液晶顯示仿真電路仿真要求:LCD第一行顯示“LM1602TESTNOW!”,第二行顯示按鍵的計(jì)數(shù)值(即按鍵每合上一次,計(jì)數(shù)值加1)。8.3.2LCD1602簡介
LCD1602字符型顯示器是2行
×
16個(gè)字符的液晶顯示器。該器件由32個(gè)字符點(diǎn)陣組成,可以顯示ASCII碼表中的所有可顯示字符。
1.LCD1602的引腳功能
(1)
VSS:供電電源地。
(2)
VDD:供電電源輸入端(接
+5V)。
(3)
VEE:LCD對比度調(diào)整。接正電源時(shí),對比度最弱;接地時(shí),對比度最強(qiáng)。使用時(shí)可用一個(gè)電位器調(diào)整其對比度。
(4)
RS:寄存器選擇輸入端。
RS=0,選擇指令寄存器,可以寫指令、讀LCD忙標(biāo)志和地址計(jì)數(shù)器。
RS=1,選擇數(shù)據(jù)寄存器,可以寫或讀數(shù)據(jù)。
2.LCD1602指令集
LCD1602字符型顯示器模塊內(nèi)部有兩種寄存器:指令寄存器和數(shù)據(jù)寄存器。LCD1602在應(yīng)用時(shí),首先要對LCD進(jìn)行初始化操作(單片機(jī)向指令寄存器寫不同的指令數(shù)據(jù)),然后確定顯示字符的地址,最后將待顯示的字符寫入LCD的數(shù)據(jù)寄存器中。LCD1602的指令集如表8-1所示。
表8-1LCD1602的指令集表8-1中的字符說明:
X:0或1。
I/D:顯示地址計(jì)數(shù)器模式選擇。I/D=0,減1模式;I/D=1,加1模式。
S:顯示屏移動(dòng)控制位。S=0,顯示屏不移動(dòng);S=1,如果I/D=1且有字符寫入時(shí)顯示屏左移,否則右移。
D:顯示屏開關(guān)控制位。D=1,顯示屏開;D=0,顯示屏關(guān)。
C:光標(biāo)開關(guān)控制位。C=1,光標(biāo)開;C=0,光標(biāo)關(guān)。
B:光標(biāo)閃爍控制位。B=1,光標(biāo)閃爍;B=0,光標(biāo)不閃爍。
S/C:顯示屏/光標(biāo)移位選擇。S/C=1,顯示屏移位;S/C=0,光標(biāo)移位。
R/L:移位方向選擇。R/L=1,右移;R/L=0,左移。
DL:傳輸數(shù)據(jù)有效位長度選擇。DL=1,有效位為8位;DL=0,有效位為4位。
N:顯示器行數(shù)選擇。N=1,雙行顯示;N=0,單行顯示。
F:字符點(diǎn)陣塊的點(diǎn)陣選擇。F=1,選擇5
×
10點(diǎn)陣;F=0,選擇5
×
7點(diǎn)陣。
BF:忙標(biāo)志位。BF=1,LCD忙;BF=0,LCD就緒。
CGRAM:字符發(fā)生器RAM。用戶自編程的字符或圖形存儲(chǔ)器。
DDRAM:顯示數(shù)據(jù)RAM。
LCD1602的顯示數(shù)據(jù)存儲(chǔ)器DDRAM與顯示屏上的字符顯示位置是一一對應(yīng)的。DDRAM的地址與字符顯示位置的對應(yīng)關(guān)系如表8-2所示。當(dāng)主控制器需要將字符顯示在屏幕的某一位置時(shí),首先將對應(yīng)位置的DDRAM的地址寫至地址計(jì)數(shù)器(指令寄存器)中,再將該字符的ASCII碼寫入DDRAM中,這樣即可完成一個(gè)字符的顯示。
表8-2DDRAM的地址與字符顯示位置的對應(yīng)關(guān)系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位數(shù)據(jù)),N=1(雙行顯示)
CALL WRITE_COMM
MOV R0,#0FH ;D=1(顯示屏開),C=1(顯示光標(biāo)),B=1(光標(biāo)閃爍)
CALL WRITE_COMM
MOV R0,#06H ;I/D=1(加1),S=0(顯示屏不移動(dòng))
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為檢測按鍵計(jì)數(shù)器
KEY1: JB KEY,$ ;等待按鍵合上
CALL DELAY ;延時(shí)去抖動(dòng)
INC R7 ;計(jì)數(shù)器加1
CJNE R7,#255,KEY2 ;是否計(jì)滿?
JNB KEY,$ ;等待按鍵松開
JMP KEY0 ;計(jì)滿,則跳轉(zhuǎn)至KEY0,將計(jì)數(shù)器清0
KEY2: CALL DIVIDE ;調(diào)用計(jì)數(shù)值分離子程序
CALL WRITE_CHAR ;在LCD第2行顯示計(jì)數(shù)值對應(yīng)的字符
JNB P1.0,$ ;等待按鍵松開
LJMP KEY1
DIVIDE:MOV A,R7 ;計(jì)數(shù)值分離子程序,三位計(jì)數(shù)值分離后分別存入;顯示緩沖區(qū)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 ;寫數(shù)據(jù)子程序
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
;寫計(jì)數(shù)值對應(yīng)的字符子程序
WRITE_CHAR:MOVR2,#3 ;計(jì)數(shù)值為3位
MOV P3,#0C0H ;LCD第2行地址
CLR RS
CLR RW
CALL ENABLE
MOV R1,#40H ;顯示緩沖區(qū)首址
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 ;延時(shí)子程序
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函數(shù)定義
sbitkey=P1^0; //端口定義
sbitRS=P2^5;
sbitRW=P2^6;
sbitE=P2^7;
#defineucharunsignedchar
#defineuintunsignedint
#defineBUSY0x80
voiddelay_LCD(ucharm) //延時(shí)程序
{
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,循環(huán)等待
{
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) //寫數(shù)據(jù)
{
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) //顯示一個(gè)字符,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為計(jì)數(shù)器,檢測按鍵次數(shù)
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; //計(jì)數(shù)器加1
sprintf(str,"%s%d",Disp_Buffer,Count);//將整型數(shù)轉(zhuǎn)換為字符串,存入str[16]
delay_LCD(15);
display_LCD(0,1,str); //在LCD第2行顯示計(jì)數(shù)結(jié)果
delay_LCD(20);
while(key==0) //等待按鍵松開
{;}
}
}
}程序說明:
(1)匯編程序?qū)Π存I計(jì)數(shù)值的顯示,是要將計(jì)數(shù)值各位分離,并分別找到其對應(yīng)的ASCII碼顯示。
(2)
C語言程序?qū)Π存I計(jì)數(shù)值的顯示,只要將按鍵計(jì)數(shù)值轉(zhuǎn)換為字符串,調(diào)用相應(yīng)的函數(shù)即可。8.3.4仿真分析
在Proteus中加載單片機(jī)控制程序(HEX文件),單擊仿真按鈕,則LCD1602液晶顯示器的仿真結(jié)果如圖8-4所示。LCD1602的第1行顯示字符串“LCD1602TESTNOW!”;用鼠標(biāo)控制按鍵(為瞬態(tài)開關(guān))的切換,LCD1602第2行顯示按鍵的計(jì)數(shù)值。
8.4.1仿真電路
創(chuàng)建中斷優(yōu)先級仿真電路,如圖8-6所示。單片機(jī)的P0口接LED數(shù)碼管(并外接上拉電阻,原因是P0口為漏極開路輸出,接拉電流負(fù)載時(shí)需外接上拉電阻),顯示主程序計(jì)數(shù)值;單片機(jī)的P1口接LED數(shù)碼管,顯示INT0(高優(yōu)先級)中斷程序計(jì)數(shù)值;單片機(jī)的P2口接LED數(shù)碼管,顯示INT1(低優(yōu)先級)中斷程序計(jì)數(shù)值。P3.2、P3.3接開關(guān),產(chǎn)生外部中斷(INT0、INT1)信號。8.4中斷優(yōu)先級的仿真與應(yīng)用
圖8-6中斷優(yōu)先級仿真電路仿真要求:
(1)執(zhí)行主程序時(shí),數(shù)碼管均依次顯示01→02→……→3E→3F→40并循環(huán)。
(2)
INT0、INT1中斷程序執(zhí)行時(shí),數(shù)碼管均依次顯示01→02→……→3E→3F→40并退出。
(3)當(dāng)有INT1(低優(yōu)先級)中斷請求時(shí),能中斷主程序的執(zhí)行,但不能中斷INT0(高優(yōu)先級)程序的執(zhí)行。
(4)當(dāng)有INT0(高優(yōu)先級)中斷請求時(shí),能中斷主程序和INT1程序。8.4.2控制程序
匯編源程序:
LJMPINIT
ORG0003H ;INT0中斷入口
LJMPEXT0
ORG0013H ;INT1中斷入口
LJMPEXT1
LJMPMAIN
INIT:MOV SP,#20H ;設(shè)置堆棧指針
LCALL CLR_LED ;單片機(jī)端口初始化
LCALL INT_ENABLE ;中斷設(shè)置與啟動(dòng)
;主程序
MAIN:MOV R5,#00H ;主程序計(jì)數(shù)器賦初值
M1:
INC R5 ;計(jì)數(shù)器加1
MOV P0,R5 ;計(jì)數(shù)值送P0口顯示
LCALL DELAY ;延時(shí)
CJNE R5,#40H,M1 ;計(jì)數(shù)值等于40H,從初值開始重新計(jì)數(shù)
JMP MAIN
;INT0中斷服務(wù)程序
EXT0:MOV R6,#00H
E0:INC R6
MOV P1,R6
LCALL DELAY
CJNE R6,#40H,E0
RETI
;INT1中斷服務(wù)程序
EXT1:
MOVR7,#00H
E1:INC R7
MOV P2,R7
LCALL DELAY
CJNE R7,#40H,E1
RETI
;單片機(jī)端口初始化子程序
CLR_LED:
MOV P0,#00H
MOV P1,#00H
MOV P2,#00H
RET
;中斷設(shè)置與啟動(dòng)子程序
INT_ENABLE:SETBIT0 ;設(shè)置為下降沿觸發(fā)
SETBEX0 ;啟動(dòng)INT0
SETBPX0 ;INT0設(shè)置為高優(yōu)先級
SETBIT1 ;設(shè)置為下降沿觸發(fā)
SETBEX1 ;啟動(dòng)INT1
SETBEA ;開放總中斷
RET;延時(shí)子程序
DELAY: MOV A,#0FFH
D1: MOV R0,#0FFH
DJNZ R0,$
DEC A
JNZ D1
RET
END
C語言源程序:
#include<reg51.h>
#defineucharunsignedchar
#defineuintunsignedint
voidDelay(uintx) //延時(shí)程序
{
uchart;
while(x--)for(t=0;t<120;t++);
}
voidInterrupt_Init() //中斷初始化程序
{
IT0=1; //下降沿觸發(fā)
EX0=1; //啟動(dòng)INT0中斷
IT1=1; //下降沿觸發(fā)
PX0=1; //設(shè)置INT0為高優(yōu)先級
EX1=1; //啟動(dòng)INT1中斷
EA=1; //開放總中斷
}
voidmain() //主程序
{
ucharCount0; //主程序計(jì)數(shù)器
Interrupt_Init(); //中斷初始化
P0=0x00; //單片機(jī)端口初始化
P1=0x00;
P2=0x00;
while(1)
{
Count0=0; //主程序計(jì)數(shù)器賦初值
while(Count0<0x40) //計(jì)數(shù)值小于40H時(shí)加1
{
Count0++;
Delay(200);
P0=Count0;
}
}
}
voidEX_INT0()interrupt0 //INT0中斷服務(wù)程序(“0”為INT0的中斷號)
{
ucharCount1=0;
while(Count1<0x40)
{
Count1++;
Delay(200);
P1=Count1;
}
}
voidEX_INT1()interrupt2 //INT1中斷服務(wù)程序(“2”為INT1的中斷號)
{
ucharCount2=0;
while(Count2<0x40)
{
Count2++;
Delay(200);
P2=Count2;
}
}8.4.3仿真分析
在Proteus中加載單片機(jī)控制程序(HEX文件),單擊仿真按鈕,則數(shù)碼管循環(huán)顯示主程序計(jì)數(shù)值。
當(dāng)?shù)蛢?yōu)先級按鍵合上(INT1有中斷請求)時(shí),主程序中斷計(jì)數(shù),INT1中斷計(jì)數(shù)器開始加1計(jì)數(shù)(從“0”加1至“40”),直至INT1中斷服務(wù)程序結(jié)束后,主程序從中斷點(diǎn)繼續(xù)計(jì)數(shù)并循環(huán)。
在INT1計(jì)數(shù)的過程中,若高優(yōu)先級按鍵合上(INT0有中斷請求),則INT1中斷服務(wù)程序中斷計(jì)數(shù),INT0中斷計(jì)數(shù)器開始加1計(jì)數(shù)(從“0”加1至“40”),直至INT0中斷服務(wù)程序結(jié)束后,INT1中斷服務(wù)程序從中斷點(diǎn)繼續(xù)加1計(jì)數(shù)直至退出,主程序再從中斷點(diǎn)繼續(xù)計(jì)數(shù)并循環(huán)。
從仿真過程可以看出,高優(yōu)先級可中斷低優(yōu)先級和主程序,低優(yōu)先級可中斷主程序但不能中斷高優(yōu)先級。仿真結(jié)果很好地演示了中斷的概念。
8.5.1創(chuàng)建電路
創(chuàng)建定時(shí)器仿真電路(秒表),如圖8-7所示。單片機(jī)的P0口接LED數(shù)碼管(并外接上拉電阻,原因是P0口為漏極開路輸出,接拉電流負(fù)載時(shí)需外接上拉電阻)的段顯信號,P2.0、P2.1、P2.2分別接數(shù)碼管的位顯信號,P2.7接開關(guān)。LED數(shù)碼管選用7SEG-MPX4-CA-BLUE(屬于Optoelectronics類,共陽數(shù)碼管)。8.5定時(shí)器的仿真與應(yīng)用
圖8-7定時(shí)器應(yīng)用仿真電路(秒表)設(shè)計(jì)要求:用單片機(jī)定時(shí)器T0設(shè)計(jì)秒表,秒表精度為0.1秒。仿真開始后,第一次按鍵,秒表開始計(jì)時(shí),最大計(jì)時(shí)時(shí)間為20秒;第二次按鍵,秒表停止計(jì)時(shí),并顯示計(jì)時(shí)時(shí)間;第三次按鍵,秒表清零,為下一次計(jì)時(shí)作準(zhǔn)備。
定時(shí)器T0(50ms)初值計(jì)算:當(dāng)T0作定時(shí)器用時(shí),計(jì)數(shù)脈沖來自單片機(jī)內(nèi)部,即每個(gè)機(jī)器周期產(chǎn)生一個(gè)計(jì)數(shù)脈沖,也即每個(gè)機(jī)器周期計(jì)數(shù)器加“1”。由于一個(gè)機(jī)器周期等于12個(gè)振蕩器的脈沖周期,因此計(jì)數(shù)頻率為振蕩頻率的1/12。單片機(jī)時(shí)鐘頻率為12MHz,則計(jì)數(shù)脈沖頻率為1MHz(周期為1μs)。要產(chǎn)生50ms定時(shí)溢出,則需要計(jì)數(shù)50000次。當(dāng)T0設(shè)置為十六進(jìn)制定時(shí)器時(shí),計(jì)數(shù)初值為216-50000
=15536
=
3CB0H。8.5.2控制程序
定時(shí)器應(yīng)用(秒表)主程序流程圖如圖8-8所示。50ms定時(shí)中斷服務(wù)程序流程圖如圖8-9所示。
圖8-8定時(shí)器應(yīng)用(秒表)主程序流程圖
圖8-950ms定時(shí)中斷服務(wù)程序流程圖匯編源程序:
KEY BITP2.7 ;按鍵端口定義
ORG 0000H
LJMP MAIN
ORG 000BH ;T0中斷入口地址
LJMP TIMER0
ORG 0040H ;主程序存放地址
MAIN:
MOV TMOD,#00000001B ;T0為十六進(jìn)制定時(shí)器/計(jì)數(shù)器
MOV TH0,#3CH ;定時(shí)器賦初值,定時(shí)時(shí)間為50ms
MOV TL0,#0B0H
SETB ET0 ;定時(shí)器T0允許
SETB EA ;開放總中斷
MOV R0,#00H ;以50ms為單位的計(jì)數(shù)次數(shù)
MOV R1,#00H ;計(jì)時(shí)時(shí)間值(單位為0.1ms)
A0: JB KEY,A00 ;判斷第一次按鍵是否合上
CALL DELAY
JB KEY,A00
SETB TR0 ;第一次按鍵合上,啟動(dòng)定時(shí)器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 ;第三次按鍵合上,計(jì)時(shí)值清零
JNB KEY,$
SJMP A0
A33: CALL DISPLAY
SJMP A3
;顯示程序
DISPLAY:
MOV A,R1
MOV B,#100 ;分離計(jì)時(shí)值的百位,并調(diào)用相應(yīng)的代碼顯示
DIV AB
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV P0,A
SETB P2.0 ;百位位顯信號有效
CALL DELAY
CLR P2.0
MOV A,B ;余數(shù)(整除100后的余數(shù)存至B中)送至A,整除
;10以后,可分離計(jì)時(shí)值的十位
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 ;余數(shù)(整除10后的余數(shù)存至B中)即為個(gè)位
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV P0,A
SETB P2.2 ;十位位顯信號有效
CALL DELAY
CLR P2.2
RET
;延時(shí)程序
DELAY:MOV R7,#20
D0:MOV R6,#250
DJNZ R6,$
DJNZ R7,D0
RET
;T0中斷服務(wù)程序
TIMER0: MOV TH0,#3CH
MOV TL0,#0B0H
INC R0
CJNE R0,#02,D1 ;計(jì)滿兩次為0.1s
MOV R0,#00H
INC R1 ;每隔0.1s,計(jì)時(shí)值加1
CJNE R1,#200,D1
MOV R1,#00H
D1: RETI
TAB_DOT:DB40H,79H,24H,30H,19H,12H,02H,78H,00H,10H ;帶小數(shù)點(diǎn)的顯示碼(共陽)
TAB: DB0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H;不帶小數(shù)點(diǎn)的顯示碼
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}; //段顯碼
//(帶小數(shù)點(diǎn))
voiddelay(ucharM) //延時(shí)程序
{
uchari,j;
for(i=0;i<M;i++)
for(j=0;j<125;j++);
}
voiddisplay(void) //顯示程序
{
P0=dis_char[time/100]; //計(jì)時(shí)值的百位送LED顯示
high=1;
delay(3);
high=0;
P0=dis_add_dot[(time%100)/10]; //計(jì)時(shí)值的十位送LED顯示
middle=1;
delay(3);
middle=0;
P0=dis_char[time%10]; //計(jì)時(shí)值的十位送LED顯示
low=1;
delay(3);
low=0;
}
voidmain() //主程序
{
TMOD=0x01; //T0為十六進(jìn)制定時(shí)器/計(jì)數(shù)器
TH0=0x3C; //設(shè)置計(jì)數(shù)初值
TL0=0xB0;
IE=0x82; //允許T0中斷、開放總中斷
while(1)
{
while(key==1)
display();
while(key==0) //按鍵第一次合上,啟動(dòng)T0中斷
display();
TR0=1;
EA=1;
while(key==1)
display();
while(key==0) //按鍵第二次合上,T0中斷停止
{
display();
EA=0;
}
while(key==1)
display();
while(key==0) //按鍵第三次合上,計(jì)時(shí)值清零
display();
while(key==1)
{
display();
time=0;
}
}
}
voidTIMER0_INT()interrupt1 //T0中斷服務(wù)程序
{
count++;
if(count==2) //計(jì)滿兩次為0.1s
{
time++; //每隔0.1s,計(jì)時(shí)值加1
count=0;
if(time==200)
time=0;
}
TH0=0x3C;
TL0=0xB0;
}8.5.3仿真分析
在Proteus中加載單片機(jī)控制程序(HEX文件),單擊仿真按鈕,則數(shù)碼管顯示“00.0”。
按鍵第一次合上,數(shù)碼管開始計(jì)時(shí),計(jì)時(shí)精度為0.1s,最大計(jì)時(shí)時(shí)間為20.0s;第二次按鍵合上,計(jì)時(shí)停止,并顯示計(jì)時(shí)時(shí)間;第三次按鍵合上,計(jì)時(shí)時(shí)間清零,為下一次繼續(xù)計(jì)時(shí)作準(zhǔn)備。
讀者可在此基礎(chǔ)上,通過設(shè)定定時(shí)器的定時(shí)溢出時(shí)間,將計(jì)時(shí)精度提高到0.01秒。
8.6.1雙機(jī)單向通信
雙機(jī)單向通信即單工通信,是指主機(jī)發(fā)送數(shù)據(jù)或指令,從機(jī)接收數(shù)據(jù)或指令,信號為單方向傳輸。本例用一個(gè)單片機(jī)(甲機(jī))作主機(jī),另一個(gè)單片機(jī)(乙機(jī))作從機(jī),主機(jī)發(fā)送命令來控制從機(jī)。8.6單片機(jī)串行通信的仿真與應(yīng)用設(shè)計(jì)要求:
(1)主機(jī)接開關(guān),通過開關(guān)發(fā)送相應(yīng)的指令給從機(jī),從機(jī)接收主機(jī)指令,執(zhí)行相應(yīng)的操作。
(2)仿真開始后,按鍵第一次合上,控制從機(jī)發(fā)光管D1閃爍;按鍵第二次合上,控制從機(jī)發(fā)光管D2閃爍;按鍵第三次合上,控制從機(jī)發(fā)光管D1、D2均閃爍;按鍵第四次合上,控制從機(jī)發(fā)光管D1、D2均熄滅。
(3)主機(jī)發(fā)光管D1、D2同從機(jī)一樣,按相同的流程亮與滅。
1.創(chuàng)建電路
創(chuàng)建單片機(jī)串行通信(單工方式)仿真電路,如圖8-10所示。MAX232用來實(shí)現(xiàn)電平轉(zhuǎn)換,即將單片機(jī)輸出的數(shù)字電平轉(zhuǎn)換為RS-232C接口電平。
圖8-10單片機(jī)串行通信(單工方式)仿真電路
2.控制程序
1)編程思路
(1)由于主機(jī)與從機(jī)分別執(zhí)行不同的任務(wù),主機(jī)負(fù)責(zé)發(fā)送命令或停止發(fā)送命令,而從機(jī)則接收命令,因此,主機(jī)與從機(jī)的控制程序要分別編寫。
(2)本處的兩單片機(jī)均工作于串口模式1(即10位異步通信模式),主機(jī)程序和從機(jī)程序均需進(jìn)行初始化設(shè)置,包括設(shè)置串口模式(SCON)、設(shè)置定時(shí)器T1的工作方式(TMOD)、給定時(shí)器T1賦初值、啟動(dòng)定時(shí)器T1。
(3)串口模式1傳輸波特率的計(jì)算公式為
波特率
=
(2SMOD/32)
×
定時(shí)器T1的溢出率
T1的初值TH1
=
TL1
=
0xFD(即253),T1的溢出率
=
fosc/(C12
×
(256
-
TH1)),fosc為單片機(jī)的晶振。PCON=0x00,SMOD為PCON的最高位,則SMOD
=
0。設(shè)單片機(jī)的晶振為11.0592MHz,代入上述表達(dá)式,得到波特率為9600b/s。
(4)主機(jī)和從機(jī)的串口通信均采用查詢方式。主機(jī)程序通過查詢發(fā)送標(biāo)志TI,檢測一幀數(shù)據(jù)是否發(fā)送完畢,當(dāng)一幀數(shù)據(jù)發(fā)送完畢后,由硬件自動(dòng)置TI=1;從機(jī)程序通過查詢接收標(biāo)志RI,檢測一幀數(shù)據(jù)是否接收完畢,當(dāng)一幀數(shù)據(jù)接收完畢后,由硬件自動(dòng)置RI=1。注意在每次收發(fā)數(shù)據(jù)時(shí),都要通過軟件將RI、TI清零,為繼續(xù)收發(fā)數(shù)據(jù)作準(zhǔn)備。
(5)如果串口工作在中斷方式,還要設(shè)置IE允許ES中斷,并編寫相應(yīng)的中斷服務(wù)程序。
2)控制程序流程圖
單片機(jī)串行通信控制程序流程圖(主機(jī))如圖8-11所示。單片機(jī)串行通信控制程序流程圖(從機(jī))如圖8-12所示。圖8-11單片機(jī)串行通信控制程序流程圖(主機(jī))圖8-12單片機(jī)串行通信控制程序流程圖(從機(jī))
3)匯編源程序
主機(jī)控制程序:
D1BIT P0.0 ;發(fā)光管端口定義
D2BIT P0.1
KEY BITP3.5 ;按鍵端口定義
ORG 0000H ;主程序存放地址
LJMPMAIN
MAIN: MOV SCON,#40H ;(主機(jī))串口工作方式1,禁止接收
MOV TMOD,#20H ;定時(shí)器T1工作方式2,8位自動(dòng)重裝初值
MOV PCON,#00H ;波特率不倍增
MOV TH1,#0FDH ;T1賦初值(波特率為9600b/s)
MOV TL1,#0FDH
CLR TI ;發(fā)送中斷標(biāo)志清零
SETB TR1 ;啟動(dòng)T1
LOP0: SETB D1 ;D1、D2熄滅
SETB D2
CALL DELAY
JB KEY,LOP0 ;檢測按鍵第1次合上
JNB KEY,$ ;等待按鍵松開
LOP1:MOV R1,#1 ;發(fā)送“1”至串口
CALL PUTC_TO_PORT
CPL D1 ;D1閃爍、D2熄滅
SETB D2
CALL DELAY
JB KEY,LOP1 ;檢測按鍵第2次合上
JNB KEY,$
LOP2: MOV R1,#2 ;發(fā)送“2”至串口
CALL PUTC_TO_PORT
SETB D1 ;D1熄滅、D2閃爍
CPL D2
CALL DELAY
JB KEY,LOP2 ;第3次檢測按鍵合上
JNB KEY,$
LOP3: MOV R1,#3 ;發(fā)送“3”至串口
CALL PUTC_TO_PORT
CPL D1 ;D1、D2均閃爍
CPL D2
CALL DELAY
JB KEY,LOP3;第4次檢測按鍵合上
JNB KEY,$
MOV R1,#4 ;發(fā)送“4”至串口
CALL PUTC_TO_PORT
AJMP LOP0
DELAY: MOV R7,#20 ;延時(shí)程序
DELAY1:
MOV R6,#250
DJNZ R6,$
DJNZ R7,DELAY1
RET
PUTC_TO_PORT:MOVSBUF,R1 ;發(fā)送數(shù)據(jù)至串口程序
JNB TI,$ ;等待一幀數(shù)據(jù)發(fā)送完(一幀數(shù)據(jù)發(fā)送完以后,
;由硬件置TI=1)
CLR TI ;TI清零(為繼續(xù)發(fā)送數(shù)據(jù)作準(zhǔn)備)
RET
END
從機(jī)控制程序:
D1BITP0.0 ;發(fā)光管端口定義
D2BITP0.1
ORG0000H
LJMPMAIN
MAIN: MOV SCON,#50H ;(從機(jī))串口工作方式1,允許接收
MOV TMOD,#20H ;定時(shí)器T1工作方式2,8位自動(dòng)重裝初值
MOV PCON,#00H ;波特率不倍增
MOV TH1,#0FDH ;T1賦初值(波特率為9600b/s)
MOV TL1,#0FDH
CLR RI ;清除接收中斷標(biāo)志位
SETB TR1 ;啟動(dòng)T1
SETB D1 ;D1、D2均熄滅
SETB D2
LOP0:JNB RI,$ ;查詢接收標(biāo)志(等待一幀數(shù)據(jù)傳送完)
CLR RI ;RI清零(為接收下一幀數(shù)據(jù)作準(zhǔn)備)
MOV R0,SBUF ;將接收緩沖區(qū)的數(shù)據(jù)存入R0
CJNE R0,#1,LOP1 ;判斷接收的數(shù)據(jù)是否為“1”
CPL D1 ;D1閃爍、D2熄滅
SETB D2
CALL DELAY
AJMP LOP0 ;跳轉(zhuǎn)至LOP0(循環(huán)查詢接收標(biāo)志)
LOP1:CJNE R0,#2,LOP2 ;判斷接收的數(shù)據(jù)是否為“2”
SETB D1 ;D1熄滅、D2閃爍
CPL D2
CALL DELAY
AJMP LOP0
LOP2: CJNE R0,#3,LOP3 ;判斷接收的數(shù)據(jù)是否為“3”
CPL D1 ;D1、D2均閃爍
CPL D2
CALL DELAY
AJMP LOP0
LOP3: SETB D1 ;若接收的數(shù)據(jù)不是1、2、3中的一個(gè),則D1、D2熄滅
SETB D2
AJMP LOP0
DELAY:MOV R7,#20 ;延時(shí)程序
DELAY1:MOV R6,#250
DJNZ R6,$
DJNZ R7,DELAY1
RET
END
4)
C語言源程序
主機(jī)控制程序:
#include<reg51.h>
#defineucharunsignedchar
#defineuintunsignedint
sbitD1=P0^0; //發(fā)光管端口定義
sbitD2=P0^1;
sbitKEY=P3^5; //按鍵端口定義
voiddelay(uintm) //延時(shí)程序
{
uchari;
while(m--)for(i=0;i<120;i++);
}
voidputchar_to_port(ucharc) //發(fā)送數(shù)據(jù)至串口程序
{
SBUF=c; //待發(fā)送數(shù)據(jù)存入發(fā)送緩沖區(qū)
while(TI==0); //等待一幀數(shù)據(jù)發(fā)送完(發(fā)送一幀數(shù)據(jù)后,由硬件置TI=1)
TI=0; //TI由軟件清零(為繼續(xù)發(fā)送數(shù)據(jù)作準(zhǔn)備)
}
voidmain() //主程序
{
ucharkey_count=0; //按鍵合上次數(shù)
SCON=0x40; //(主機(jī))串口方式1,禁止接收
TMOD=0x20;
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025四川建筑安全員-B證考試題庫附答案
- 2025天津市安全員《A證》考試題庫及答案
- 《it推動(dòng)商業(yè)變革》課件
- 大匠文化精神課件(增)
- 多項(xiàng)式與多項(xiàng)式相乘的課件
- 【物理課件】測定金屬的電阻率 練習(xí)使用螺旋測微器課件
- 江蘇省無錫市2024-2025學(xué)年高二上學(xué)期期終教學(xué)質(zhì)量調(diào)研測試歷史試卷(含答案)
- 單位管理制度展示大全【職員管理】十篇
- 單位管理制度收錄大全【員工管理】十篇
- 單位管理制度收錄大合集人事管理篇
- 重慶市社會(huì)保險(xiǎn)登記表
- 高血壓疾病證明書
- GA 763-2008警服V領(lǐng)、半高領(lǐng)毛針織套服
- 10000中國普通人名大全
- (完整word版)兒童迷宮圖 清晰可直接打印
- 醫(yī)院財(cái)務(wù)科出納崗位說明書
- DB37-T 5076-2016 賓館酒店建筑能耗限額標(biāo)準(zhǔn)
- 數(shù)據(jù)中心機(jī)房裝修標(biāo)準(zhǔn)規(guī)范(精簡)
- 某機(jī)修廠供配電系統(tǒng)設(shè)計(jì)
- (完整)公共衛(wèi)生基本知識考試題題庫及答案
- (完整)碘造影劑的理化性質(zhì)幾種常用碘造影劑的比較新ppt
評論
0/150
提交評論