|
/script> ;************************************************ ;* 18F_LCD.asm * ;* Microchip Taiwan * ;* Date : Sept. 24 2002 * ;* Version : v1.00 * ;************************************************ ;* Contains subroutines to control an external * ;* lcd panel in 4-bit mode. These routines * ;* were designed specifically for the panel on * ;* the PICdemo 2 Plus demo board, but should * ;* work with other LCDs with a HD44780 type * ;* controller. * ;* Routines include: * ;* - InitLCD to initialize the LCD panel * ;* - putcLCD to write a character to LCD * ;* - SendCmd to write a command to LCD * ;* - clrLCD to clear the LCD display * ;* - L1homeLCD to return cursor to line 1 home* ;* - L2homeLCD to return cursor to line 2 home* ;* - PutHexLCD to write a HEX Code to LCD * ;* - Hex2ASCII to convert 4 bits to ASCII Code* ;************************************************ ; list p=18F452 #include <P18F452.inc> ; global InitLCD global putcLCD global clrLCD global L1homeLCD global L2homeLCD global Send_Cmd global PutHexLCD global Hex2ASCII global Delay_xMS global Delay_1mS ; ; Defines for I/O ports that provide LCD data & control ; PORTD[0:3]-->DB[4:7]: Higher order 4 lines data bus with bidirectional ; : DB7 can be used as a BUSY flag ; PORTA,1 --> [E] : LCD operation start signal control ; PORTA,2 --> [RW]: LCD Read/Write control ; PORTA,3 --> [RS]: LCD Register Select control ; : "0" for Instrunction register (Write), Busy Flag (Read) ; : "1" for data register (Read/Write) ; ; LCD_CTRL equ TRISD LCD_DATA equ PORTD #define LCD_E_DIR TRISA,1 #define LCD_RW_DIR TRISA,2 #define LCD_RS_DIR TRISA,3 #define LCD_E PORTA,1 #define LCD_RW PORTA,2 #define LCD_RS PORTA,3 ; LCD Module commands CLR_DISP equ b'00000001' ; 1.64mS , Clear display and return cursor to home Cursor_Home equ b'00000010' ; 1.64mS , Return cursor to home position
ENTRY_DEC equ b'00000100' ; 40uS , Decrement cursor position & No display shift ENTRY_DEC_S equ b'00000101' ; 40uS , Decrement cursor position & display shift ENTRY_INC equ b'00000110' ; 40uS , Increment cursor position & No display shift ENTRY_INC_S equ b'00000111' ; 40uS , Increment cursor position & display shift DISP_OFF equ b'00001000' ; 40uS , Display off DISP_ON equ b'00001100' ; 40uS , Display on control DISP_ON_C equ b'00001110' ; 40uS , Display on, Cursor on DISP_ON_B equ b'00001111' ; 40uS , Display on, Cursor on, Blink cursor FUNC_SET equ b'00101000' ; 40uS , 4-bit interface , 2-lines & 5x7 dots CG_RAM_ADDR equ b'01000000' ; 40uS , Least Significant 6-bit are for CGRAM address DD_RAM_ADDR equ b'10000000' ; 40uS , Least Significant 7-bit are for DDRAM address ; ; Directs linker to provide 4 variables in GPR memory UDATA LCD_Byte RES 1 LCD_Temp RES 1 Count_uS RES 1 Count_mS RES 1 W_BUFR RES 1 Hex_Bfr RES 1 ; LCD_CODE CODE ;******************************************************************* ;* The LCD Module Subroutines * ;* Command sequence for 2 lines of 5x16 characters * ;******************************************************************* InitLCD bcf LCD_E ; Clear LCD control line to Zero bcf LCD_RW bcf LCD_RS ; bcf LCD_E_DIR ;configure control lines for Output pin bcf LCD_RW_DIR bcf LCD_RS_DIR ; movlw b'00001110' ; configure AN0 as A/D inut pin movwf ADCON1 movf LCD_CTRL,W ; get I/O directional settng andlw 0xF0 movwf LCD_CTRL ; set LCD bus DB[4:7] for output ; movlw .50 ; Power-On delay 50mS rcall Delay_xMS ; movlw b'00000011' ; #1 , Init for 4-bit interface rcall Send_Low_4bit ; movlw .10 ; Delay 10 mS rcall Delay_xMS ; movlw b'00000011' ; #2 , Fully Initial LCD module rcall Send_Low_4bit ; Sent '0011' data rcall Delay_1mS ; movlw b'00000011' ; #3 , Fully Initial LCD module rcall Send_Low_4bit ; Sent '0011' data rcall Delay_1mS ; movlw b'00000010' ; #4 , Fully Initial LCD module rcall Send_Low_4bit ; Sent '0010' data rcall Delay_1mS ; movlw FUNC_SET ; #5,#6 , Set 4-bit mode , 2 lines & 5 x 7 dots rcall Send_Cmd rcall Delay_1mS ; movlw DISP_ON ; #7,#8 , Turn display on (0x0C) rcall Send_Cmd rcall Delay_1mS ; movlw CLR_DISP ; #9,#10 , Clear LCD Screen rcall Send_Cmd movlw .5 ; Delay 5mS for Clear LCD Command execution rcall Delay_xMS ; movlw ENTRY_INC ; #11,#12 , Configure cursor movement rcall Send_Cmd rcall Delay_1mS ; movlw DD_RAM_ADDR ; Set writes for display memory rcall Send_Cmd rcall Delay_1mS ; return ; ;******************************************************************* ;*SendChar - Sends character to LCD * ;*This routine splits the character into the upper and lower * ;*nibbles and sends them to the LCD, upper nibble first. * ;******************************************************************* putcLCD movwf LCD_Byte ; Save WREG in Byte variable rcall Send_High_LCD ; Send upper nibble first movf LCD_Byte,W rcall Send_Low_LCD ; Send lower nibble data rcall Delay_100uS return ; Send_High_LCD swapf WREG,W ; swap high/low nibble Send_Low_LCD bcf LCD_RW ; set LCD Write Mode andlw 0x0F ; Clear high nibble movwf LCD_Temp movf LCD_DATA,W ; Read back PORT andlw 0xF0 ; keep data for PORTD[4:7] iorwf LCD_Temp,W movwf LCD_DATA ; Write data to LCD bus for low nibble bus DB[4:7] bsf LCD_RS ; Set for data input nop bsf LCD_E ; Clock nibble into LCD nop bcf LCD_E return ; ;********************************************************************* ;* To put the HEX value to LCD Display ,, ;* High nibble first than Low nibble ;* Input : W Reg. ;********************************************************************* PutHexLCD movwf W_BUFR ; Save W Register !! swapf W_BUFR,W ; High nibble first !! rcall Hex2ASCII rcall putcLCD ; movf W_BUFR,W rcall Hex2ASCII rcall putcLCD return ; ;****************************************************************** ;* Convert a low nibble to ASCII code ;* Input : W Reg. ;* Output: W Reg. ;****************************************************************** Hex2ASCII andlw 0x0f ; Mask Bit 4 to 7 movwf Hex_Bfr sublw .09 btfsc STATUS,C ; If W less than A (C=1) --> only add 30h bra _Add_W_30 _Add_W_37 movlw 0x37 bra _Hex_cont _Add_W_30 movlw 0x30 _Hex_cont addwf Hex_Bfr,W ; The correct ASCII code for this char !! return ; ;******************************************************************* ;* SendCmd - Sends command to LCD * ;* This routine splits the command into the upper and lower * ;* nibbles and sends them to the LCD, upper nibble first. * ;******************************************************************* ; _ ______________________________ ; RS _>--<______________________________ ; _____ ; RW \_____________________________ ; __________________ ; E ____________/ \___ ; _____________ ______ ; DB _____________>--------------<______ ; Send_Cmd movwf LCD_Byte ; Save WREG in Byte variable rcall Send_High_4bit ; Send upper nibble first movf LCD_Byte,W rcall Send_Low_4bit ; Send lower nibble data rcall Delay_100uS return ; Send_High_4bit swapf WREG,W ; swap high/low nibble Send_Low_4bit bcf LCD_RW ; set LCD Write Mode andlw 0x0F ; Clear high nibble movwf LCD_Temp movf LCD_DATA,W ; Read back PORT andlw 0xF0 ; keep data for PORTD[4:7] iorwf LCD_Temp,W movwf LCD_DATA ; Write data to LCD bus for low nibble bus DB[4:7] bcf LCD_RS ; Clear for command inut nop bsf LCD_E ; Clock nibble into LCD nop bcf LCD_E return ; ;******************************************************************* ;* clrLCD - Clear the contents of the LCD * ;******************************************************************* clrLCD movlw CLR_DISP ; Clear LCD screen rcall Send_Cmd movlw .5 ; Delay 5mS for Clear LCD Command execution bra Delay_xMS ; ;******************************************************************* ;* L1homeLCD - Moves the cursor to home position on Line 1 * ;******************************************************************* L1homeLCD movlw DD_RAM_ADDR|0x00 ; Send command to move cursor to rcall Send_Cmd ; home position on line 1 bra Delay_100uS ; ;******************************************************************* ;* L2homeLCD - Moves the cursor to home position on Line 2 * ;******************************************************************* L2homeLCD movlw DD_RAM_ADDR|0x40 ; Send command to move cursor to rcall Send_Cmd ; home position on line 2 bra Delay_100uS ; ;******************************************************************* ;* Delay - 1mS base delay * ;* input : W Reg. * ;* * ;******************************************************************* Delay_xMS movwf Count_mS ; _D_1mS call Delay_1mS decfsz Count_mS,F goto _D_1mS return ; ;******************************************************************* ;* Delay_1mS - Generic LCD delay (1.00mS @ 4MHz) * ;* Delay_100uS - Generic LCD delay 100us @ 4Mhz * * ;******************************************************************* Delay_1mS movlw .248 ; Load 1mS Dealy Value bra Delay_uS ; Delay_100uS movlw .25 ; Load delay 100uS value Delay_uS movwf Count_uS ; Save to Count2 _D_uS nop decfsz Count_uS,F ; Count2 - 1 = 0 ? bra _D_uS return ; END |