PIC16F690 and HD44780 display

I'm trying to get a PIC16F690 (mplab's PICKIT 2) to send characters to a 2x20 HD44780-based display. I've cobbled bits from various sources into an assembly program, but all I get is a row of black boxes across the first line.

The circuit is wired as follows: micro display RC0-RC7 pin 7-14 (DB0-DB7) RB4 pin 4 (RS) RB5 pin 5 (R/W) RB6 pin 6 (E)

I've run the mplab simulator on the code below, and it seems to put out the signals in the right order, but obviously the display does not agree on 'right'! ;)

Can anyone point me to where the problem lies? Is it a timing issue?

Code follows.

;=========================== ;display text on a HD44780-based LCD ;from a PIC16F690.

;Preset variables, state and I/O settings ;============================================================ #include __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOD_OFF & _IESO_OFF & _FCMEN_OFF)

; register declarations PORT_A EQU 0x05 PORT_B EQU 0x06 PORT_C EQU 0x07 TRIS_A EQU 0x85 TRIS_B EQU 0x86 TRIS_C EQU 0x87

STATUS EQU 0x03 RP0 EQU 0x05 LCD_DATA EQU PORT_C ; LCD data lines interface - PORT C LCD_DATA_TRIS EQU TRIS_C ; PORTC tristate register LCD_CTRL EQU PORT_B ; LCD control lines interface - PORT B

; PORTB control bits LCD_E EQU 6 ; LCD Enable control line LCD_RW EQU 5 ; LCD Read/Write control line LCD_RS EQU 4 ; LCD Register-Select control line W EQU 0 ; MOVF designator for W register

cblock 0x20 LCD_TEMP ; LCD subroutines internal use DELAY ; Used in DELAYxxx routines X_DELAY ; Used in X_DELAYxxx routines endc

org 0x000 goto START

;Initiate LCD communications LCDINIT ; Busy-flag is not yet valid CLRF LCD_CTRL ; ALL PORTB output should output Low. ; power-up delay MOVLW 0x1E CALL X_DELAY500 ; 30 * 0.5mS = 15mS ; Busy Flag should be valid from here MOVLW 0x3C ; 8-bit-interface, 2-lines CALL LCDPUTCMD MOVLW 0x08 ; disp.on, curs.off, no-blink CALL LCDDMODE CALL LCDCLEAR MOVLW 0x010 ; curs. move CALL LCDDMODE MOVLW 0x02 ; cursor home CALL LCDDMODE RETURN

;test LCD busy line LCDBUSY BSF STATUS, RP0 ; Select Register page 1 MOVLW b'11111111' ; Set PORTC for input - read the BUSY line MOVWF LCD_DATA_TRIS BCF STATUS, RP0 ; Select Register page 0 BCF LCD_CTRL, LCD_RS ; Set LCD for command mode BSF LCD_CTRL, LCD_RW ; Setup to read busy flag BSF LCD_CTRL, LCD_E ; LCD E-line High MOVF LCD_DATA, W ; Read busy flag + DDram address BCF LCD_CTRL, LCD_E ; LCD E-line Low ANDLW 0x80 ; Check Busy flag, High = Busy BTFSS STATUS, Z GOTO LCDBUSY LCDNOTBUSY BCF LCD_CTRL, LCD_RW BSF STATUS, RP0 ; Select Register page 1 MOVLW 0x00 MOVWF LCD_DATA_TRIS ; Set PORTC for output BCF STATUS, RP0 ; Select Register page 0 RETURN

; clear LCD display LCDCLEAR MOVLW 0x001 CALL LCDPUTCMD RETURN

;returns LCD cursor to home position LCDHOME MOVLW 0x002 CALL LCDPUTCMD RETURN

;- Sets display control ;- Required entry mode must be set in W ; b0 : 0 = cursor blink off, 1 = cursor blink on (if b1 = 1) ; b1 : 0 = cursor off, 1 = cursor on ; b2 : 0 = display off, 1 = display on (display data remains in DD-RAM) ; b3-b7 : don't care

LCDDMODE ANDLW 0x007 ; Strip upper bits IORLW 0x008 ; Function set CALL LCDPUTCMD RETURN

;set character generator RAM address LCDSCGA ANDLW 0x03F ; Strip upper bits IORLW 0x040 ; Function set CALL LCDPUTCMD RETURN

