In a message dated 97-12-09 15:49:45 EST, you write: << Hi All, After working with the PIC for a while I thought it would be neat to display stuff on a character LCD. (Easier said than done, of course.) I bought an Optrex HD44780-based display and the data sheet by mail order, and when they arrived, the problems started. First of all, the data sheet read like a Chinese had translated the Japanese original into some sort of psuedo-English. The text itself acted like the LCD interface was common knowledge, so it only provided tips on such things as how the glookamoort starts when fizzinacked by the voltakork, which made it basically useless. So I gave up on the data sheet and looked into the Microchip Application Handbook, and found an app note describing how to interface of one of these little LCDs to a PIC. Cool, I thought. Just what I need. Unfortunately, this was the second problem. The app note was for a different PIC and the source code did not work. The article itself didn't explain much; the charts and tables were taken directly from the data sheet, except the decimal point in key timing values had moved around, which only added to the confusion. Despite this, I managed to get the 8-bit transfer mode working fine. After building several neat projects with the LCD, I realized that 11 I/O lines for the LCD doesn't leave much room for other gadgets to connect to the PIC, which only has 13 I/O lines. I looked back at the data sheet and the app note again, but they told me nothing. Now (Hoping that this won't be the third problem) for the question: Can anyone out there help me get this @%$#% thing working in the 4-bit transfer mode? I would like source code for the 16F84. Thanks in advance, Eric >> Hello Eric! Here is an include file I have used on my own projects. I think it is well commented but I don't gaurantee it is the best code for your job. I threw it together fast one evening and I probably stole half of it from somwhere on the net. It is written in standard Microchip assembly. This file should be called LCD4.inc In your source code put the line INCLUDE LCD4.inc at the point where you want the routines to go. If you need, I can probably dig up an example of how I have used it in the past. Hope this helps. Dave Duley ;************************************************************ ;Use this file for 4 bit LCD interfaces ;************************************************************ lcddata equ Port_B ; these two lines make it easy to port LCD lcdcntrl equ Port_A ; routines to the PIC 57 or whatever. LCD_DATA equ lcddata LCD_CNTL equ lcdcntrl ;************************************************************ ; Bit Definitions ;************************************************************ E equ 2 ;LCD enable strobe RS equ 3 ;LCD register select RW equ 4 ;LCD read write select lcd_strobe equ 03fh ;LCD strobe pulse width number_of_chars equ .20 ;# of characters on line Disp_On equ 0x00C ;Display on Disp_On_C equ 0x00E ;Display on Cursor on Disp_On_B equ 0x00F ;Display on cursor blink Disp_Off equ 0x008 ;Display off Clr_Disp equ 0x001 ;Clear display Entry_Inc equ 0x006 Entry_Inc_S equ 0x007 Entry_Dec equ 0x004 Entry_Dec_S equ 0x005 DD_RAM_ADDR equ 0x080 ;Least significant 7 bit are for address DD_RAM_UL equ 0x080 ;Upper Left corner of the display Busy_Check movlw TrisMaskB ;get I/O assignments bsf status,rp0 ;bank 1 select iorlw 0xf0 ;deal with only the upper nibble movwf Tris_B ;setup LCD to read data bcf status,rp0 bcf LCD_CNTL,RS bsf LCD_CNTL,RW call lcd_wait bsf LCD_CNTL,E ;get upper nibble bcf LCD_CNTL,E movf LCD_DATA,w ;get upper nibble of display data andlw 0xf0 ;mask off the lower nibble movwf temp bsf LCD_CNTL,E ;get lower nibble bcf LCD_CNTL,E swapf LCD_DATA,W andlw 0x0f ;mask off upper nibble iorwf temp,f btfsc temp,7 ;check busy flag goto Busy_Check ;do it again if still busy bcf LCD_CNTL,RW movlw TrisMaskB bsf status,rp0 Movwf Tris_B bcf status,rp0 return LCD_init ;init LCD display call lcd_wait bcf lcdcntrl,RS ;Set register select to command regs bcf lcdcntrl,E ;Clear the lcd module enable bit. bcf lcdcntrl,RW ;Clear the lcd module Read/Write bit. call lcd_wait movlw 0x020 ;set lcd module for 4 bit operation movwf lcddata bsf LCD_CNTL,E bcf LCD_CNTL,E call lcd_wait movlw 0x020 ;set lcd module for 4 bit operation movwf lcddata bsf LCD_CNTL,E bcf LCD_CNTL,E call lcd_wait movlw 0x080 ;set lcd module for 8 bit operation movwf lcddata bsf LCD_CNTL,E bcf LCD_CNTL,E movlw Disp_On ;set lcd on, cursor off call SEND_CMD movlw Clr_Disp ;Clear Display call SEND_CMD movlw Entry_Inc ;Set to increment display call SEND_CMD movlw DD_RAM_ADDR call SEND_CMD movlw number_of_chars movwf chcount bcf flag,7 goto lcd_wait ;******************************************************************* ;* The LCD Module Subroutines * ;******************************************************************* ; ;******************************************************************* ;*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. * ;******************************************************************* ; SEND_CHAR MOVWF CHAR ;Character to be sent is in W call Busy_Check movf CHAR,w ANDLW 0xF0 ;Get upper nibble movwf CharSave movf LCD_DATA,w andlw 0x0F iorwf CharSave,w ;only affect upper nibble of LCD_DATA MOVWF LCD_DATA ;Send data to LCD BSF LCD_CNTL, RS ;Set LCD to data mode BSF LCD_CNTL, E ;toggle E for LCD BCF LCD_CNTL, E SWAPF CHAR, w ANDLW 0xF0 ;Get lower nibble movwf CharSave movf LCD_DATA,w andlw 0x0F iorwf CharSave,w ;only affect upper nibble of LCD_DATA MOVWF LCD_DATA ;Send data to LCD BSF LCD_CNTL, E ;toggle E for LCD BCF LCD_CNTL, E return ;******************************************************************* ;* SEND_CMD - Sends command to LCD * ;* This routine splits the command into the upper and lower * ;* nibbles and sends them to the LCD, upper nibble first. * ;******************************************************************* SEND_CMD MOVWF CHAR ; Character to be sent is in W call Busy_Check movf CHAR,w ANDLW 0xF0 ; Get upper nibble movwf CharSave movf LCD_DATA,w andlw 0x0F iorwf CharSave,w ;only affect upper nibble of LCD_DATA MOVWF LCD_DATA ; Send data to LCD BCF LCD_CNTL,RS ; Set LCD to command mode BSF LCD_CNTL,E ; toggle E for LCD BCF LCD_CNTL,E SWAPF CHAR,w ANDLW 0xF0 ; Get lower nibble movwf CharSave movf LCD_DATA,w andlw 0x0F iorwf CharSave,w ;only affect upper nibble of LCD_DATA MOVWF LCD_DATA ; Send data to LCD BSF LCD_CNTL,E ; toggle E for LCD BCF LCD_CNTL,E return ;******************************************************************** ; This routine clears the LCD display * ;******************************************************************** dispclear bcf lcdcntrl,RS movlw 01h ;clear lcd display call SEND_CMD movlw 06h ;set entry mode on lcd module call SEND_CMD movlw number_of_chars movwf chcount bcf flag,7 ;******************************************************************** ; This routine waits 12ms for erase ans write commands * ;******************************************************************** lcd_wait movlw .48 movwf count wwait movlw 0ffh movwf temp wwait1 decfsz temp,f goto wwait1 decfsz count,f goto wwait retlw 0 ; LCD_Out ;put data at current cursor position on LCD call SEND_CHAR decf chcount,f retlw 0 set1st ;set display to display on the first line movlw 080h ;address cursor to 1st position call SEND_CMD movlw number_of_chars ;reset character counter movwf chcount bcf flag,7 ;reset line flag retlw 0 set2nd ;set display to display on the second line movlw 0c0h ;address cursor to 1st position 2nd line call SEND_CMD movlw number_of_chars ;reset character counter movwf chcount bsf flag,7 ;set line flag retlw 0