《電子設(shè)計(jì)自動(dòng)化》課件第8章_第1頁
《電子設(shè)計(jì)自動(dòng)化》課件第8章_第2頁
《電子設(shè)計(jì)自動(dòng)化》課件第8章_第3頁
《電子設(shè)計(jì)自動(dòng)化》課件第8章_第4頁
《電子設(shè)計(jì)自動(dòng)化》課件第8章_第5頁
已閱讀5頁,還剩322頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論