EmbeddedRelated.com
Forums

Help getting an LCD to work

Started by Will February 3, 2004
I have an Optrex LCD (DMC-20481NY-LY-AGE) that is 4x20 characters and
driven by a Microchip PIC16F877 running at 20MHz.  I know I got this
exact same physical LCD to work before but for the life of me I can't
recall what trick I used to do so.  Attached at the end is my
software.  I get power to the LCD, but all I see is lines 1 and 3 as
all dark and lines 2 and 4 as all clear.  Hunting around newsgroups
leads me to think my initialization routines aren't working (gee, ya
think?!?!) but as near as I can tell I have met or exceeded all of the
timing requirements for data transfer.  PLEASE HELP!!!!!  If it
matters, I am using a dedicated 5V DC supply to drive both the PIC and
the LCD.  The PIC is connected  to the LCD through 330 Ohm resistors,
with 10KOhm pulldown resistors to ground on ALL of the lines on the
PIC side.  This was because I was seeing a lot of glitches on powerup
due to ports being inputs.  Each line also has a .01uF cap to ground
and there is a bypass capacitor on the 5V line to ground next to the
PIC.  The BusyFlag is also connected directly from the LCD to the PIC
on PORTB, 6.  Thanks for any insight!
-Will

;	LCD Control Software
;
;	Software uses a 20MHz crystal
;	for timing.
;

;******************************************************************
Stall	MACRO
		LOCAL	  Stall_Jump
		goto Stall_Jump
Stall_Jump
	ENDM
;******************************************************************
Wait_For_Busy_Flag MACRO
	btfsc BUSY_FLAG
	goto $-1
	ENDM
;******************************************************************
Wait_15ms MACRO
	LOCAL OuterLoop
	LOCAL InnerLoop

	movlw .59
	movwf OUTER_COUNTER
OuterLoop
	movlw .255
	movwf INNER_COUNTER
InnerLoop
	Stall
	decfsz INNER_COUNTER, F
	goto InnerLoop
	decfsz OUTER_COUNTER, F
	goto OuterLoop
	ENDM
;******************************************************************
Wait_4.1ms MACRO
	LOCAL OuterLoop
	LOCAL InnerLoop

	movlw .17
	movwf OUTER_COUNTER
OuterLoop
	movlw .255
	movwf INNER_COUNTER
InnerLoop
	Stall
	decfsz INNER_COUNTER, F
	goto InnerLoop
	decfsz OUTER_COUNTER, F
	goto OuterLoop
	ENDM
;******************************************************************
Wait_100us MACRO
	LOCAL InnerLoop

	movlw .100
	movwf INNER_COUNTER
InnerLoop
	Stall
	decfsz INNER_COUNTER, F
	goto InnerLoop
	ENDM
;******************************************************************

	list p=16F877

	; Include file, change directory	if	needed
	include "p16f877.inc"

#define ENABLE 		PORTE, 2
#define RS 				PORTE, 1
#define RW 				PORTE, 0

#define DATA_PORT 	PORTD
#define BUSY_FLAG 	PORTB, 6

OUTER_COUNTER		equ 0x20
INNER_COUNTER		equ 0x21


W_TEMP			equ 0x70
STATUS_TEMP		equ 0x71
PCLATH_TEMP		equ 0x72


;//Reset Vector
 Org 0x00
	clrf	 PCLATH				 ;	ensure page	bits are	cleared
	goto	 Initialize

;//Interrupt Vector
 ORG 0x04
	MOVWF   W_TEMP          ;Copy W to TEMP register
	SWAPF   STATUS,W        ;Swap status to be saved into W
	CLRF    STATUS          ;bank 0, regardless of current bank, Clears
IRP,RP1,RP0
	MOVWF   STATUS_TEMP     ;Save status to bank zero STATUS_TEMP
register
	MOVF    PCLATH, W       ;Only required if using pages 1, 2 and/or 3
	MOVWF   PCLATH_TEMP     ;Save PCLATH into W
	CLRF    PCLATH          ;Page zero, regardless of current page

	;Fill this in if you want interrupt vectoring

	banksel PCLATH_TEMP
	MOVF    PCLATH_TEMP, W  ;Restore PCLATH
	MOVWF   PCLATH          ;Move W into PCLATH
	SWAPF   STATUS_TEMP,W   ;Swap STATUS_TEMP register into W
			                  ;(sets bank to original state)
	MOVWF   STATUS          ;Move W into STATUS register
	SWAPF   W_TEMP,F        ;Swap W_TEMP
	SWAPF   W_TEMP,W        ;Swap W_TEMP into W
	retfie						; return from interrupt

