HD44780 LCD Initialization Issues

The Zander, Sat Apr 08 2006, 04:10AM

I recently aquired a 4X20 character LCD and i have been pulling my hair out trying to get the thing to work. i have plenty of experience with low level programming, and PICs, but i just can't seem to get the LCD initialized. perhapes someone more experienced in matters of this type may be able to help. i'll breifly outline exactly what i have done upto this point.

- connected LCD module and backlight to power, both turn on
- programmed a pic with the following simple program intended to simply display a flashing cursor

#include <P16F84A.INC>

DELAYCOUNT EQU 0CH

RW EQU 1
RS EQU 2
ENABLE EQU 3

START
	BSF STATUS, RP0
	MOVLW B'00000000'
	MOVWF TRISB
	MOVLW B'00000'
	MOVWF TRISA
	BCF STATUS, RP0

LOOPY
	MOVLW B'00011'
	MOVWF PORTA
	MOVLW D'250'
	MOVWF DELAYCOUNT
	CALL X_MS_DELAY
	CLRF PORTA
	MOVLW D'250'
	MOVWF DELAYCOUNT
	CALL X_MS_DELAY
	GOTO LOOPY

	MOVLW B'00000000'
	MOVWF PORTB
	MOVWF PORTA

	BCF PORTA, RW
	BCF PORTA, RS

	MOVLW B'00000110'
	MOVWF PORTB
	
	BSF PORTA, ENABLE
	CALL MS_DELAY
	BCF PORTA, ENABLE


LOOP
	NOP
	GOTO LOOP

MS_DELAY
	MOVLW D'250'
DELAYLOOP
	NOP
	NOP
	DECFSZ W
	GOTO DELAYLOOP
	RETURN

X_MS_DELAY
	DECFSZ DELAYCOUNT
	GOTO REPEAT
	RETURN
REPEAT
	CALL MS_DELAY
	GOTO X_MS_DELAY

END
- when powered up the backlight turns on, and i can adjust the constrast of the LCD display from black to zero, but there is no flashing cursor to be seen.
- PortB of the pic is connected to the data bus of the LCD, and bits on PortA corresponding the resigter select, and read/write and connected correctly as well.
- the PIC is of course powered, and it MCLR line held high.

any help remedying this problem is greatly appreciated

Thanx
-TheZander

[Edit: Made the loops easier to see.]
Re: HD44780 LCD Initialization Issues
Wolfram, Sat Apr 08 2006, 10:18AM

LOOPY
MOVLW B'00011'
MOVWF PORTA
MOVLW D'250'
MOVWF DELAYCOUNT
CALL X_MS_DELAY
CLRF PORTA
MOVLW D'250'
MOVWF DELAYCOUNT
CALL X_MS_DELAY
GOTO LOOPY


I don't see how it gets past this part, it looks like an endless loop to me.

Also, an other common mistake:
RW EQU 1
RS EQU 2
ENABLE EQU 3
Are you sure you didn't mean 0, 1 and 2?

Here are some good documents on driving character LCDs, if you haven't seen them already: Link2 Link2
Re: HD44780 LCD Initialization Issues
Avalanche, Sat Apr 08 2006, 12:25PM

I would say you probably haven't got long enough delays in. Those character modules are quite slow to respond I find.

A problem I had once was caused by the oscillator not starting up quickly enough. On power up, the PIC would skip through the LCD initialization routine way too quick for the module, before the oscillator settled down, and the PIC began running properly.
Re: HD44780 LCD Initialization Issues
rupidust, Sat Apr 08 2006, 08:18PM

[size]
I admire the effort. As for pulling your hair out, even the veterans run through a hundred compiles before it works.

Yes, LOOPY does not end. Calls to X_MS_DELAY is 320 milliseconds rather than 250, which can cause problems later. Too much going on with the X_MS_DELAY sub. If you can, keep it in one spot.

There is no need to load PORTA AND PORTB with 0's then in next line clear these bits:
BCF PORTA, RW
BCF PORTA, RS

Use B'xxxxxxxx' with all 8 bits, otherwise any bits not included are defaulted to 0.
MOVLW B'00000' = MOVLW B'00000000'