;set display data RAM address LCDSDDA IORLW 0x080 ; Function set CALL LCDPUTCMD RETURN

;get address counter contents LCDGADDR BSF STATUS,RP0 ; Select Register page 1 MOVLW b'11111111' ; Set PORTB for input MOVWF LCD_DATA_TRIS BCF STATUS, RP0 ; Select Register page 0 BCF LCD_CTRL, LCD_RS ; Set LCD for command mode BSF LCD_CTRL, LCD_RW ; Setup to read busy flag BSF LCD_CTRL, LCD_E ; LCD E-line High MOVF LCD_DATA, W ; Read busy flag + RAM address BCF LCD_CTRL, LCD_E ; LCD E-line Low ANDLW 0x07F ; Strip upper bit BCF LCD_CTRL, LCD_RW BSF STATUS, RP0 ; Select Register page 1 MOVLW 0x000 MOVWF LCD_DATA_TRIS ; Set PORTB for output BCF STATUS, RP0 ; Select Register page 0 RETURN

;send character to LCD ;- Sends character to LCD ;- Required character must be in W

LCDPUTCHAR MOVWF LCD_TEMP ; Character to send is in W CALL LCDBUSY ; Wait for LCD to be ready BCF LCD_CTRL, LCD_RW ; Set LCD in read mode BSF LCD_CTRL, LCD_RS ; Set LCD in data mode MOVF LCD_TEMP, W MOVWF LCD_DATA ; Send data to LCD BSF LCD_CTRL, LCD_E ; LCD E-line High for one cycle BCF LCD_CTRL, LCD_E ; LCD E-line Low RETURN

;send command to LCD ;- Sends command to LCD ;- Required command must be in W

LCDPUTCMD MOVWF LCD_TEMP ; Command to send is in W CALL LCDBUSY ; Wait for LCD to be ready BCF LCD_CTRL, LCD_RW ; Set LCD in read mode BCF LCD_CTRL, LCD_RS ; Set LCD in command mode MOVF LCD_TEMP, W MOVWF LCD_DATA ; Send data to LCD BSF LCD_CTRL, LCD_E ; LCD E-line High for one cycle BCF LCD_CTRL, LCD_E ; LCD E-line Low RETURN

;delay loop ;- Used in LCDINIT subroutine ;- Required delay factor must be in W ; (Could be coded more efficient, but this approach gives more flexibility)

;*********************************** a 500uS delay @ 4MHz X-tal DELAY500 MOVLW D'165' ; +1 1 cycle MOVWF DELAY ; +2 1 cycle DELAY500_LOOP DECFSZ DELAY, F ; step1 1 cycle GOTO DELAY500_LOOP ; step2 2 cycles DELAY500_END RETURN ; +3 2 cycles

;*********************************** a delay of 'W' * 500mS X_DELAY500 MOVWF X_DELAY ; +1 1 cycle X_DELAY500_LOOP CALL DELAY500 ; step1 wait 500uSec DECFSZ X_DELAY, F ; step2 1 cycle GOTO X_DELAY500_LOOP ; step3 2 cycles X_DELAY500_END RETURN ; +2 2 cycles

START call LCDINIT

;set LCD display mode MOVLW 0x004 ;cursor off, blink off, display on CALL LCDDMODE

;Send special user characters to LCD

;Send LCD opening screen(s) ;line 1 MOVLW 'M' CALL LCDPUTCHAR ; MOVLW 'y' ; CALL LCDPUTCHAR ; MOVLW ' ' ; CALL LCDPUTCHAR ; MOVLW 't' ; CALL LCDPUTCHAR ; MOVLW 'e' ; CALL LCDPUTCHAR ; MOVLW 'x' ; CALL LCDPUTCHAR ; MOVLW 't' ; CALL LCDPUTCHAR ; MOVLW ' ' ; CALL LCDPUTCHAR ; MOVLW 'h' ; CALL LCDPUTCHAR ; MOVLW 'e' ; CALL LCDPUTCHAR ; MOVLW 'r' ; CALL LCDPUTCHAR ; MOVLW 'e' ; CALL LCDPUTCHAR ; MOVLW '!' ; CALL LCDPUTCHAR