;//Initialization
Initialize
	clrf INTCON
	clrf INTCON
CGIE
	bcf	 INTCON,	GIE
	btfsc	 INTCON,	GIE
	goto	 CGIE

;	//Declare port/pin definitions
	banksel TRISA
	movlw  B'00000111'
	movwf  ADCON1			; Port A is all digital
	movlw	 B'00000000'
	movwf	 TRISA			; Port A is OOOOOOOO
	movlw	 B'01000000'
	movwf	 TRISB			; Port B is OIOOOOOO
	movlw	 B'10000001'
	movwf	 TRISC			; Port C is IOOOOOOI
	movlw	 B'00000000'
	movwf	 TRISD			; Port D is OOOOOOOO
	bcf TRISE, PSPMODE	; Turn off the parallel port
	bcf TRISE, 0			; Port E is -----OOO
	bcf TRISE, 1
	bcf TRISE, 2

	bsf OPTION_REG, 7		;Turn off port B pullups

	banksel OUTER_COUNTER
	bsf PORTB, 7

	Wait_15ms
	Wait_15ms

	bcf PORTB, 7

	bcf RS
	bcf RW
	movlw b'00111000'
	call StrobeData

	Wait_4.1ms
	Wait_4.1ms

	bcf RS
	bcf RW
	movlw b'00111000'
	call StrobeData

	Wait_4.1ms
	Wait_4.1ms

	bcf RS
	bcf RW
	movlw b'00111000'
	call StrobeData

	Wait_4.1ms
	Wait_4.1ms

	call DisplayOFF_CursorOFF_BlinkOFF
	Wait_15ms
	Wait_4.1ms

	call DisplayON_CursorON_BlinkON
	Wait_15ms
	Wait_4.1ms

	call EntryModeSet
	Wait_100us

	call ClearDisplay
	Wait_15ms
	Wait_4.1ms

	movlw b'01001000'	;H
	call SendChar
	movlw b'01100101'	;e
	call SendChar
	movlw b'01101100'	;l
	call SendChar
	movlw b'01101100'	;l
	call SendChar
	movlw b'01101111'	;o
	call SendChar
	movlw b'01010111'	;W
	call SendChar
	movlw b'01101111'	;o
	call SendChar
	movlw b'01110010'	;r
	call SendChar
	movlw b'01101100'	;l
	call SendChar
	movlw b'01100100'	;d
	call SendChar

Eternal
	bcf PORTB, 0
	nop
	bsf PORTB, 0
	goto Eternal
	
;-----------
StrobeData
	nop
	bsf ENABLE
	nop
	movwf DATA_PORT
	nop
	bcf ENABLE
	return
;-----------
EntryModeSet
	btfsc BUSY_FLAG
	goto EntryModeSet
	bcf RS
	bcf RW
	movlw b'00000110'
	call StrobeData
	return
;-----------
SendChar
	btfsc BUSY_FLAG
	goto SendChar
	bsf RS
	bcf RW
	call StrobeData
	return
;-----------
ClearDisplay
	btfsc BUSY_FLAG
	goto ClearDisplay
	bcf RS
	bcf RW
	movlw 0x01
	call StrobeData
	return
;-----------
HomeCursor
	btfsc BUSY_FLAG
	goto HomeCursor
	bcf RS
	bcf RW
	movlw 0x02
	call StrobeData
	return
;-----------
DisplayOFF_CursorOFF_BlinkOFF
	btfsc BUSY_FLAG
	goto DisplayOFF_CursorOFF_BlinkOFF
	bcf RS
	bcf RW
	movlw b'00001000'
	call StrobeData
	return
;-----------
DisplayOFF_CursorOFF_BlinkON
	btfsc BUSY_FLAG
	goto DisplayOFF_CursorOFF_BlinkON
	bcf RS
	bcf RW
	movlw b'00001001'
	call StrobeData
	return
