I have been trying to interface an Optrex 16202 16x2 LCD module to a 10 Mhz PIC 16F84. It is not working. I know the LCD module works, as I connected it to my mac (with an ADB I/O), and it worked fine. This code is supposed to repeatedly send 'hello' to the screen, and outputs a roughly 2.4Khz square wave to PORTA,0. The 2.4Khz tone is produced (so I know the PIC is working), but the LCD does not. I know of the existance of AN587 and Norm Cramer's adaption thereof. I decided that i'd rather write my own code, so that if it didn't work, I would at least have some idea of what was wrong. (Lot of good that did! :). I did use one piece of Norm Cramer's code -- the delay loops, which I modified for 10Mhz, and trimmed down to save ~14 instructions. Any assistance would be greatly appreciated! - Keelan Lightfoot -- Problem code follows -- bank0 macro bcf STATUS,RP0 endm bank1 macro bsf STATUS,RP0 endm W_TEMP equ h'0C' ;Temporary W storage during interrupt ST_TEMP equ h'0D' ;Temporary STATUS storate during interrupt AReg equ h'E' ;GPR - DO NOT USE IN INTERRUPTS BReg equ h'F' ;GPR - DO NOT USE IN INTERRUPTS r1 equ h'10' r2 equ h'11' RS equ h'01' RW equ h'02' E equ h'03' org h'0000' goto MCUInit org h'0004' ; Interrupt routine goto IntModule MCUInit clrf STATUS clrf INTCON bank1 bsf OPTION,RBPU ; Turn off weak pullups on port B. clrf TRISA ; Port A all outputs clrf TRISB ; Upper half of Port B input, lower half output. bank0 clrf PORTA ; Port A low clrf PORTB ; Port B low bank1 IntOff bcf INTCON,GIE ; Turn off interrupts btfsc INTCON,GIE ; Interrupts off? goto IntOff ; No - try again. bcf OPTION,T0CS ; Timer mode bsf OPTION,PSA ; Give timer to TMR0 bsf INTCON,T0IE ; Enable TMR0 module bcf INTCON,RBIE ; Disable port B change interrupts bcf OPTION,PS0 ; 1 bcf OPTION,PS1 ; 0 bcf OPTION,PS2 ; 0 Prescaler set to 2 bsf INTCON,GIE goto MainModule ;******* End Basic Init Module ******* ;***************************************************** ;* Main * ;***************************************************** MainModule call LCDInit Looper movlw a'h' call LCDSCmmd movlw a'e' call LCDSCmmd movlw a'l' call LCDSCmmd movlw a'l' call LCDSCmmd movlw a'o' call LCDSCmmd goto Looper ;***************************************************** ;* Interrupt Module * ;***************************************************** IntModule bcf T0IF movwf W_TEMP swapf STATUS,W movwf ST_TEMP bank0 btfsc PORTA,RA0 goto poff bsf PORTA,RA0 goto IntEnd poff bcf PORTA,RA0 goto IntEnd IntEnd swapf ST_TEMP,W movwf STATUS swapf W_TEMP,F swapf W_TEMP,W retfie ;***************************************************** ;* Init LCD Module * ;***************************************************** LCDInit call Delay15000 bank0 movlw h'0F' ;Clear upper nibble of port B andwf PORTB ; movlw b'00110000' iorwf PORTB bcf PORTA,RS ;Command mode bcf PORTA,RW ;Write bsf PORTA,E ;Enable high nop ;Waste time nop nop bcf PORTA,E ;Enable low call Delay4100 bank0 bsf PORTA,E ;Enable high nop ;Waste time nop nop bcf PORTA,E ;Enable low call Delay100 bank0 bsf PORTA,E ;Enable high nop ;Waste time nop nop bcf PORTA,E ;Enable low bank0 movlw h'0F' ;Clear uper nibble of port B andwf PORTB ; movlw b'00100000' iorwf PORTB nop bsf PORTA,E ;Enable high nop ;Waste time nop nop bcf PORTA,E ;Enable low movlw b'00101000' call LCDSCmmd movlw b'00001111' call LCDSCmmd movlw b'00000001' call LCDSCmmd movlw b'00000010' call LCDSCmmd movlw b'00000110' call LCDSCmmd movlw b'10000000' call LCDSCmmd return ;***************************************************** ;* Send LCD Command * ;***************************************************** LCDSCmmd movwf AReg ;Save data call LCDWait bank0 movlw h'0F' ;Clear lower nibble of port B andwf PORTB ; movf AReg,w andlw h'F0' ;Send upper nibble first iorwf PORTB bcf PORTA,RS ;Command mode bcf PORTA,RW ;Write bsf PORTA,E ;Enable high nop ;Waste time nop nop bcf PORTA,E ;Enable low movlw h'0F' ;Clear lower nibble of port B andwf PORTB swapf AReg,w andlw h'F0' ;Send upper nibble first iorwf PORTB bsf PORTA,E ;Enable high nop ;Waste time nop nop bcf PORTA,E ;Enable low return ;***************************************************** ;* Send LCD Data * ;***************************************************** LCDSData movwf AReg ;Save data call LCDWait bank0 movlw h'0F' ;Clear lower nibble of port B andwf PORTB ; movf AReg,w andlw h'F0' ;Send upper nibble first iorwf PORTB bsf PORTA,RS ;Data mode bcf PORTA,RW ;Write bsf PORTA,E ;Enable high nop ;Waste time nop nop bcf PORTA,E ;Enable low movlw h'0F' ;Clear lower nibble of port B andwf PORTB swapf AReg,w andlw h'F0' ;Send upper nibble first iorwf PORTB bsf PORTA,E ;Enable high nop ;Waste time nop nop bcf PORTA,E ;Enable low return ;***************************************************** ;* Wait For LCD Module * ;***************************************************** LCDWait movlw h'F0' bank1 movwf TRISB ;Make LCD data lines inputs bank0 bcf PORTA,RS ;RS low - Read Busy flag & Address register bsf PORTA,RW ;Read from display nop bsf PORTA,E nop nop nop bcf PORTA,E movf PORTB,W movwf Breg nop bsf PORTA,E nop nop nop bcf PORTA,E ;Clock in second bytem ignore. btfsc Breg,7 goto LCDWait bcf PORTA,RW ;Return to default state bank1 clrf TRISB nop return ;***************************************************** ;* Delay Module * ;***************************************************** delay_loop nop decfsz r1,f goto delay_loop decfsz r2,f goto delay_loop return Delay4100 movlw h'FA' movwf r1 movlw h'A' movwf r2 goto delay_loop Delay100 movlw h'3E' movwf r1 movlw 1 movwf r2 goto delay_loop Delay15000 movlw h'88' movwf r1 movlw h'25' movwf r2 goto delay_loop