題目:
掃描minikey,將按鍵值依下列方式顯示於LCD上:- 按'1'鍵,將'1'顯示於第一列奇數位置和第二列偶數位置
- 按'2'鍵,將'2'顯示於第一列偶數位置和第二列奇數位置
- 按'3'鍵,將'3'顯示於第一列奇數位置和第二列偶數位置
- 按'4'鍵,將'4'顯示於第一列偶數位置和第二列奇數位置
功能描述:
LCD顯示器,由S1~S4開關控制,各開關功能如下:
按下S1
LCD顯示:
按下S2
LCD顯示:
按下S3
LCD顯示:
按下S4
LCD顯示:
流程圖:
初步程式碼:
LCD_BUS EQU P0LCD_RS EQU P2.1
LCD_EN EQU P3.7
OUT_S1S2 EQU P3.2;定義OUT_S1S2為89C51的P3.2腳
OUT_S3S4 EQU P3.3;定義OUT_S3S4為89C51的P3.3腳
IN_S1S3 EQU P3.4;定義IN_S1S3為89C51的P3.4腳
IN_S2S4 EQU P3.5;定義IN_S2S4為89C51的P3.5腳
KEYNUM EQU 35H;定義KEYNUM為35H
KEYFLAG EQU 20H.1;定義KEYFLAG為20H.1
FLAG_S1S2 EQU 20H.2;定義FLAG_S1S2為20H.2
FLAG_S3S4 EQU 20H.3;定義FLAG_S3S4為20H.3
MOV KEYNUM,#0
CLR KEYFLAG
CALL INITLCD
LOOP13: CALL KEY
JNB KEYFLAG,LOOP13
MOV R1,KEYNUM
CJNE R1,#1,LOOP9
MOV DPTR,#STR1
MOV B,#00H
JMP LOOP8
LOOP9: CJNE R1,#2,LOOP10
MOV DPTR,#STR2
MOV B,#01H
JMP LOOP8
LOOP10: CJNE R1,#3,LOOP11
MOV DPTR,#STR3
MOV B,#00H
JMP LOOP8
LOOP11: CJNE R1,#4,LOOP13
MOV DPTR,#STR4
MOV B,#01H
LOOP8: CALL INITLCD
MOV A,#1
LOOP14: MOV R0,#8;;;;;;;
LOOP5: ; MOV A,#1
PUSH ACC
CALL GOXY
CALL PRTSTR
MOV A,B
ADD A,#02H
MOV B,A
POP ACC
DJNZ R0,LOOP5
CJNE A,#1,LOOP13
INC A
MOV R2,B
CJNE R2,#11H,LOOP15;;;;
MOV B,#00H
JMP LOOP14
LOOP15: MOV B,#01H
JMP LOOP14
JMP LOOP13
STR1: DB '1'
STR2: DB '2'
STR3: DB '3'
STR4: DB '4'
PRTSTR: CLR A
MOVC A,@A+DPTR
CALL WRDR
RET
WRDR: SETB LCD_EN
SETB LCD_RS;;
MOV LCD_BUS,A
CLR LCD_EN
MOV R7,#1
CALL DELAY
RET
WRIR: SETB LCD_EN
CLR LCD_RS;;
MOV LCD_BUS,A
CLR LCD_EN
MOV R7,#1
CALL DELAY
RET
INITLCD: MOV A,#38H
CALL WRIR
MOV A,#0DH
CALL WRIR
MOV A,#06H
CALL WRIR
MOV A,#01H
CALL WRIR
MOV R7,#40
CALL DELAY
RET
GOXY: ANL B,#00001111B
CJNE A,#1,LOOP1
MOV A,B
ADD A,#10000000B
CALL WRIR
RET
LOOP1: MOV A,B
ADD A,#11000000B
CALL WRIR
RET
DELAY: MOV TMOD,#00000001B
LOOP: MOV TH0,#HIGH(65536-50)
MOV TL0,#LOW(65536-50)
SETB TR0
JNB TF0,$
CLR TR0
CLR TF0
DJNZ R7,LOOP
RET
KEY: CLR OUT_S1S2;將OUT_S1S2變為低0電位,
MOV R7,#1;設定DELAY時間
CALL DELAY;呼叫DELAY副程式,目的是為了使OUT_S1S2有時間變為低0電位
JB IN_S1S3,KEY2;若IN_S1S3為1高電位,則表示無按S1開關,並跳至KEY2,反之有按S1開關,成為低0電位,則往下執行
MOV KEYNUM,#1;將KEYNUM放入1值,表示有按S1開關
SETB KEYFLAG
JMP RMIN;跳至RMIN副程式
KEY2: JB IN_S2S4,KEY3;若IN_S2S4為1高電位,則表示無按S2開關,並跳至KEY3,反之有按S2開關成為低0電位,則往下執行
MOV KEYNUM,#2;將KEYNUM放入2值,表示有按S2開關
SETB KEYFLAG
JMP RMIN;跳至RMIN副程式
KEY3: SETB OUT_S1S2;將OUT_S1S2設為1,防止按下S1S2開關時使IN_S1S3 IN_S2S4變成0
CLR OUT_S3S4;將OUT_S1S2變為低0電位
MOV R7,#1;設定DELAY時間
CALL DELAY;呼叫DELAY副程式,目的是為了使OUT_S3S4有時間變為低0電位
JB IN_S1S3,KEY4;若IN_S1S3為1高電位,則表示無按S3開關,並跳至KEY4,反之有按S3開關成為低0電位,則往下執行
MOV KEYNUM,#3;將KEYNUM放入3值,表示有按S3開關
SETB KEYFLAG
JMP RMIN;跳至RMIN副程式
KEY4: JB IN_S2S4,KEY5;若IN_S2S4為1高電位,則表示無按S4開關,並跳至KEY5,反之有按S4開關成為低0電位,則往下執行
MOV KEYNUM,#4;將KEYNUM放入4值,表示有按S4開關
SETB KEYFLAG
JMP RMIN
KEY5: CLR KEYFLAG
RMIN: SETB OUT_S1S2;設回初值
SETB OUT_S3S4;設回初值
RET
END
修正程式碼:
;=============================參數定義=================================
LCD_BUS EQU P0;定義LCD_BUS為89C51的P0腳
LCD_RS EQU P2.1;定義OUT_S1S2為89C51的P3.2腳
LCD_EN EQU P3.7;定義OUT_S1S2為89C51的P3.2腳
OUT_S1S2 EQU P3.2;定義OUT_S1S2為89C51的P3.2腳
OUT_S3S4 EQU P3.3;定義OUT_S3S4為89C51的P3.3腳
IN_S1S3 EQU P3.4;定義IN_S1S3為89C51的P3.4腳
IN_S2S4 EQU P3.5;定義IN_S2S4為89C51的P3.5腳
KEYNUM EQU 35H;定義KEYNUM為35H
KEYFLAG EQU 20H.1;定義KEYFLAG為20H.1
;==============================主程式==================================
MOV KEYNUM,#4;設定KEYNUM初始值
CLR KEYFLAG;設定KEYFLAG初始值
CALL INITLCD;初始值LCD
LOOP13: CALL KEY;呼叫KEY副程式
JNB KEYFLAG,LOOP13;若無按按鍵,則繼續偵測按鍵
LOOP8: CALL INITLCD;初始值LCD
MOV A,#1;表示第一行
LOOP14: MOV R0,#8;一列有0~15行而我每行將顯示8個字元
LOOP5: PUSH ACC;暫存A之值,將A值放入堆疊區
CALL GOXY;呼叫GOXY副程式
MOV A,KEYNUM;將KEYNUM放入A,使DPTR+KEYNUM指向所要顯示的字元
CALL PRTSTR;呼叫PRTSTR副程式
MOV A,B;將B複製到A,為了把B值加2已指向另一行位址在顯示出字元
ADD A,#02H;增二
MOV B,A;A複製回B
POP ACC;從堆疊區取回
DJNZ R0,LOOP5;將R0減一不等於0,跳至LOOP5
CJNE A,#1,LOOP13;比較A=1往下執行,不相等跳至LOOP13表示第一行與第二行都已顯示完成
INC A;將A增一,表示第二行
MOV R2,B
CJNE R2,#11H,LOOP15;因B表第幾行,且一行只到0F,故若一開始B為01H時,加八次2時為01H,且顯示完後還會在執行到一次B+2,故為11H時往下執行
MOV B,#00H;第二行給為從00H開始顯示
JMP LOOP14
LOOP15: MOV B,#01H
JMP LOOP14
STR: DB '1234'
;-----------------------------顯示字元--------------------------------
PRTSTR: MOVC A,@A+DPTR
CALL WRDR
RET
;-------------------------寫入資料暫存器------------------------------
WRDR: SETB LCD_EN
SETB LCD_RS
MOV LCD_BUS,A
CLR LCD_EN
MOV R7,#1
CALL DELAY
RET
;-------------------------寫入指令暫存器------------------------------
WRIR: SETB LCD_EN
CLR LCD_RS
MOV LCD_BUS,A
CLR LCD_EN
MOV R7,#1
CALL DELAY
RET
;---------------------------初始LCD-----------------------------------
INITLCD: MOV A,#38H
CALL WRIR
MOV A,#0DH
CALL WRIR
MOV A,#06H
CALL WRIR
MOV A,#01H
CALL WRIR
MOV R7,#40
CALL DELAY
RET
;---------------------------移動游標----------------------------------
GOXY: ANL B,#00001111B
CJNE A,#1,LOOP1
MOV A,B
ADD A,#10000000B
CALL WRIR
RET
LOOP1: MOV A,B
ADD A,#11000000B
CALL WRIR
RET
;-----------------------------延遲------------------------------------
DELAY: MOV TMOD,#00000001B
LOOP: MOV TH0,#HIGH(65536-50)
MOV TL0,#LOW(65536-50)
SETB TR0
JNB TF0,$
CLR TR0
CLR TF0
DJNZ R7,LOOP
RET
;----------------------------按鍵偵測----------------------------------
KEY: CLR OUT_S1S2;將OUT_S1S2變為低0電位,
MOV R7,#1;設定DELAY時間
CALL DELAY;呼叫DELAY副程式,目的是為了使OUT_S1S2有時間變為低0電位
JB IN_S1S3,KEY2;若IN_S1S3為1高電位,則表示無按S1開關,並跳至KEY2,反之有按S1開關,成為低0電位,則往下執行
MOV KEYNUM,#0;將KEYNUM放入0值,表示有按S1開關,且為了指向DPTR位址,固原本設計為1改為0
MOV DPTR,#STR
MOV B,#00H
SETB KEYFLAG;用來判定是否有按開關
JMP RMIN;跳至RMIN副程式
KEY2: JB IN_S2S4,KEY3;若IN_S2S4為1高電位,則表示無按S2開關,並跳至KEY3,反之有按S2開關成為低0電位,則往下執行
MOV KEYNUM,#1;將KEYNUM放入1值,表示有按S2開關
MOV DPTR,#STR
MOV B,#01H
SETB KEYFLAG;用來判定是否有按開關
JMP RMIN;跳至RMIN副程式
KEY3: SETB OUT_S1S2;將OUT_S1S2設為1,防止按下S1S2開關時使IN_S1S3 IN_S2S4變成0
CLR OUT_S3S4;將OUT_S1S2變為低0電位
MOV R7,#1;設定DELAY時間
CALL DELAY;呼叫DELAY副程式,目的是為了使OUT_S3S4有時間變為低0電位
JB IN_S1S3,KEY4;若IN_S1S3為1高電位,則表示無按S3開關,並跳至KEY4,反之有按S3開關成為低0電位,則往下執行
MOV KEYNUM,#2;將KEYNUM放入2值,表示有按S3開關
MOV DPTR,#STR
MOV B,#00H
SETB KEYFLAG;用來判定是否有按開關
JMP RMIN;跳至RMIN副程式
KEY4: JB IN_S2S4,KEY5;若IN_S2S4為1高電位,則表示無按S4開關,並跳至KEY5,反之有按S4開關成為低0電位,則往下執行
MOV KEYNUM,#3;將KEYNUM放入3值,表示有按S4開關
MOV DPTR,#STR
MOV B,#01H
SETB KEYFLAG;用來判定是否有按開關
JMP RMIN
KEY5: CLR KEYFLAG;用來判定是否有按開關
RMIN: SETB OUT_S1S2;設回初值
SETB OUT_S3S4;設回初值
RET
END
沒有留言:
張貼留言
文章有誤或有問題麻煩您留言告知! 謝謝您~~