;-----------
DisplayOFF_CursorON_BlinkOFF
	btfsc BUSY_FLAG
	goto DisplayOFF_CursorON_BlinkOFF
	bcf RS
	bcf RW
	movlw b'00001010'
	call StrobeData
	return
;-----------
DisplayOFF_CursorON_BlinkON
	btfsc BUSY_FLAG
	goto DisplayOFF_CursorON_BlinkON
	bcf RS
	bcf RW
	movlw b'00001011'
	call StrobeData
	return
;-----------
DisplayON_CursorOFF_BlinkOFF
	btfsc BUSY_FLAG
	goto DisplayON_CursorOFF_BlinkOFF
	bcf RS
	bcf RW
	movlw b'00001100'
	call StrobeData
	return
;-----------
DisplayON_CursorOFF_BlinkON
	btfsc BUSY_FLAG
	goto DisplayON_CursorOFF_BlinkON
	bcf RS
	bcf RW
	movlw b'00001101'
	call StrobeData
	return
;-----------
DisplayON_CursorON_BlinkOFF
	btfsc BUSY_FLAG
	goto DisplayON_CursorON_BlinkOFF
	bcf RS
	bcf RW
	movlw b'00001110'
	call StrobeData
	return
;-----------
DisplayON_CursorON_BlinkON
	btfsc BUSY_FLAG
	goto DisplayON_CursorON_BlinkON
	bcf RS
	bcf RW
	movlw b'00001111'
	call StrobeData
	return
;-----------
 END
Hi, the 2 dark lines means that the module has not been initialised. Remove all
the components from the connections to the module, just connect directly.
Hi again, i just noited that your "strobe data" is too fast, check the data
sheet for timming, also your should put the data on the port before the enable
pulse.
Will wrote:

> I have an Optrex LCD (DMC-20481NY-LY-AGE) that is 4x20 characters and > driven by a Microchip PIC16F877 running at 20MHz. I know I got this > exact same physical LCD to work before but for the life of me I can't > recall what trick I used to do so. Attached at the end is my > software. I get power to the LCD, but all I see is lines 1 and 3 as > all dark and lines 2 and 4 as all clear. Hunting around newsgroups > leads me to think my initialization routines aren't working (gee, ya > think?!?!) but as near as I can tell I have met or exceeded all of the > timing requirements for data transfer. PLEASE HELP!!!!! If it > matters, I am using a dedicated 5V DC supply to drive both the PIC and > the LCD. The PIC is connected to the LCD through 330 Ohm resistors, > with 10KOhm pulldown resistors to ground on ALL of the lines on the > PIC side. This was because I was seeing a lot of glitches on powerup > due to ports being inputs. Each line also has a .01uF cap to ground > and there is a bypass capacitor on the 5V line to ground next to the > PIC. The BusyFlag is also connected directly from the LCD to the PIC > on PORTB, 6. Thanks for any insight!
[...] 10nF on each signal line is quite a lot! Why do you need such a big capacitive load on the data wires? Have you checked the timing on a scope, or are you just counting clock cycles in your program? -- Cheers Stefan
Make sure you have the proper delays in the Init routines.
I've used the same display  and had problems with short delays in the Init routines.

Cheers