The delay sub MS_DELAY always generates a 1280 microsecond delay because decrementing W decrements 255 times. W is initially set to 0x00 because it is defined as W EQU H'0000' in the include file. The first loop lowers that H'00' to H'FF' forcing the DELAYLOOP to be repeated 254 more times regardless what MOVLW D'xxx' is set to. DECFSZ W does not decrement the PIC's working register unless you do this DECFSZ W, 0 which would repeatedly dump H'00' in to the true working register for eternity. W is meant to be used as a Destination flag in compliment with F.
MS_DELAY
    MOVLW D'250'      'EITHER MOVLW D'2' OR MOVLW D'250'
DELAYLOOP             'CAUSES 1280 MICROSECOND DELAY
    NOP
    NOP
    DECFSZ W
    GOTO DELAYLOOP
    RETURN

No harm in generating a full 1 millisecond delay to toggle the ENABLE line. However, since the ENABLE lines does not need that much time, needs only 10 micro seconds during pulse and after, this excess delay will cause timing issues later or at least make LCD writing extremelly slow.
BSF PORTA, ENABLE
    CALL MS_DELAY
    BCF PORTA, ENABLE
There is not point to reading from the LCD at the moment, therefore just tie the R/W LCD line to ground for write mode. That frees up a PIC i/o line and coding complications. If you do not have a scope, do all you can to get one, a digital one. [/size]
Re: HD44780 LCD Initialization Issues
The Zander, Wed Apr 12 2006, 01:40AM

<rupidist>

in regards to the MS_DELAY function causing a 1280ms delay

MS_DELAY
MOVLW D'250' 'EITHER MOVLW D'2' OR MOVLW D'250'
DELAYLOOP 'CAUSES 1280 MICROSECOND DELAY
NOP
NOP
DECFSZ W
GOTO DELAYLOOP
RETURN

it is my understanding the "nop" and "decfsz" execute in a single cycle (assuming the location w is != 0) and "goto delay loop" executes in 2 cycles. adding all of these up it would seem that the "delayloop" part of the above function should execute for 255 * 1uS, which yields 1020 microseconds (pretty close to 1mS). i'm not questioning your response, but i would like to know where my logic is flawed for future reference.

Thanx
-TheZander
Re: HD44780 LCD Initialization Issues
Bjørn, Wed Apr 12 2006, 02:02AM

What he really is trying to say is that your delay function does something completely different than you imagine.

"DECFSZ W" Will decrement address 0 because W is a special variable defined by the include file and is defined to be 0. Look in the datasheet for a little surprise to see what you really are decrementing.

To get your milisecond delay (at 4 MHz) you need to:
MS_DELAY
    MOVLW D'249'      ;Subtract one because the call and return takes two cycles each
    MOVWF DELAYCOUNT  ;You must move the count into a file, DECFSZ does not work on the W register.
DELAYLOOP
    NOP
    DECFSZ DELAYCOUNT
    GOTO DELAYLOOP    ;This takes two clock cycles so remove one nop
    RETURN

That should amount to a total of 1001 µs unless I counted wrong.
Re: HD44780 LCD Initialization Issues
rupidust, Wed Apr 12 2006, 09:32AM

[size]My scope measures the time I calculated. I used same code to flash an LED and noticed time was constant.
MS_DELAY
    MOVLW D'250'                ; 1 usec
DELAYLOOP                       ; 5 usec * 255
    NOP                               
    NOP                               
    DECFSZ W                       
    GOTO DELAYLOOP          
    RETURN                      ;2 usec

(5 * 255) - (1)   + 2 + 1 = 1277 usec + (external calls)
[/size]
Re: HD44780 LCD Initialization Issues
Bjørn, Wed Apr 12 2006, 10:28AM

There are two problems. Since W is defined to be 0 it points to the INDF register. It in turn points to an address contained in the FSR register. The FSR register has an undefined content at startup. So it may by luck be pointing to free RAM. Since it is undefined it may change at power up and/or behave differently in different models.

The other detail is that after the last DECFSZ W the content of the file will be 0 so it will loop 256 times and not 255.

If FSR=0 the Microchip simulator says that INDF will always return 0. It has been known to return the wrong result in some odd cases so it might possibly behave different in hardware.
Re: HD44780 LCD Initialization Issues
Steve Conner, Wed Apr 12 2006, 10:31AM

Bjorn is right. The decfsz instruction is only meant to be used on file registers. If you use it on the W register, it won't work. Look at the instruction set summary for a description of how it works.

Bjorn's reply made me finally realise why "W" is defined as zero in the include file. I guess it's for when you use it as an option bit with the decfsz, decf, incf, comf, etc. instructions. incf register,W gets preprocessed by the assembler into incf <address>,0

