




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 網絡安全問題及對策分析試題及答案
- 網絡工程師職業生涯成功的秘訣試題及答案
- 如何建立有效的公共政策反饋通道試題及答案
- 新零售私域流量運營用戶滿意度提升策略報告
- 西方國家的選民行為變遷試題及答案
- 直面西方政治制度的多重挑戰試題及答案
- 安全防范測試題及答案
- 生態系統視角下的企業戰略創新
- 機電工程中的職業認同感提升及試題與答案
- 案例分析2025年信息管理師試題及答案
- 建筑施工資料員培訓課件:提升工程檔案管理技能
- 全域旅游視角下浙江白水洋鎮鄉村旅游發展路徑優化研究
- 2024北京西城區五年級(下)期末數學試題及答案
- 【課件】2025年安全生產月主題宣講(一)
- 燕舞集團招聘試題及答案
- 2024園藝師考試栽培方法試題及答案
- 工程結算審核實務:重點難點解析及解決方案
- 小學數學課堂互動教學模式探究
- 外架承包合同完整版
- CHINET2024年全年細菌耐藥監測結果
- 2025年河北建投能源投資股份有限公司招聘筆試參考題庫含答案解析
評論
0/150
提交評論