"Will" <larkmore@aol.com> wrote in message news:5faf6114.0402031434.38db8ce2@posting.google.com...
> I have an Optrex LCD (DMC-20481NY-LY-AGE) that is 4x20 characters and > driven by a Microchip PIC16F877 running at 20MHz. I know I got this > exact same physical LCD to work before but for the life of me I can't > recall what trick I used to do so. Attached at the end is my > software. I get power to the LCD, but all I see is lines 1 and 3 as > all dark and lines 2 and 4 as all clear. Hunting around newsgroups > leads me to think my initialization routines aren't working (gee, ya > think?!?!) but as near as I can tell I have met or exceeded all of the > timing requirements for data transfer. PLEASE HELP!!!!! If it > matters, I am using a dedicated 5V DC supply to drive both the PIC and > the LCD. The PIC is connected to the LCD through 330 Ohm resistors, > with 10KOhm pulldown resistors to ground on ALL of the lines on the > PIC side. This was because I was seeing a lot of glitches on powerup > due to ports being inputs. Each line also has a .01uF cap to ground > and there is a bypass capacitor on the 5V line to ground next to the > PIC. The BusyFlag is also connected directly from the LCD to the PIC > on PORTB, 6. Thanks for any insight! > -Will > > ; LCD Control Software > ; > ; Software uses a 20MHz crystal > ; for timing. > ; > > ;****************************************************************** > Stall MACRO > LOCAL Stall_Jump > goto Stall_Jump > Stall_Jump > ENDM > ;****************************************************************** > Wait_For_Busy_Flag MACRO > btfsc BUSY_FLAG > goto $-1 > ENDM > ;****************************************************************** > Wait_15ms MACRO > LOCAL OuterLoop > LOCAL InnerLoop > > movlw .59 > movwf OUTER_COUNTER > OuterLoop > movlw .255 > movwf INNER_COUNTER > InnerLoop > Stall > decfsz INNER_COUNTER, F > goto InnerLoop > decfsz OUTER_COUNTER, F > goto OuterLoop > ENDM > ;****************************************************************** > Wait_4.1ms MACRO > LOCAL OuterLoop > LOCAL InnerLoop > > movlw .17 > movwf OUTER_COUNTER > OuterLoop > movlw .255 > movwf INNER_COUNTER > InnerLoop > Stall > decfsz INNER_COUNTER, F > goto InnerLoop > decfsz OUTER_COUNTER, F > goto OuterLoop > ENDM > ;****************************************************************** > Wait_100us MACRO > LOCAL InnerLoop > > movlw .100 > movwf INNER_COUNTER > InnerLoop > Stall > decfsz INNER_COUNTER, F > goto InnerLoop > ENDM > ;****************************************************************** > > list p=16F877 > > ; Include file, change directory if needed > include "p16f877.inc" > > #define ENABLE PORTE, 2 > #define RS PORTE, 1 > #define RW PORTE, 0 > > #define DATA_PORT PORTD > #define BUSY_FLAG PORTB, 6 > > OUTER_COUNTER equ 0x20 > INNER_COUNTER equ 0x21 > > > W_TEMP equ 0x70 > STATUS_TEMP equ 0x71 > PCLATH_TEMP equ 0x72 > > > ;//Reset Vector > Org 0x00 > clrf PCLATH ; ensure page bits are cleared > goto Initialize > > ;//Interrupt Vector > ORG 0x04 > MOVWF W_TEMP ;Copy W to TEMP register > SWAPF STATUS,W ;Swap status to be saved into W > CLRF STATUS ;bank 0, regardless of current bank, Clears > IRP,RP1,RP0 > MOVWF STATUS_TEMP ;Save status to bank zero STATUS_TEMP > register > MOVF PCLATH, W ;Only required if using pages 1, 2 and/or 3 > MOVWF PCLATH_TEMP ;Save PCLATH into W > CLRF PCLATH ;Page zero, regardless of current page > > ;Fill this in if you want interrupt vectoring > > banksel PCLATH_TEMP > MOVF PCLATH_TEMP, W ;Restore PCLATH > MOVWF PCLATH ;Move W into PCLATH > SWAPF STATUS_TEMP,W ;Swap STATUS_TEMP register into W > ;(sets bank to original state) > MOVWF STATUS ;Move W into STATUS register > SWAPF W_TEMP,F ;Swap W_TEMP > SWAPF W_TEMP,W ;Swap W_TEMP into W > retfie ; return from interrupt > > ;//Initialization > Initialize > clrf INTCON > clrf INTCON > CGIE > bcf INTCON, GIE > btfsc INTCON, GIE > goto CGIE > > ; //Declare port/pin definitions > banksel TRISA > movlw B'00000111' > movwf ADCON1 ; Port A is all digital > movlw B'00000000' > movwf TRISA ; Port A is OOOOOOOO > movlw B'01000000' > movwf TRISB ; Port B is OIOOOOOO > movlw B'10000001' > movwf TRISC ; Port C is IOOOOOOI > movlw B'00000000' > movwf TRISD ; Port D is OOOOOOOO > bcf TRISE, PSPMODE ; Turn off the parallel port > bcf TRISE, 0 ; Port E is -----OOO > bcf TRISE, 1 > bcf TRISE, 2 > > bsf OPTION_REG, 7 ;Turn off port B pullups > > banksel OUTER_COUNTER > bsf PORTB, 7 > > Wait_15ms > Wait_15ms > > bcf PORTB, 7 > > bcf RS > bcf RW > movlw b'00111000' > call StrobeData > > Wait_4.1ms > Wait_4.1ms > > bcf RS > bcf RW > movlw b'00111000' > call StrobeData > > Wait_4.1ms > Wait_4.1ms > > bcf RS > bcf RW > movlw b'00111000' > call StrobeData > > Wait_4.1ms > Wait_4.1ms > > call DisplayOFF_CursorOFF_BlinkOFF > Wait_15ms > Wait_4.1ms > > call DisplayON_CursorON_BlinkON > Wait_15ms > Wait_4.1ms > > call EntryModeSet > Wait_100us > > call ClearDisplay > Wait_15ms > Wait_4.1ms > > movlw b'01001000' ;H > call SendChar > movlw b'01100101' ;e > call SendChar > movlw b'01101100' ;l > call SendChar > movlw b'01101100' ;l > call SendChar > movlw b'01101111' ;o > call SendChar > movlw b'01010111' ;W > call SendChar > movlw b'01101111' ;o > call SendChar > movlw b'01110010' ;r > call SendChar > movlw b'01101100' ;l > call SendChar > movlw b'01100100' ;d > call SendChar > > Eternal > bcf PORTB, 0 > nop > bsf PORTB, 0 > goto Eternal > > ;----------- > StrobeData > nop > bsf ENABLE > nop > movwf DATA_PORT > nop > bcf ENABLE > return > ;----------- > EntryModeSet > btfsc BUSY_FLAG > goto EntryModeSet > bcf RS > bcf RW > movlw b'00000110' > call StrobeData > return > ;----------- > SendChar > btfsc BUSY_FLAG > goto SendChar > bsf RS > bcf RW > call StrobeData > return > ;----------- > ClearDisplay > btfsc BUSY_FLAG > goto ClearDisplay > bcf RS > bcf RW > movlw 0x01 > call StrobeData > return > ;----------- > HomeCursor > btfsc BUSY_FLAG > goto HomeCursor > bcf RS > bcf RW > movlw 0x02 > call StrobeData > return > ;----------- > DisplayOFF_CursorOFF_BlinkOFF > btfsc BUSY_FLAG > goto DisplayOFF_CursorOFF_BlinkOFF > bcf RS > bcf RW > movlw b'00001000' > call StrobeData > return > ;----------- > DisplayOFF_CursorOFF_BlinkON > btfsc BUSY_FLAG > goto DisplayOFF_CursorOFF_BlinkON > bcf RS > bcf RW > movlw b'00001001' > call StrobeData > return > ;----------- > DisplayOFF_CursorON_BlinkOFF > btfsc BUSY_FLAG > goto DisplayOFF_CursorON_BlinkOFF > bcf RS > bcf RW > movlw b'00001010' > call StrobeData > return > ;----------- > DisplayOFF_CursorON_BlinkON > btfsc BUSY_FLAG > goto DisplayOFF_CursorON_BlinkON > bcf RS > bcf RW > movlw b'00001011' > call StrobeData > return > ;----------- > DisplayON_CursorOFF_BlinkOFF > btfsc BUSY_FLAG > goto DisplayON_CursorOFF_BlinkOFF > bcf RS > bcf RW > movlw b'00001100' > call StrobeData > return > ;----------- > DisplayON_CursorOFF_BlinkON > btfsc BUSY_FLAG > goto DisplayON_CursorOFF_BlinkON > bcf RS > bcf RW > movlw b'00001101' > call StrobeData > return > ;----------- > DisplayON_CursorON_BlinkOFF > btfsc BUSY_FLAG > goto DisplayON_CursorON_BlinkOFF > bcf RS > bcf RW > movlw b'00001110' > call StrobeData > return > ;----------- > DisplayON_CursorON_BlinkON > btfsc BUSY_FLAG > goto DisplayON_CursorON_BlinkON > bcf RS > bcf RW > movlw b'00001111' > call StrobeData > return > ;----------- > END
I can only tell you from my experience which things made my life difficult
with LCD.