PICs have lots of fun quirks like this. But we put up with them because they're cheap and easy to buy wink
Re: HD44780 LCD Initialization Issues
The Zander, Wed Apr 12 2006, 09:19PM

EDIT:
well, my progress has halted once again, i have been able to partially initialize the LCD (as far as i can tell) i can get it to display the flashing cursor by simply sending the "turn LCD on, turn cursor on, blink cursor" instruction. but if i send the "8-bit interface instruction" or the "cursor increment direction" instrucion the cursor is not displayed. in addition i am completely unable to display characters on the LCD.

here is my new code:
#include <P16F84A.INC>

MS_DELAYCOUNT EQU 0DH
X_MS_DELAYCOUNT EQU 0CH
CHAR_TEMP EQU 0EH
INS_TEMP EQU 0FH

RW EQU 1
RS EQU 2
ENABLE EQU 3

START
BSF STATUS, RP0
MOVLW B'00000000'
MOVWF TRISB
MOVLW B'00000001'
MOVWF TRISA
BCF STATUS, RP0

MOVLW D'250'
MOVWF X_MS_DELAYCOUNT
CALL X_MS_DELAY

MOVLW B'00000000'
MOVWF PORTB
MOVWF PORTA

SETUP_INTERFACE
MOVLW B'00111000'
MOVWF INS_TEMP
CALL INS_WRITE

CALL MS_DELAY

TURN_DISPLAY_ON
MOVLW B'00001111'
MOVWF INS_TEMP
CALL INS_WRITE

CALL MS_DELAY

SET_MOVE_DIRECTION
MOVLW B'00000110'
MOVWF INS_TEMP
CALL INS_WRITE

CALL MS_DELAY

DISPLAY_A
; MOVLW B'01000001'
; MOVWF CHAR_TEMP
; CALL CHAR_WRITE


INS_WRITE

MOVF INS_TEMP, 0
MOVWF PORTB

BCF PORTA, RW
BCF PORTA, RS

BSF PORTA, ENABLE
CALL MS_DELAY
BCF PORTA, ENABLE
RETURN


CHAR_WRITE

MOVF CHAR_TEMP, 0
MOVWF PORTB

BCF PORTA, RW
BSF PORTA, RS

BSF PORTA, ENABLE
CALL MS_DELAY
BCF PORTA, ENABLE
RETURN


LOOP
NOP
GOTO LOOP

MS_DELAY
MOVLW D'250'
MOVWF MS_DELAYCOUNT
DELAYLOOP
NOP
NOP
DECFSZ MS_DELAYCOUNT, 1
GOTO DELAYLOOP
RETURN

X_MS_DELAY
DECFSZ X_MS_DELAYCOUNT
GOTO REPEAT
RETURN
REPEAT
CALL MS_DELAY
GOTO X_MS_DELAY

END

Once again, i appologize for using you guys like spellcheckers, but honestly i have been compiling/fiddling with this for hours on end and am getting no where on my own.

-TheZander
Re: HD44780 LCD Initialization Issues
rupidust, Thu Apr 13 2006, 08:29AM

[size]Worked for me. Got Letter 'A' to display. If it initialized and you see a blinking cursor that is not randomly and rapidly moving around, you could be just one step away from it working. Is your MCLR line tied HIGH? Are you connecting the LCD pins in the order of the code? Look at this:
RW EQU 1
RS EQU 2
ENABLE EQU 3

;TRY
RS EQU 1
RW EQU 2
ENABLE EQU 3
I used the same values but had to connect the LCD i/o lines as the LCD needs them: RS first (pin 5), RW second (pin 4), and Enable third (pin 6). If I connected PortA, RW to LCD pin 4, it initializes but does not display 'A'.

This does not effect the LCD, but the delays are still running long. 1 milliseconds reads 1.260ms and 250 milliseconds reads 315ms, meaning an extra reapet is happening. Paypal is fine shades
[/size]
Re: HD44780 LCD Initialization Issues
The Zander, Thu Apr 13 2006, 03:53PM

[rupidist]

Any idea why reversing the pins solves the problem? seems like a wierd fix to me. i'll have to try it later today, hope it works.

[edit]
after a bit of contemplating i'm confused as to what exactly you did you get the LCD to display "A",what do you mean by you connected the i/o line as the LCD needed them? is that the order in which you activated them on the PIC, or the order in which you physically connected them (ie: plug one in, then the next, then the next)

Thanx
-TheZander