W
Will
Guest
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
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