1. Contrast voltage had to be negative.

  I belive it isn't the case in your case, you only have to connect 10k
potentiometer
  for contrast.

2. Inpropper initialization routine.

  Wrong sequence of initialization commands. If order off commands is not
right it
  can cause a lot of headaches.

3. Using BUSY flag?

   When using BUSY flag you have to watch carefuly during the initialization
routine
   when the busy flag can be checked.

In your case my guess you would be you have incorrect initialization routine
maybe
timings are ok but the order of commands isn't.
I had done initialization as written in one datasheet of my 2x16 LCD, and it
worked
badly sometimes it would initialize the LCD, and sometimes wouldn't I found
another
sequence for initializing on the Internet and it worked great since then.

Mickey


"Will" <larkmore@aol.com> wrote in message
news:5faf6114.0402031434.38db8ce2@posting.google.com...
> I have an Optrex LCD (DMC-20481NY-LY-AGE) that is 4x20 characters and > driven by a Microchip PIC16F877 running at 20MHz. I know I got this > exact same physical LCD to work before but for the life of me I can't > recall what trick I used to do so. Attached at the end is my > software. I get power to the LCD, but all I see is lines 1 and 3 as > all dark and lines 2 and 4 as all clear. Hunting around newsgroups > leads me to think my initialization routines aren't working (gee, ya > think?!?!) but as near as I can tell I have met or exceeded all of the > timing requirements for data transfer. PLEASE HELP!!!!! If it > matters, I am using a dedicated 5V DC supply to drive both the PIC and > the LCD. The PIC is connected to the LCD through 330 Ohm resistors, > with 10KOhm pulldown resistors to ground on ALL of the lines on the > PIC side. This was because I was seeing a lot of glitches on powerup > due to ports being inputs. Each line also has a .01uF cap to ground > and there is a bypass capacitor on the 5V line to ground next to the > PIC. The BusyFlag is also connected directly from the LCD to the PIC > on PORTB, 6. Thanks for any insight! > -Will
Your strobedata routine is too fast. Many LCD displays have a cycle time of 500ns to 1000ns, where the E has to be kept high for 300 to 500ns or longer. Apart from that, your filtering of the datalines kills your signals. 0.01uF and 330 Ohm has a time constant of 3.3us. Your signals in the order of 1us cycle times will NEVER pass this filter. Remove the caps and resistors and you'll be fine. Meindert
Have a look at this very usfull sofware pic simulator including lcd
http://www.oshonsoft.com/pic.html
regards
bob
"Will" <larkmore@aol.com> wrote in message
news:5faf6114.0402031434.38db8ce2@posting.google.com...
> I have an Optrex LCD (DMC-20481NY-LY-AGE) that is 4x20 characters and > driven by a Microchip PIC16F877 running at 20MHz. I know I got this > exact same physical LCD to work before but for the life of me I can't > recall what trick I used to do so. Attached at the end is my > software. I get power to the LCD, but all I see is lines 1 and 3 as > all dark and lines 2 and 4 as all clear. Hunting around newsgroups > leads me to think my initialization routines aren't working (gee, ya > think?!?!) but as near as I can tell I have met or exceeded all of the > timing requirements for data transfer. PLEASE HELP!!!!! If it > matters, I am using a dedicated 5V DC supply to drive both the PIC and > the LCD. The PIC is connected to the LCD through 330 Ohm resistors, > with 10KOhm pulldown resistors to ground on ALL of the lines on the > PIC side. This was because I was seeing a lot of glitches on powerup > due to ports being inputs. Each line also has a .01uF cap to ground > and there is a bypass capacitor on the 5V line to ground next to the > PIC. The BusyFlag is also connected directly from the LCD to the PIC > on PORTB, 6. Thanks for any insight! > -Will > > ; LCD Control Software > ; > ; Software uses a 20MHz crystal > ; for timing. > ; > > ;****************************************************************** > Stall MACRO > LOCAL Stall_Jump > goto Stall_Jump > Stall_Jump > ENDM > ;****************************************************************** > Wait_For_Busy_Flag MACRO > btfsc BUSY_FLAG > goto $-1 > ENDM > ;****************************************************************** > Wait_15ms MACRO > LOCAL OuterLoop > LOCAL InnerLoop > > movlw .59 > movwf OUTER_COUNTER > OuterLoop > movlw .255 > movwf INNER_COUNTER > InnerLoop > Stall > decfsz INNER_COUNTER, F > goto InnerLoop > decfsz OUTER_COUNTER, F > goto OuterLoop > ENDM > ;****************************************************************** > Wait_4.1ms MACRO > LOCAL OuterLoop > LOCAL InnerLoop > > movlw .17 > movwf OUTER_COUNTER > OuterLoop > movlw .255 > movwf INNER_COUNTER > InnerLoop > Stall > decfsz INNER_COUNTER, F > goto InnerLoop > decfsz OUTER_COUNTER, F > goto OuterLoop > ENDM > ;****************************************************************** > Wait_100us MACRO > LOCAL InnerLoop > > movlw .100 > movwf INNER_COUNTER > InnerLoop > Stall > decfsz INNER_COUNTER, F > goto InnerLoop > ENDM > ;****************************************************************** > > list p=16F877 > > ; Include file, change directory if needed > include "p16f877.inc" > > #define ENABLE PORTE, 2 > #define RS PORTE, 1 > #define RW PORTE, 0 > > #define DATA_PORT PORTD > #define BUSY_FLAG PORTB, 6 > > OUTER_COUNTER equ 0x20 > INNER_COUNTER equ 0x21 > > > W_TEMP equ 0x70 > STATUS_TEMP equ 0x71 > PCLATH_TEMP equ 0x72 > > > ;//Reset Vector > Org 0x00 > clrf PCLATH ; ensure page bits are cleared > goto Initialize > > ;//Interrupt Vector > ORG 0x04 > MOVWF W_TEMP ;Copy W to TEMP register > SWAPF STATUS,W ;Swap status to be saved into W > CLRF STATUS ;bank 0, regardless of current bank, Clears > IRP,RP1,RP0 > MOVWF STATUS_TEMP ;Save status to bank zero STATUS_TEMP > register > MOVF PCLATH, W ;Only required if using pages 1, 2 and/or 3 > MOVWF PCLATH_TEMP ;Save PCLATH into W > CLRF PCLATH ;Page zero, regardless of current page > > ;Fill this in if you want interrupt vectoring > > banksel PCLATH_TEMP > MOVF PCLATH_TEMP, W ;Restore PCLATH > MOVWF PCLATH ;Move W into PCLATH > SWAPF STATUS_TEMP,W ;Swap STATUS_TEMP register into W > ;(sets bank to original state) > MOVWF STATUS ;Move W into STATUS register > SWAPF W_TEMP,F ;Swap W_TEMP > SWAPF W_TEMP,W ;Swap W_TEMP into W > retfie ; return from interrupt > > ;//Initialization > Initialize > clrf INTCON > clrf INTCON > CGIE > bcf INTCON, GIE > btfsc INTCON, GIE > goto CGIE > > ; //Declare port/pin definitions > banksel TRISA > movlw B'00000111' > movwf ADCON1 ; Port A is all digital > movlw B'00000000' > movwf TRISA ; Port A is OOOOOOOO > movlw B'01000000' > movwf TRISB ; Port B is OIOOOOOO > movlw B'10000001' > movwf TRISC ; Port C is IOOOOOOI > movlw B'00000000' > movwf TRISD ; Port D is OOOOOOOO > bcf TRISE, PSPMODE ; Turn off the parallel port > bcf TRISE, 0 ; Port E is -----OOO > bcf TRISE, 1 > bcf TRISE, 2 > > bsf OPTION_REG, 7 ;Turn off port B pullups > > banksel OUTER_COUNTER > bsf PORTB, 7 > > Wait_15ms > Wait_15ms > > bcf PORTB, 7 > > bcf RS > bcf RW > movlw b'00111000' > call StrobeData > > Wait_4.1ms > Wait_4.1ms > > bcf RS > bcf RW > movlw b'00111000' > call StrobeData > > Wait_4.1ms > Wait_4.1ms > > bcf RS > bcf RW > movlw b'00111000' > call StrobeData > > Wait_4.1ms > Wait_4.1ms > > call DisplayOFF_CursorOFF_BlinkOFF > Wait_15ms > Wait_4.1ms > > call DisplayON_CursorON_BlinkON > Wait_15ms > Wait_4.1ms > > call EntryModeSet > Wait_100us > > call ClearDisplay > Wait_15ms > Wait_4.1ms > > movlw b'01001000' ;H > call SendChar > movlw b'01100101' ;e > call SendChar > movlw b'01101100' ;l > call SendChar > movlw b'01101100' ;l > call SendChar > movlw b'01101111' ;o > call SendChar > movlw b'01010111' ;W > call SendChar > movlw b'01101111' ;o > call SendChar > movlw b'01110010' ;r > call SendChar > movlw b'01101100' ;l > call SendChar > movlw b'01100100' ;d > call SendChar > > Eternal > bcf PORTB, 0 > nop > bsf PORTB, 0 > goto Eternal > > ;----------- > StrobeData > nop > bsf ENABLE > nop > movwf DATA_PORT > nop > bcf ENABLE > return > ;----------- > EntryModeSet > btfsc BUSY_FLAG > goto EntryModeSet > bcf RS > bcf RW > movlw b'00000110' > call StrobeData > return > ;----------- > SendChar > btfsc BUSY_FLAG > goto SendChar > bsf RS > bcf RW > call StrobeData > return > ;----------- > ClearDisplay > btfsc BUSY_FLAG > goto ClearDisplay > bcf RS > bcf RW > movlw 0x01 > call StrobeData > return > ;----------- > HomeCursor > btfsc BUSY_FLAG > goto HomeCursor > bcf RS > bcf RW > movlw 0x02 > call StrobeData > return > ;----------- > DisplayOFF_CursorOFF_BlinkOFF > btfsc BUSY_FLAG > goto DisplayOFF_CursorOFF_BlinkOFF > bcf RS > bcf RW > movlw b'00001000' > call StrobeData > return > ;----------- > DisplayOFF_CursorOFF_BlinkON > btfsc BUSY_FLAG > goto DisplayOFF_CursorOFF_BlinkON > bcf RS > bcf RW > movlw b'00001001' > call StrobeData > return > ;----------- > DisplayOFF_CursorON_BlinkOFF > btfsc BUSY_FLAG > goto DisplayOFF_CursorON_BlinkOFF > bcf RS > bcf RW > movlw b'00001010' > call StrobeData > return > ;----------- > DisplayOFF_CursorON_BlinkON > btfsc BUSY_FLAG > goto DisplayOFF_CursorON_BlinkON > bcf RS > bcf RW > movlw b'00001011' > call StrobeData > return > ;----------- > DisplayON_CursorOFF_BlinkOFF > btfsc BUSY_FLAG > goto DisplayON_CursorOFF_BlinkOFF > bcf RS > bcf RW > movlw b'00001100' > call StrobeData > return > ;----------- > DisplayON_CursorOFF_BlinkON > btfsc BUSY_FLAG > goto DisplayON_CursorOFF_BlinkON > bcf RS > bcf RW > movlw b'00001101' > call StrobeData > return > ;----------- > DisplayON_CursorON_BlinkOFF > btfsc BUSY_FLAG > goto DisplayON_CursorON_BlinkOFF > bcf RS > bcf RW > movlw b'00001110' > call StrobeData > return > ;----------- > DisplayON_CursorON_BlinkON > btfsc BUSY_FLAG > goto DisplayON_CursorON_BlinkON > bcf RS > bcf RW > movlw b'00001111' > call StrobeData > return > ;----------- > END
"Will" <larkmore@aol.com> wrote in message
news:5faf6114.0402031434.38db8ce2@posting.google.com...

> with 10KOhm pulldown resistors to ground on ALL of the lines on the
I think one pin on the most PICs is open collector.
"Meindert Sprang" <mhsprang@NOcustomSPAMware.nl> wrote in message news:<40209d2c$1@news.nb.nu>...
> Your strobedata routine is too fast. Many LCD displays have a cycle time of > 500ns to 1000ns, where the E has to be kept high for 300 to 500ns or longer.
I'm not sure how you're arriving at that conclusion. The formula I used to determine how long the enable pin strobed was as follows: For a PIC 20 MHz external resonator/crystal -> 5MHz instruction rate (clock/4) -> 200 ns per instruction. Even assuming worst case that the PIC sets the pin high at the very end of the BSF instruction and low at the very beginning of the BCF instruction, there are 3 instructions between them. At 200ns each, that's at least 600ns and possibly 800ns if everything lines up nicely. I've also checked it with a scope probe and it looks more than long enough. In fact, I have verified that the PIC is in fact sending the signals I thinnk it should be at the right timing, based upon the datasheet that Optrex had on their website. In case anyone cares, that file was Dmcman_full.pdf and had 58 pages. It had no revisions listed on the second page so I guess it was revision 0.