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