/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*;************************************************;listp=18F452#include <P18F452.inc>;globalInitLCDglobalputcLCDglobalclrLCDglobalL1homeLCDglobalL2homeLCDglobal Send_CmdglobalPutHexLCDglobalHex2ASCIIglobalDelay_xMSglobalDelay_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_CTRLequTRISDLCD_DATAequPORTD#defineLCD_E_DIRTRISA,1#defineLCD_RW_DIRTRISA,2#defineLCD_RS_DIRTRISA,3#defineLCD_EPORTA,1#defineLCD_RW PORTA,2#defineLCD_RSPORTA,3 ; LCD Module commandsCLR_DISPequb'00000001'; 1.64mS , Clear display and return cursor to homeCursor_Homeequb'00000010'; 1.64mS , Return cursor to home positionENTRY_DECequb'00000100'; 40uS , Decrement cursor position & No display shiftENTRY_DEC_Sequb'00000101'; 40uS , Decrement cursor position & display shiftENTRY_INCequb'00000110'; 40uS , Increment cursor position & No display shiftENTRY_INC_Sequb'00000111'; 40uS , Increment cursor position & display shiftDISP_OFFequb'00001000'; 40uS , Display offDISP_ONequb'00001100'; 40uS , Display on controlDISP_ON_Cequb'00001110'; 40uS , Display on, Cursor onDISP_ON_Bequ b'00001111'; 40uS , Display on, Cursor on, Blink cursorFUNC_SETequb'00101000'; 40uS , 4-bit interface , 2-lines & 5x7 dotsCG_RAM_ADDRequb'01000000'; 40uS , Least Significant 6-bit are for CGRAM addressDD_RAM_ADDRequb'10000000'; 40uS , Least Significant 7-bit are for DDRAM address;; Directs linker to provide 4 variables in GPR memoryUDATALCD_ByteRES1LCD_TempRES1Count_uSRES1Count_mSRES1W_BUFRRES1Hex_Bfr RES1;LCD_CODE CODE;*******************************************************************;* The LCD Module Subroutines *;* Command sequence for 2 lines of 5x16 characters *;*******************************************************************InitLCDbcfLCD_E; Clear LCD control line to ZerobcfLCD_RW bcfLCD_RS ;bcfLCD_E_DIR;configure control lines for Output pinbcfLCD_RW_DIRbcfLCD_RS_DIR;movlwb'00001110'; configure AN0 as A/D inut pinmovwfADCON1movfLCD_CTRL,W; get I/O directional settngandlw0xF0movwfLCD_CTRL; set LCD bus DB[4:7] for output;movlw.50; Power-On delay 50mSrcall Delay_xMS;movlw b'00000011'; #1 , Init for 4-bit interfacercallSend_Low_4bit;movlw.10; Delay 10 mSrcall Delay_xMS;movlwb'00000011'; #2 , Fully Initial LCD module rcallSend_Low_4bit; Sent '0011' data rcall Delay_1mS;movlwb'00000011'; #3 , Fully Initial LCD module rcallSend_Low_4bit; Sent '0011' data rcall Delay_1mS;movlwb'00000010'; #4 , Fully Initial LCD module rcallSend_Low_4bit; Sent '0010' data rcall Delay_1mS;movlwFUNC_SET; #5,#6 , Set 4-bit mode , 2 lines & 5 x 7 dotsrcallSend_Cmdrcall Delay_1mS;movlwDISP_ON ; #7,#8 , Turn display on (0x0C)rcallSend_Cmdrcall Delay_1mS;movlwCLR_DISP; #9,#10 , Clear LCD ScreenrcallSend_Cmdmovlw.5; Delay 5mS for Clear LCD Command executionrcall Delay_xMS;movlwENTRY_INC; #11,#12 , Configure cursor movementrcallSend_Cmdrcall Delay_1mS;movlwDD_RAM_ADDR; Set writes for display memoryrcallSend_Cmdrcall 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. *;*******************************************************************putcLCDmovwfLCD_Byte; Save WREG in Byte variablercallSend_High_LCD; Send upper nibble firstmovfLCD_Byte,WrcallSend_Low_LCD; Send lower nibble datarcallDelay_100uSreturn;Send_High_LCD swapfWREG,W; swap high/low nibbleSend_Low_LCD bcfLCD_RW; set LCD Write Modeandlw0x0F; Clear high nibblemovwfLCD_TempmovfLCD_DATA,W; Read back PORTandlw0xF0; keep data for PORTD[4:7]iorwfLCD_Temp,Wmovwf LCD_DATA; Write data to LCD busfor low nibble bus DB[4:7]bsfLCD_RS; Set for data inputnopbsfLCD_E; Clock nibble into LCDnopbcfLCD_Ereturn;;*********************************************************************;* To put the HEX value to LCD Display ,,;* High nibble first than Low nibble ;* Input : W Reg.;*********************************************************************PutHexLCDmovwfW_BUFR; Save W Register !!swapfW_BUFR,W; High nibble first !!rcallHex2ASCIIrcallputcLCD;movfW_BUFR,WrcallHex2ASCIIrcallputcLCDreturn;;******************************************************************;* Convert a low nibble to ASCII code;* Input : W Reg.;* Output: W Reg.;******************************************************************Hex2ASCIIandlw0x0f; Mask Bit 4 to 7movwfHex_Bfrsublw.09btfscSTATUS,C; If W less than A (C=1) --> only add 30hbra_Add_W_30 _Add_W_37movlw0x37bra_Hex_cont _Add_W_30movlw0x30_Hex_contaddwfHex_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_CmdmovwfLCD_Byte; Save WREG in Byte variablercallSend_High_4bit; Send upper nibble firstmovfLCD_Byte,WrcallSend_Low_4bit; Send lower nibble datarcallDelay_100uSreturn;Send_High_4bitswapfWREG,W; swap high/low nibbleSend_Low_4bitbcfLCD_RW; set LCD Write Modeandlw0x0F; Clear high nibblemovwfLCD_TempmovfLCD_DATA,W; Read back PORTandlw0xF0; keep data for PORTD[4:7]iorwfLCD_Temp,Wmovwf LCD_DATA; Write data to LCD busfor low nibble bus DB[4:7]bcfLCD_RS; Clear for command inutnopbsfLCD_E; Clock nibble into LCDnopbcfLCD_Ereturn;;*******************************************************************;* clrLCD - Clear the contents of the LCD *;*******************************************************************clrLCDmovlwCLR_DISP; Clear LCD screenrcallSend_Cmdmovlw.5; Delay 5mS for Clear LCD Command executionbra Delay_xMS;;*******************************************************************;* L1homeLCD - Moves the cursor to home position on Line 1 *;*******************************************************************L1homeLCDmovlwDD_RAM_ADDR|0x00 ; Send command to move cursor to rcallSend_Cmd ; home position on line 1braDelay_100uS;;*******************************************************************;* L2homeLCD - Moves the cursor to home position on Line 2 *;*******************************************************************L2homeLCDmovlwDD_RAM_ADDR|0x40 ; Send command to move cursor torcallSend_Cmd ; home position on line 2braDelay_100uS;;*******************************************************************;* Delay - 1mS base delay *;* input : W Reg. *;* *;*******************************************************************Delay_xMSmovwfCount_mS;_D_1mScallDelay_1mSdecfszCount_mS,Fgoto_D_1mSreturn;;*******************************************************************;* Delay_1mS - Generic LCD delay (1.00mS @ 4MHz) *;* Delay_100uS - Generic LCD delay 100us @ 4Mhz * *;*******************************************************************Delay_1mSmovlw.248; Load 1mS Dealy ValuebraDelay_uS;Delay_100uSmovlw.25; Load delay 100uS valueDelay_uSmovwfCount_uS; Save to Count2_D_uSnopdecfszCount_uS,F; Count2 - 1 = 0 ?bra_D_uSreturn;END |