;16x2 LCD測試程式 ;在LCD上顯示時間 LCD_RS EQU P1.0 ;定義LCD接線位置 LCD_RW EQU P1.1 LCD_E EQU P1.2 LCD_DATA EQU P2 SUBSEC EQU 30H SECOND EQU 31H MINUTE EQU 32H HOUR EQU 33H ORG 0H JMP START ORG 0BH JMP TIMER0_INT ;設定50ms 中斷一次 START: ; MOV R5,#1 ;如果電源關掉重開時,LCD無法正常顯示 ; CALL DELAY ;請加上此延遲程式 MOV TMOD,#00000001B ;設定TIMER0工作於MODE 1 MOV TH0,#(65536-49990) / 256 ;設定計數約50ms MOV TL0,#(65536-49990) MOD 256 SETB TR0 ;啟動計時器 MOV IE,#10000010B ;啟動TIMER0中斷 MOV SUBSEC,#20 ;設定中斷20次 1秒鐘 MOV SECOND,#0 MOV MINUTE,#0 MOV HOUR,#0 CLR LCD_RW ;習慣上直接將LCD的RW接腳直接接地, MOV A,#00111000B ;設定LCD介面為8位元, 2行, 5x7字型 CALL WRIR MOV A,#00001100B ;設定要LCD顯示, 不要有游標, 不要閃爍 CALL WRIR MOV A,#00000110B ;設定寫資料進入LCD時, 顯示器不要動, 游標向右移一格 CALL WRIR MOV A,#1 ;清除LCD CALL WRIR MOV R5,#1 ;延遲等清除LCD命令處理完畢 CALL DELAY MOV A,#10001000B ;游標移到第一行第8個字 CALL WRIR MOV DPTR,#str1 ;指標指到str1, 顯示初值00:00:00 CALL PRT_STR JMP $ ;--------------------------------------------------------------------------- TIMER0_INT: ;計時中斷程式,每中斷20次為1秒鐘 MOV TH0,#(65536-49990) / 256 ;設定計數約50ms MOV TL0,#(65536-49990) MOD 256 DJNZ SUBSEC,NOT_1SEC ;判斷是否已計數1秒鐘,若還沒1秒,離開中斷程式 MOV SUBSEC,#2 ;為便於觀察,已經將時間調快10倍, 請於測試正常後,以下一行指令代替 ; MOV SUBSEC,#20 INC SECOND MOV A,SECOND CJNE A,#60,NOT_1MIN ;判斷是否已經1分鐘(second=60) MOV SECOND,#0 INC MINUTE MOV A,MINUTE CJNE A,#60,NOT_1HR ;判斷是否已經1小時(MINUTE=60) MOV MINUTE,#0 INC HOUR MOV A,HOUR CJNE A,#24,NOT_1DAY ;判斷是否已經1天(HOUR=24) MOV HOUR,#0 NOT_1DAY: MOV A,#10001000B ;游標移到'小時'的位置 CALL WRIR MOV A,HOUR CALL DISPLAY NOT_1HR: MOV A,#10001011B ;游標移到'分鐘'的位置 CALL WRIR MOV A,MINUTE CALL DISPLAY NOT_1MIN: MOV A,#10001110B ;游標移到'秒'的位置 CALL WRIR MOV A,SECOND CALL DISPLAY NOT_1SEC: RETI ;-------------------------------------------------------------------------------------- PRT_STR: ;顯示字串副程式 CLR A ;清除累加器內資料 MOVC A,@A+DPTR ;讀取字型資料 JZ END_STR ;判斷抓到的資料是否為0,如果是0代表字串結束,跳至返回主程式 CALL WRDR INC DPTR ;指標內容加1, 指到下一個字 JMP PRT_STR END_STR: RET str1: DB "00:00:00",0 ;定義字串內容, 以數值0當結束碼 WRIR: CLR LCD_RS ;寫命令到LCD副程式 SETB LCD_E MOV LCD_DATA,A MOV R7,#50 ;延遲等訊號穩定 DJNZ R7,$ CLR LCD_E ;讓Enable接腳產生負緣訊號 MOV R7,#60 ;延遲等訊號處裡完畢 DJNZ R7,$ RET WRDR: SETB LCD_RS ;寫資料到LCD副程式 SETB LCD_E MOV LCD_DATA,A MOV R7,#50 ;延遲等訊號穩定 DJNZ R7,$ CLR LCD_E ;讓Enable接腳產生負緣訊號 MOV R7,#60 ;延遲等訊號處裡完畢 DJNZ R7,$ RET DISPLAY: ;將2位數數值顯示於LCD MOV B,#10 DIV AB ;數值除以10,十位數在A, 個位數在B ADD A,#30H ;轉換數字成ASCII碼 0~9 => 30H~39H CALL WRDR ;顯示於LCD MOV A,B ADD A,#30H ;轉換數字成ASCII碼 CALL WRDR ;顯示於LCD RET DELAY: MOV R6,#100 DEL: MOV R7,#100 DJNZ R7,$ DJNZ R6,DEL DJNZ R5,DELAY RET END