;line 2 ; MOVLW 'S' ; CALL LCDPUTCHAR ; MOVLW 'u' ; CALL LCDPUTCHAR ; MOVLW 'c' ; CALL LCDPUTCHAR ; MOVLW 'c' ; CALL LCDPUTCHAR ; MOVLW 'e' ; CALL LCDPUTCHAR ; MOVLW 's' ; CALL LCDPUTCHAR ; MOVLW 's' ; CALL LCDPUTCHAR ; MOVLW '!' ; CALL LCDPUTCHAR

goto $ END

Reply to
Randy Day
Loading thread data ...

That means the lcd has not been initialised properly. You will get a blank screen when youve done it right.

Reply to
cbarn24050

Randy Day wrote: > I'm trying to get a PIC16F690 (mplab's PICKIT 2) > to send characters to a 2x20 HD44780-based display. > I've cobbled bits from various sources into an > assembly program, but all I get is a row of black > boxes across the first line. >

I'm not a PIC guy but I have used displays with Motorola processors in assembly language. The initialization is not difficult but must be done as described in the data sheet on the processor. IIRC it was send a start sequence, wait 20mS, send it again, wait 4.5mS, send again, etc. If followed, it works just fine. The automatic hardware init never worked for me but the 'programmed' init always did. I never used the busy flag for comm as I just 'spread out' the data through the main run loop. What's the point of waiting for a busy flag when there are other tasks to be done?

I found a website for the 44780 that includes PIC code examples. Here you go.

formatting link

GG

Reply to
stratus46

Hi,

Have a look at -

formatting link

and audit Vladimir's PIC simulator program. You should be able to fix your problem in the evaluation period as there are a lot of LCD statements in his PIC BASIC. You can mix-in assembler code so you can use most of what you've done. Whether you later purchase it or not is up to you.

BTW, there is also a Yahoo Group.

Cheers - Joe

Reply to
Joe McElvenney

Hi,

Sorry, his program doesn't support the 'F690 yet but that wouldn't stop you looking at and disassembling the LCD statements.

Cheers - Joe, with egg on face :-(

Reply to
Joe McElvenney

Some thoughts...

You've LCDCLEAR near the end of LCDINIT, but LCDCLEAR takes a quite long time to complete, during which nothing should be written to the LCD otherwise it messes up. Instead of LCDCLEAR, you can write spaces ' ' to the LCD lines, faster and IMO failsafer (at least in my experience).

Second, try a first 8-bit mode set without busy flag checking, wait over 4ms, then do a second 8-bit mode set.

Also, check that you haven't set LCD contrast wrong (wrong Vcc).

And add a test LED to a new I/O pin on the PIC, light the led if you ever reach the end of LCDINIT to see if the busy flag reading really works, and not that the LCD got stuck already before end of LCDINIT.

regards, - Jan

Reply to
Jan Wagner

I appreciate the replies I received, and I've tried the suggestions, but still no letters on screen.

One thing I've noticed is that the debugger in MPLAB is showing incorrect register values after particular instructions. I can't work out if these are being reflected in the .hex file or on-chip, but it would certainly cause comm problems.

=========================================== Here's one: bsf STATUS,RP0 ; select Register Page 1 movlw 0x3F movwf TRIS_A ; Make PortA all input clrf TRIS_C bcf STATUS,RP0 ; select Register Page 0

1) TRIS_A shows 0x0F after the MOVWF, but since A has RA0-RA5, shouldn't it show 0x3F?

2) TRISC has bits 6 and 7 high after the CLRF - why?

========================================== Here's another: ; Busy Flag should be valid from here MOVLW b'11111111' CALL LCDPUTCMD

LCDPUTCMD MOVWF LCD_TEMP ; Command to send is in W CALL LCDBUSY ; Wait for LCD to be ready BCF LCD_CTRL, LCD_RW ; Set LCD in read mode BCF LCD_CTRL, LCD_RS ; Set LCD in command mode MOVF LCD_TEMP, W MOVWF LCD_DATA ; Send data to LCD BSF LCD_CTRL, LCD_E ; LCD E-line High for two cycles NOP BCF LCD_CTRL, LCD_E ; LCD E-line Low RETURN

When the 'MOVWF LCD_DATA' command executes, the value in LCD_TEMP (0xFF) should be sent to the LCD_DATA port (PORTC in my case). What actually shows up at the port is 0x30; it drops bits 0-3, 6 and 7!

I noticed this behavior when writing to the wrong bits of a partial port, and that's expected, but on the '690, port C is the one full 8-bit port ... isn't it?

Or is there something about this chip I need to know?

Reply to
Randy Day

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.