; File: LCD_KP1@.A51 Date: 1/25/95 ; ; /* (c) Copyright BLUE EARTH RESEARCH, MANKATO, MN 1995. */ ; /* All rights reserved. */ ; $ TITLE (4-BIT LCD PRINT@ DRIVER USING P1) $ DEBUG XREF ERRORPRINT $ NOGEN $ DATE (01-25-95) $ PW(106) PL(60) ; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ; º º ; º LCD MODULE SOFTWARE DRIVER ROUTINE º ; º º ; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ; ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸ ; ³ Written By: Thomas Bachmann ³ ; ³ Blue Earth Research, Mankato, MN 56001 ³ ; ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ; This program implements a 4-bit interface to a LCD module using a total ; of 6 I/O lines on P1. Four lines are used for data, with two additional ; lines for "Register Select" and "E". The Register Select line is used to ; specify whether data is currently being written to the Command or Data ; register. The E signal is used to clock the data to the LCD module. A ; third control line, R/W, is not used in this application. Since data ; will only be written to the LCD, the R/W line should be tied low ; (grounded). ; When this program is initialized from within BASIC by executing the ; "CALL 7E00H" Statement, characters are written to the LCD by the ; "PRINT@" Statement. A Carriage Return (0DH) will cause the cursor to be ; at the "home" position, and a Line Feed (0AH) will place the cursor at ; the beginning of the second line. A Form Feed (0CH) will clear the ; screen and return the cursor to the home position. ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ $ EJECT ; ---------------------- SCAN A MATRIX KEYPAD ---------------------------- ; The keypad software does not require any initialization. Since this ; example uses a 4x4 keypad, BIT 9 is set during the LCD initialization to ; enable the keypad routine to scan the bottom two rows of the keypad. The ; LCD initialization also configures Timer0 for a 5 millisecond timer to ; periodically sample the keypad input. ; Executing the CALL 7EE3H Statement will scan the keypad and return a ; number between 0 and 8 (0 and 16 for a 4x4 keypad). The number will be ; placed in internal memory location 1BH. The number indicates the key ; being pressed, where 1 represents row 1 column 1, 2 represents row 2 ; column 1, etc. A zero indicates that no keys are pressed. ; The keypad scan routine simply checks each row for a key press and ; returns the number corresponding to the first key press detected, or ; zero if no keys are pressed. As an option, Bit 10 can be set to force ; the key scan software to wait until a new key is pressed. The routine ; will not return a zero. ; Keypad Layout: ; ÉÍÍÍÍÍÑÍÍÍÍÍÑÍÍÍÍÍÑÍÍÍÍÍ» ; º 1 ³ 2 ³ 3 ³ SPC º ; ÇÄÄÄÄÄÅÄÄÄÄÄÅÄÄÄÄÄÅÄÄÄÄĶ ; º 4 ³ 5 ³ 6 ³ ENT º ; ÇÄÄÄÄÄÅÄÄÄÄÄÅÄÄÄÄÄÅÄÄÄÄĶ ; º 7 ³ 8 ³ 9 ³ CLR º ; ÇÄÄÄÄÄÅÄÄÄÄÄÅÄÄÄÄÄÅÄÄÄÄĶ ; º * ³ 0 ³ # ³ ESC º ; ÈÍÍÍÍÍÏÍÍÍÍÍÏÍÍÍÍÍÏÍÍÍÍͼ ; 0-9, '*','#' will be displayed on the LCD. ; SPC will result in a space character on the LCD. ; ENT will place the cursor on the second line of the LCD. ; CLR will clear the LCD. ; ESC will terminate the control program. $ EJECT ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ DEFINITIONS SPECIFIC TO THE SYSTEM WIRING ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ; THE FOLLOWING DEFINITIONS ASSUME THAT THE SYSTEM WIRING IS ; CONFIGURED WITH ALL CONNECTIONS TO PORT1 & PORT3 AS FOLLOWS: ; SIGNAL CONTROLLER SIGNAL ; -------- ------------ -------- ; 22 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; DB4ÄÄÄÄÄÄÄÄÄÄÄ´ P1.0 P1.0 ÃÄÄÄÄÄÄÄÄÄÄÄCOL1 ; 9 ³ ³ ; DB5ÄÄÄÄÄÄÄÄÄÄÄ´ P1.1 P1.1 ÃÄÄÄÄÄÄÄÄÄÄÄCOL2 ; 21 ³ ³ ; DB6ÄÄÄÄÄÄÄÄÄÄÄ´ P1.2 P1.2 ÃÄÄÄÄÄÄÄÄÄÄÄCOL3 ; 8 ³ ³ ; DB7ÄÄÄÄÄÄÄÄÄÄÄ´ P1.3 P1.3 ÃÄÄÄÄÄÄÄÄÄÄÄCOL4 ; 20 ³ ³ ; RSÄÄÄÄÄÄÄÄÄÄÄ´ P1.4 P3.3 ÃÄÄÄÄÄÄÄÄÄÄÄROW1 ; 7 ³ ³ ; E ÄÄÄÄÄÄÄÄÄÄÄ´ P1.5 P3.5 ÃÄÄÄÄÄÄÄÄÄÄÄROW2 ; 1 ³ ³ ; R/WÄÄÄÄÄÄÄÄÄÄÄ´ GND P3.2 ÃÄÄÄÄÄÄÄÄÄÄÄROW3 (Optional) ; 1 ³ ³ ; VeeÄÄÄÄÄÄÄÄÄÄÄ´ GND P3.4 ÃÄÄÄÄÄÄÄÄÄÄÄROW4 (Optional) ; 1 ³ ³ ; VssÄÄÄÄÄÄÄÄÄÄÄ´ GND ³ +5V ÄÄÄÄÄVcc ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ; The LCD control lines are wired to the controller as follows: RS BIT P1.4 Eclk BIT P1.5 ; Note that both of these signals can be reassigned to any of the ; available Port 1 or Port 3 signals if the keypad is not used. ; Note: The port pins are assigned in order to allow the use of up to 2 ; of the Micro-440e's PCA Modules ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ $ EJECT ; The following BASIC program can be used to demonstrate the functions of ; the LCD with this program: ; 2 REM LCD KEYPAD SAMPLE PROGRAM ; ; REM INITIALIZE LCD MODULE ; 10 CALL 7E00H ; 20 PRINT@ "BLUE EARTH" : PRINT@ "RESEARCH" ; ; REM WAIT FOR KEY, CLEAR AND REWRITE THE DISPLAY ; 30 GOSUB 500 : J=G : PRINT@ CHR$(12), ; 40 PRINT@ "LCD" : PRINT@ "DEMO" ; 50 GOSUB 500 : PRINT@ CHR$(12), ; ; REM GET KEYS AND WRITE THEM TO THE DISPLAY ; ; 60 GOSUB 500 ; 70 IF G=4 THEN P.@" ",: GOTO 60 ; 80 IF G=8 THEN P.@ : GOTO 60 ; 90 IF G=12 THEN P.@ CHR$(12), : GOTO 60 ; 100 IF G=13 THEN P.@ "*", : GOTO 60 ; 110 IF G=14 THEN P.@ "0", : GOTO 60 ; 120 IF G=15 THEN P.@ "#", : GOTO 60 ; ; 130 IF G=16 THEN CALL 7EBCH : END ; ; REM PRINT THE NUMBER ; ; 140 IF G<4 THEN P.@ CHR$(G+48), : GOTO 60 ; 150 G1=G-1 : IF G1<7 THEN P.@ CHR$(G1+48), : GOTO 60 ; 160 G1=G1-1 : P.@ CHR$(G1+48), : GOTO 60 ; ; 500 DO : J=DBY(1BH) : IF J=0 THEN G=J ; 505 WHILE G=J ; 510 DO : G=DBY(1BH) : UNTIL G : RETURN ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ $ EJECT ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ DATA MEMORY DECLARATIONS ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ DSEG AT 18H Clock: DS 2 ; Timer Registers TEMP_HOLD: DS 1 ; LCD BYTE TEMP HOLDER Keys: DS 1 ; Hold Key byte number Not_Used: DS 4 ; Unused memory locations LCD_Byte: DS 1 ; Byte to write to Port1 ; Variable Equates RS_BIT BIT 4 ; DATA BIT Bit that is written to RS DIFF BIT 8 ; DATA BIT Different key pressed ? LINES BIT 9 ; DATA BIT 1=4x4 Keypad, 0=2x4. W4Key BIT 10 ; DATA BIT Set = wait until key pressed ; I/O Line Equates ROW1 EQU P3.3 ; PORT PIN Keypad Row 1 ROW2 EQU P3.5 ; PORT PIN Keypad Row 2 ROW3 EQU P3.2 ; PORT PIN Keypad Row 3 (Optional) ROW4 EQU P3.4 ; PORT PIN Keypad Row 4 (Optional) ; Miscellaneous Equates COLS EQU 0FH ; Keypad column lines are in lower nibble. SPACE EQU 20H CR EQU 0DH LF EQU 0AH FF EQU 0CH RESET EQU 1100$0011B ; "RESET" BYTE F_FIRST EQU 1100$0010B ; "FUNCTION SET" BYTES F_SET EQU 0010$1000B ; "FUNCTION SET" BYTES DOFF EQU 0000$1000B ; "DISPLAY OFF" BYTES CLEAR_DISPLAY EQU 0000$0001B ; "CLEAR DISPLAY" BYTE LINE2 EQU 1100$0000B ; "GOTO LINE 2" BYTE LINE1 EQU 1000$0000B ; "GOTO LINE 1" BYTE ; NOTE: 0000$11cbB For "Display On," where ; c=1 for Cursor on, and b=1 for blinking character DON EQU 0000$1100B ; "DISPLAY ON" BYTES MODE EQU 0000$0110B ; "ENTRY MODE" BYTES SHIFTR EQU 0001$1100B ; "SHIFT RIGHT" BYTES SHIFTL EQU 0001$1000B ; "SHIFT LEFT" BYTES EXEC_TIME EQU 20 ; EXECUTION TIME FOR INSTRUCTIONS ; ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸ ; ³ BEGINNING OF INITIALIZATION ROUTINE ³ ; ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; CSEG AT 7E00H ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ INITIALIZE USER LCD OUTPUT ALGORITHM ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ; The following code places the jump vector in memory and ; sets the protection bit that tells BASIC where it should ; direct the PRINT@ output to. Start: MOV DPTR,#403CH ; POINT TO JUMP LOCATION MOV A,#2 ; LOAD LJMP MOVX @DPTR,A INC DPTR MOV A,#HIGH CHAR_OUTPUT MOVX @DPTR,A INC DPTR MOV A,#LOW CHAR_OUTPUT MOVX @DPTR,A SETB 39 ; PROTECTION BIT SETB LINES ; 4x4 Keypad ; -------------- SET UP TIMER0 INTERRUPT VECTOR --------------- MOV DPTR,#400BH ; Stuff "LJMP XXXXH" into MOV A,#2 ; mirrored Timer 0 overflow MOVX @DPTR,A ; vector at address 400BH. INC DPTR MOV A,#HIGH Timer0Int ; Location of Timer 0 MOVX @DPTR,A ; interrupt routine. INC DPTR MOV A,#LOW Timer0Int MOVX @DPTR,A $ EJECT ; ------------------- INITIALIZE LCD MODULE ------------------- MOV LCD_Byte,#0C0H ; P1.6 & P1.7 High CLR Eclk CLR RS ; OUTPUT TO COMMAND REGISTER CLR RS_BIT MOV Clock+1,#0FFH ; WAIT FOR A LONG TIME ACALL WAIT_Z MOV P1,#RESET ; WRITE BYTE SETB Eclk ; CLOCK IT IN CLR Eclk MOV Clock+1,#9 ; WAIT AT LEAST 4.1 mS ACALL WAIT_Z MOV P1,#RESET ; WRITE BYTE ACALL CLOCK_N_WAIT MOV P1,#RESET ; WRITE BYTE ACALL CLOCK_N_WAIT MOV P1,#F_FIRST ; WRITE BYTE ACALL CLOCK_N_WAIT ; CLOCK IT IN MOV A,#F_SET ACALL OUTPUT ; FUNCTION SET MOV A,#DOFF ACALL OUTPUT ; TURN DISPLAY OFF ACALL Clear ; CLEAR DISPLAY MOV A,#MODE ACALL OUTPUT ; SET ENTRY MODE MOV A,#DON ACALL OUTPUT ; TURN DISPLAY ON $ EJECT ; ------------- SET UP TIMER0 FOR 5 mS INTERRUPT -------------- CLR TR0 ; STOP TIMER0 FOR NOW MOV A,TL0 ; Reload Timer 0 for 5 mS ADD A,#LOW -4998 ; (Less 2uS to compensate MOV TL0,A ; for ADD & MOV latency.) MOV TH0,#HIGH -4998 ; Timer 0 is a 16 bit timer used to generate a 5 mS interrupt. ; The input to both Timers is the internal system clock ; The frequency is OSC/12 = 1 MHz. (1uS) ; TMOD: ; Timer 1 Timer 0 ; ÃÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÅÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄ´ ; ³ GAT ³ C/T ³ M1 ³ M0 ³ GAT ³ C/T ³ M1 ³ M0 ³ ; ÀÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÙ ; 0 0 0 1 0 0 0 1 MOV TMOD,#11H ; TIMER/CNTR MODE CTRL REGISTER ; TCON: ; ÚÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄ¿ ; ³ TF1 ³ TR1 ³ TF0 ³ TR0 ³ IE1 ³ IT1 ³ IE0 ³ IT0 ³ ; ÀÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÙ ; 0 0 0 1 0 0 0 0 SETB TR0 ; Start Timer ; IE: ; ÚÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄ¿ ; ³ EA ³ EC ³ ET2 ³ ES ³ ET1 ³ EX1 ³ ET0 ³ EX0 ³ ; ÀÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÙ ; 1 0 0 0 0 0 1 0 SETB ET0 ; Timer 0 interrupt enable SETB EA ; Global interrupt enable ; Fall through to clear display and return to BASIC $ EJECT ; ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸ ; ³ DISPLAY WRITING SUBROUTINES ³ ; ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ CLEAR DISPLAY ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ CLEAR: CLR RS_BIT Clear1: MOV A,#CLEAR_DISPLAY ACALL OUTPUT MOV Clock+1,#10 ; WAIT AT LEAST 4.9 mS WAIT_Z: MOV Clock,#0FFH DJNZ Clock,$ DJNZ Clock+1,WAIT_Z RET ; ---------------------- LCD UPDATE --------------------------- ; The following code is executed every time that the BASIC ; program executes a "PRINT@" Statement. After the statement ; is executed from within BASIC, the character to be output is ; in the accumulator. CHAR_OUTPUT: SETB RS_BIT ; POINT TO DATA REGISTER CJNE A,#SPACE,$+3 ; CHECK FOR A PRINTABLE CHAR JNC OUTPUT CLR RS_BIT ; POINT TO COMMAND REGISTER ; If the character is a Form Feed, the display is cleared and ; the cursor is placed at the beginning of the first line. CJNE A,#FF,CR_Chk ; Form Feed? SJMP Clear1 ; If the character is a carriage return, the display cursor is ; placed at the beginning of the first line of the display. CR_Chk: CJNE A,#CR,LF_Chk ; Carriage return? MOV A,#LINE1 SJMP OUTPUT ; If the character is a line feed, the display cursor is ; placed at the beginning of the second line of the display. LF_Chk: CJNE A,#LF,NoChar ; Line Feed? MOV A,#LINE2 ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ SUBROUTINE FOR SENDING A CHARACTER ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ; SEND AN 8-BIT CHARACTER (OR COMMAND) TO THE LCD. OUTPUT: MOV TEMP_HOLD,A ; SAVE IT ; ------------------ OUTPUT CHARACTER HALF -------------------- SWAP A ANL A,#0FH ; Get rid of High nibble ORL A,LCD_Byte ; OUTPUT 1's ON UPPER 2 BITS MOV P1,A SETB Eclk CLR Eclk MOV A,TEMP_HOLD ; GET LOWER HALF ANL A,#0FH ; Get rid of High nibble ORL A,LCD_Byte ; OUTPUT OTHER CHAR HALF MOV P1,A CLOCK_N_WAIT: SETB Eclk ; CLOCK IN THE BYTE CLR Eclk MOV Clock,#EXEC_TIME ; WAIT AT LEAST 120 uS DJNZ Clock,$ NoChar: RET ; Back to BASIC ; ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸ ; ³ CLEAR TIMER0 INTERRUPT ³ ; ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; STOP: CLR TR0 ; Stop Timer CLR ET0 ; Timer 0 interrupt enable CLR EA ; Global interrupt enable RET $ EJECT ; ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸ ; ³ TIMER0 INTERRUPT SERVICING ROUTINE ³ ; ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; Timer0Int: PUSH ACC ; 5 mS interrupt PUSH B PUSH PSW PUSH DPH PUSH DPL MOV A,TL0 ; Reload Timer 0 for 5 mS ADD A,#LOW -4998 ; (Less 2uS to compensate MOV TL0,A ; for ADD & MOV latency.) MOV TH0,#HIGH -4998 ACALL KEYPAD ; SCAN THE KEYPAD TIME1: ;* Any other function that needs to be executed every *; ;* 5 mS should be programmed here. *; AllDone: POP DPL ; Tail end of 5 mS interrupt POP DPH POP PSW POP B POP ACC RETI ; -------------------- SCAN THE KEYPAD ------------------------ KEYPAD: ORL P1,#COLS ; Assert column input high ROW_1: CLR ROW1 ; Enable Row 1 MOV B,#1 ; Offset value to B register MOV A,P1 CPL A ANL A,#COLS ; Clear lower nibble. SETB ROW1 ; Disable Row 1 JNZ ISKEY ; Find one pressed ? ROW_2: CLR ROW2 ; Do Row 2 MOV B,#5 MOV A,P1 CPL A ANL A,#COLS SETB ROW2 JNZ ISKEY JNB LINES,CLRDIF ; Just 2x4 keypad ? ROW_3: CLR ROW3 ; Do Row 3 MOV B,#9 MOV A,P1 CPL A ANL A,#COLS SETB ROW3 JNZ ISKEY ROW_4: CLR ROW4 ; Do Row 4 MOV B,#13 MOV A,P1 CPL A ANL A,#COLS SETB ROW4 JNZ ISKEY CLRDIF: CLR DIFF MOV B,#0 ; Nothing pressed SJMP STORE ISKEY: JB ACC.0,OKSTOR ; Col 1 ? INC B JB ACC.1,OKSTOR ; Col 2 ? INC B JB ACC.2,OKSTOR ; Col 3 ? INC B ; Must be Col 4 ! OKSTOR: MOV A,KEYS SETB DIFF CJNE A,B,STORE ; Different ? CLR DIFF ; No ! STORE: MOV KEYS,B ; Stuff here ? JNB W4Key,KeyEnd ; Wait until a new key is pressed? JNB DIFF,KEYPAD KeyEnd: RET ; Only one exit point ! ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; END OF PROGRAM END ; Following is the HEX file derived from the assembled source ; file. This can be used for directly loading the program via ; MONITOR-51 and almost any terminal program. :107E000090403C7402F0A3747EF0A37482F0D227F9 :107E1000D20990400B7402F0A3747EF0A374C3F0F7 :107E20007520C0C295C294C2047519FFD1787590AF :107E3000C3D295C295751909D1787590C3D1B17522 :107E400090C3D1B17590C2D1B17428D19C7408D1BE :107E50009CD16F7406D19C740CD19CC28CE58A2491 :107E60007AF58A758CEC758911D28CD2A9D2AFC201 :107E7000047401D19C75190A7518FFD518FDD51920 :107E8000F722D204B420005013C204B40C0280E1E3 :107E9000B40D0474808005B40A2174C0F51AC4546A :107EA0000F4520F590D295C295E51A540F4520F55F :107EB00090D295C295751814D518FD22C28CC2A90E :107EC000C2AF22C0E0C0F0C0D0C083C082E58A2427 :107ED0007AF58A758CECD1E3D082D083D0D0D0F003 :107EE000D0E03243900FC2B375F001E590F4540F27 :107EF000D2B37034C2B575F005E590F4540FD2B525 :107F0000702630091CC2B275F009E590F4540FD206 :107F1000B27015C2B475F00DE590F4540FD2B47080 :107F200007C20875F000801820E00C05F020E1077A :107F300005F020E20205F0E51BD208B5F002C20808 :0A7F400085F01B300A0330089A2276 :00000001FF