Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

LCD Template Code For PIC16F84A (Help)

Status
Not open for further replies.

Peter_wadley

New Member
Hi,

I am trying to use Nigels code for driving an LCD with a PIC16F84a instead of a PIC16F628, which is used in his tutorial...

Since the 84a does not have as many (A) pins I wanted to make the connections like this..

RS (pin4 of LCD) goes to A0
RW (pin5 of LCD) goes to A1
E (pin6 of LCD) goes to A2

-----

and as for the 4 data bus bits..

D4 goes to RB0
D5 goes to RB1
D6 goes to RB2
D7 goes to RB3

Here is the code after I have tried modifed it:
PHP:
;LCD text demo - 4 bit mode

cblock	0x20		;start of general purpose registers
count			;used in looping routines
count1			;used in delay routine
counta			;used in delay routine
countb			;used in delay routine
tmp1			;temporary storage
tmp2
templcd			;temp store for 4 bit mode
templcd2	
endc

LCD_PORT Equ	05h
LCD_TRIS Equ	85h
LCD_RS    Equ	0x00 ;RS IS ON RA0
LCD_RW   Equ	0x01 ;RW IS ON RA1
LCD_E     Equ	0x02 ;E IS ON RA2
PORTA	 Equ       0x05
PORTB     Equ       0x06
STATUS   Equ       0x03
Z            Equ       0x02
PCL         Equ       0x02
org	0x0000

Initialise	
clrf	count
clrf	PORTA
clrf	PORTB


SetPorts	
bsf 	STATUS,5	;select bank 1
movlw	0x00		;make all pins outputs (for portA and portB)
movwf	LCD_TRIS
movwf    0x86
bcf 	STATUS,5	;select bank 0

call	Delay100		;wait for LCD to settle
call	LCD_Init		;setup LCD
clrf	count			;set counter register to zero

Message		
movf	count, w		;put counter value in W
call	Text			;get a character from the text table
xorlw	0x00			;is it a zero?
btfsc	STATUS, Z
goto	NextMessage
call	LCD_Char
call	Delay255
incf	count, f
goto	Message

NextMessage	
call	LCD_Line2		;move to 2nd row, first column
clrf	count			;set counter register to zero

Message2	
movf	count, w		;put counter value in W
call	Text2			;get a character from the text table
xorlw	0x00			;is it a zero?
btfsc	STATUS, Z
goto	EndMessage
call	LCD_Char
incf	count, f
goto	Message2

EndMessage	
		
Stop		goto	Stop			;endless loop

;Subroutines and text tables

;LCD routines

;Initialise LCD
LCD_Init	
movlw	0x20			;Set 4 bit mode
call	LCD_Cmd

movlw	0x28			;Set display shift
call	LCD_Cmd

movlw	0x06			;Set display character mode
call	LCD_Cmd

movlw	0x0d			;Set display on/off and cursor command
call	LCD_Cmd

call	LCD_Clr			;clear display

retlw	0x00

; command set routine
LCD_Cmd	
movwf	templcd
swapf	templcd,	w	;send upper nibble
andlw	0x0f			;clear upper 4 bits of W
movwf	LCD_PORT
movwf	PORTB              ;[COLOR="Red"]; Line added by PW - problem?[/COLOR]
bcf	LCD_PORT, LCD_RS	;RS line to 0
call	Pulse_e			;Pulse the E line high

movf	templcd,	w	;send lower nibble
andlw	0x0f			;clear upper 4 bits of W
movwf	LCD_PORT
movwf	PORTB              ;[COLOR="Red"]; Line added by PW - problem?[/COLOR]
bcf	LCD_PORT, LCD_RS	;RS line to 0
call	Pulse_e			;Pulse the E line high
call 	Delay5
retlw	0x00

LCD_CharD	addlw	0x30
LCD_Char	
movwf	templcd
swapf	templcd,	w	;send upper nibble
andlw	0x0f			;clear upper 4 bits of W
movwf	LCD_PORT
movwf	PORTB                        ;[COLOR="Red"]; Line added by PW - problem?[/COLOR]
bsf	LCD_PORT, LCD_RS	;RS line to 1
call	Pulse_e			;Pulse the E line high

movf	templcd,	w	;send lower nibble
andlw	0x0f			;clear upper 4 bits of W
movwf	LCD_PORT 
movwf	PORTB                         ;[COLOR="Red"]; Line added by PW - problem?[/COLOR]
bsf	LCD_PORT, LCD_RS	;RS line to 1
call	Pulse_e			;Pulse the E line high
call 	Delay5
retlw	0x00

LCD_Line1	
movlw	0x80			;move to 1st row, first column
call	LCD_Cmd
retlw	0x00

LCD_Line2
movlw	0xc0			;move to 2nd row, first column
call	LCD_Cmd
retlw	0x00

LCD_Line1W	
addlw	0x80			;move to 1st row, column W
call	LCD_Cmd
retlw	0x00

LCD_Line2W	
addlw	0xc0			;move to 2nd row, column W
call	LCD_Cmd
retlw	0x00

LCD_CurOn	
movlw	0x0d			;Set display on/off and cursor command
call	LCD_Cmd
retlw	0x00

LCD_CurOff	
movlw	0x0c			;Set display on/off and cursor command
call	LCD_Cmd
retlw	0x00

LCD_Clr		
movlw	0x01			;Clear display
call	LCD_Cmd
retlw	0x00

LCD_HEX		
movwf	tmp1
swapf	tmp1,	w
andlw	0x0f
call	HEX_Table
call	LCD_Char
movf	tmp1, w
andlw	0x0f
call	HEX_Table
call	LCD_Char
retlw	0x00

Delay255	movlw	0xff		;delay 255 mS
		goto	d0
Delay100	movlw	d'100'		;delay 100mS
		goto	d0
Delay50		movlw	d'50'		;delay 50mS
		goto	d0
Delay20		movlw	d'20'		;delay 20mS
		goto	d0
Delay5		movlw	0x05		;delay 5.000 ms (4 MHz clock)
d0		movwf	count1
d1		movlw	0xC7			;delay 1mS
		movwf	counta
		movlw	0x01
		movwf	countb
Delay_0
		decfsz	counta, f
		goto	$+2
		decfsz	countb, f
		goto	Delay_0

		decfsz	count1	,f
		goto	d1
		retlw	0x00

Pulse_e		bsf	LCD_PORT, LCD_E
		nop
		bcf	LCD_PORT, LCD_E
		retlw	0x00

;end of LCD routines

HEX_Table  	
addwf   PCL       , f
retlw   0x30
retlw   0x31
retlw   0x32
retlw   0x33
retlw   0x34
retlw   0x35
retlw   0x36
retlw   0x37
retlw   0x38
retlw   0x39
retlw   0x41
retlw   0x42
retlw   0x43
retlw   0x44
retlw   0x45
retlw   0x46


Text		addwf	PCL, f
retlw	'H'
retlw	'e'
retlw	'l'
retlw	'l'
retlw	'o'
retlw	0x00

Text2		addwf   PCL, f
retlw   'R'
retlw   'e'
retlw   'a'
retlw   'd'
retlw   'y'
retlw   '.'
retlw   '.'
retlw   '.'
retlw   0x00

end


Basically nothing happens when this is hooked up :eek:

I have a good understanding of the code but I must have goofed somewhere.. any ideas?

P.W

Edit: Im using MPLAB.
 
Last edited:
Does the LCD light up or show any evidence that it is receiving power supply? Which LCD are you using? Some time ago I spent weeks debugging the LCD, only to find out in the end that my LCD needs at least 7.5V supply and I was supplying 5V!
 
mdanh2002 said:
Does the LCD light up or show any evidence that it is receiving power supply? Which LCD are you using? Some time ago I spent weeks debugging the LCD, only to find out in the end that my LCD needs at least 7.5V supply and I was supplying 5V!

Hey Mdanh,

The LCD has no backlit so it doesnt light up

It is 2x16

15pins

HD44780A00 (s)
w/ HD44100H

I am giving it 5v

I have gotten the LCD to work with a very dumbed down piece of code from another website but I prefer code to be laided out in methods such as Nigels so that brings me here..

I dont see in the code where D11-D14 are called can someone point it out?

I think that is probably the problem I am facing.. most likely it is because I am using B ports now.. whereas Nigels tutorial uses just A ports?
 
Where you have added the movwf PORTB, you should have removed the existing instruction movwf LCD_PORT.

Mike.
 
Peter_wadley said:
I think that is probably the problem I am facing.. most likely it is because I am using B ports now.. whereas Nigels tutorial uses just A ports?

You're sending both data and control signals to LCD_PORT, that is PORTA (LCD_PORT Equ 05h). Replace LCD_PORT with PORTB if you're sending data and with PORTA if you're sending control signals.

General purpose registers start at 0x0C (cblock 0x0C).
 
Last edited:
Where you have added the movwf PORTB, you should have removed the existing instruction movwf LCD_PORT.

Mike.



eng1 said:
You're sending both data and control signals to LCD_PORT, that is PORTA (LCD_PORT Equ 05h). Replace LCD_PORT with PORTB if you're sending data and with PORTA if you're sending control signals.

General purpose registers start at 0x0C (cblock 0x0C).

I have taken out the four movwf LCD_PORT lines

And have changed the cblock register to 0x0c

So movwf PORTB should be sending the data WITH THE 4bits (D11-D14) such as the 2 words we are trying to send in this asm. correct?

Whereas the LCD_PORT is used to control things such as tell the LCD if we are sending data (RS)? if we are Reading or writing (RW) now about E.. when we pulse it high what is this telling the LCD? From what Ive read when we pulse we are preparing the LCD for a data transmission..

But isnt RS the same thing?

Thanks for your help
PW
 
On a side note, have you considered using a higher language such as PIC Basic to do the work for you?

**broken link removed**

Code:
Device = 16F877
XTAL = 4

LCD_DTPIN = PORTB.4
LCD_RSPIN = PORTB.2
LCD_ENPIN = PORTB.3
LCD_INTERFACE = 4
LCD_LINES = 2
LCD_TYPE = 0

ALL_DIGITAL = True

Delayms 150
Cls

Main:

    Print At 1,1, "Hello World"

    While 1=1                                ' Loop for ever

    Wend

**broken link removed**

All written in **broken link removed**
 
Personally I would suggest moving the LCD entirely to PortB, the tutorial code is designed to easily move between full ports, and just needs the equates changing at the beginning.
 
What speed is your pic running at? Nigel's routines are designed for 4MHz. If you are running any faster then you will have to change the delay routine.

Mike.
 
All written in Proton

Gramo,

Thanks for the suggestion..

Proton seems like a very user friendly and simple program great for people who are after the end result.. a perfectly and simple working LCD for their projects that is easy to debug..

Personally Id rather learn exactly what processes are going on between the controller and LCD.

What speed is your pic running at? Nigel's routines are designed for 4MHz. If you are running any faster then you will have to change the delay routine.

Mike.

Its running at 4mhz w/ xtal

Personally I would suggest moving the LCD entirely to PortB, the tutorial code is designed to easily move between full ports, and just needs the equates changing at the beginning.

Yes I think I am just going to arrange like so..

RB0 = RS
RB1 = RW
RB2 = E
RB3 = D11
RB4 = D12
RB5 = D13
RB6 = D14


The reason I didnt want to do this is because of us Pic Novices favourite thing.. pins which can only be used for input/ can't sink or source..

Which pins must I stay away from? I know RB4 is dangerous 5 too?

Is it fast to use 8bit mode rather then 4bit mode?

From what Ive gathered 4bit sends data out 2 steps where 8bit would send in 1.

PW
 
All of PortB is fine, it's RA4 you're thinking off that's open collector, which is fine as well - as my tutorial board includes a resistor for that very reason. 8bit mode is slightly faster, but it's not worth it for the extra pins you need - if you use my tutorial code that reads back from the LCD it's very fast anyway, far faster than you can read, or the LCD can actually update.
 
House0Fwax said:
What was the problem ?

The four occurences of these lines:
movwf LCD_PORT
movwf PORTB

caused the problem.

I added the line 'movwf PORTB' because the 4bits d11-d15 were moved to portB

I didnt take out the line 'LCD_PORT' because I figured that since, in Nigels orginal code, ALL of the LCD leads are attached to PORTA therefore this line wouldnt have any negative ramification on the program... guess not :p

I still dont understand why it would cause the program to stop working entirely.. but its working now so I cant complain!
 
Ok, the first problem is taken care of - now for the second on! :p

My attempts to drive the LCD with ONLY the B ports have proved unsuccessful..

I have the following wiring:

RB0 = RS
RB1 = RW
RB2 = E
RB3 = D11
RB4 = D12
RB5 = D13
RB6 = D14

All I see is at about the 3rd character space on the first line three horizontal lines and on the character space next to it the cursor is flashing!

Here is the code.. i have gone through it 100 times and it looks perfect to me!

PHP:
;LCD text demo - 4 bit mode 

cblock    0x0C  ;start of general purpose registers 
count           ;used in looping routines 
count1          ;used in delay routine 
counta          ;used in delay routine 
countb          ;used in delay routine 
tmp1            ;temporary storage 
tmp2 
templcd         ;temp store for 4 bit mode 
templcd2     
endc 

LCD_PORT Equ    0x06 
LCD_TRIS Equ    0x86
PORTA    Equ    0x05
A_TRIS   Equ    0x85
LCD_RS   Equ    0x00 ;RS IS ON RB0 
LCD_RW   Equ    0x01 ;RW IS ON RB1 
LCD_E    Equ    0x02 ;E IS ON RB2 
STATUS   Equ    0x03 
Z        Equ    0x02
PCL      Equ    0x02
org    0x0000 

Initialise     
clrf    count 
clrf    PORTA
clrf    LCD_PORT   ;PortB 


SetPorts     
bsf     STATUS,5      ;select bank 1 
movlw   0x00          ;make all pins outputs for LCD
movwf   LCD_TRIS  
bcf     STATUS,5      ;select bank 0 

call    Delay100      ;wait for LCD to settle 
call    LCD_Init      ;setup LCD 
clrf    count         ;set counter register to zero 

;STARTING OF OUTPUT

Message         
movf    count, w        ;put counter value in W 
call    Text            ;get a character from the text table 
xorlw   0x00            ;is it a zero? 
btfsc   STATUS, Z 
goto    EndMessage
call    LCD_Char 
call    Delay255 
incf    count, f 
goto    Message 

EndMessage
         
Stop  goto  Stop 


;LCD routines 

;Initialise LCD 
LCD_Init     
movlw    0x20            ;Set 4 bit mode 
call    LCD_Cmd 

movlw    0x28            ;Set display shift 
call    LCD_Cmd 

movlw    0x06            ;Set display character mode 
call    LCD_Cmd 

movlw    0x0d            ;Set display on/off and cursor command 
call    LCD_Cmd 

call    LCD_Clr           ;clear display 

retlw    0x00 

; command set routine 
LCD_Cmd     
movwf    templcd 
swapf    templcd,    w    ;send upper nibble 
andlw    0x0f             ;clear upper 4 bits of W 
movwf    LCD_PORT            
bcf      LCD_PORT, LCD_RS  ;RS line to 0 
call     Pulse_e           ;Pulse the E line high 

movf     templcd,    w     ;send lower nibble 
andlw    0x0f              ;clear upper 4 bits of W 
movwf    LCD_PORT              
bcf      LCD_PORT, LCD_RS   ;RS line to 0 
call     Pulse_e            ;Pulse the E line high 
call     Delay5 
retlw    0x00 

LCD_CharD    addlw    0x30 

LCD_Char     
movwf    templcd 
swapf    templcd,    w      ;send upper nibble 
andlw    0x0f               ;clear upper 4 bits of W  
movwf    LCD_PORT                      
bsf      LCD_PORT, LCD_RS   ;RS line to 1 
call     Pulse_e            ;Pulse the E line high 

movf     templcd,    w      ;send lower nibble 
andlw    0x0f               ;clear upper 4 bits of W 
movwf    LCD_PORT                      
bsf      LCD_PORT, LCD_RS   ;RS line to 1 
call     Pulse_e            ;Pulse the E line high 
call     Delay5 
retlw    0x00 

LCD_Line1     
movlw    0x80            ;move to 1st row, first column 
call    LCD_Cmd 
retlw    0x00 

LCD_Line2 
movlw    0xc0            ;move to 2nd row, first column 
call    LCD_Cmd 
retlw    0x00 

LCD_Line1W     
addlw    0x80            ;move to 1st row, column W 
call    LCD_Cmd 
retlw    0x00 

LCD_Line2W     
addlw    0xc0            ;move to 2nd row, column W 
call    LCD_Cmd 
retlw    0x00 

LCD_CurOn     
movlw    0x0d            ;Set display on/off and cursor command 
call    LCD_Cmd 
retlw    0x00 

LCD_CurOff     
movlw    0x0c            ;Set display on/off and cursor command 
call    LCD_Cmd 
retlw    0x00 

LCD_Clr         
movlw    0x01            ;Clear display 
call    LCD_Cmd 
retlw    0x00 

LCD_HEX         
movwf    tmp1 
swapf    tmp1,    w 
andlw    0x0f 
call     HEX_Table 
call     LCD_Char 
movf     tmp1, w 
andlw    0x0f 
call     HEX_Table 
call     LCD_Char 
retlw    0x00 

Delay255    movlw    0xff        ;delay 255 mS 
            goto    d0 
Delay100    movlw    d'100'      ;delay 100mS 
            goto    d0 
Delay50     movlw    d'50'       ;delay 50mS 
            goto    d0 
Delay20     movlw    d'20'       ;delay 20mS 
            goto    d0 
Delay5      movlw    0x05        ;delay 5.000 ms (4 MHz clock) 
d0          movwf    count1 
d1          movlw    0xC7        ;delay 1mS 
            movwf    counta 
            movlw    0x01 
            movwf    countb 
Delay_0 
           decfsz    counta, f 
           goto    $+2 
           decfsz    countb, f 
           goto    Delay_0 

           decfsz    count1    ,f 
           goto    d1 
           retlw    0x00 

Pulse_e    bsf    LCD_PORT, LCD_E 
           nop 
           bcf    LCD_PORT, LCD_E 
           retlw    0x00 

;end of LCD routines 

HEX_Table       
addwf   PCL       , f 
retlw   0x30 
retlw   0x31 
retlw   0x32 
retlw   0x33 
retlw   0x34 
retlw   0x35 
retlw   0x36 
retlw   0x37 
retlw   0x38 
retlw   0x39 
retlw   0x41 
retlw   0x42 
retlw   0x43 
retlw   0x44 
retlw   0x45 
retlw   0x46 


Text        addwf    PCL, f 
retlw    'H' 
retlw    'e' 
retlw    'l' 
retlw    'l' 
retlw    'o' 
retlw    0x00 

end

RB4 has a 10k resistor going to 5v also.

Anythoughts?... even if its a long shot Id like to hear it!
 
The code is specifically written to require the data lines to be on RB0-RB3. To make it work the way you have it wired, change the 4 occurrences of andlw 0x0f to andlw 0xf0 in LCD_Cmd and LCD_Chr.

Edit, this isn't going to work as the bits are still in the wrong place. I don't have time now but if your still stuck tomorrow I'll see what I can do.

Mike.
 
Last edited:
Whoops, just noticed you have the data lines on RB3-RB6. This is not going to work. You can either change them to be RB4-RB7 or you need to modify the code more.

Mike.
 
Is it just me? - you post tutorials on the net, with proven working code and hardware, in use by large numbers of people all over the world. Then someone connects it up differently, blindly bodges about with the code, and wonders why it doesn't work.

This is the LCD equates from the tutorial code, to move it to PortB all you need to do is alter PORTA to PORTB, and TRISA to TRISB - it's that simple. Connect it as shown in the tutorials, alter those two letters - and it works on PortB. Why connect it differently?, if you want it different then write your own code!.

Code:
LCD_PORT	Equ	PORTA
LCD_TRIS	Equ	TRISA
LCD_RS		Equ	0x04			;LCD handshake lines
LCD_RW		Equ	0x06
LCD_E		Equ	0x07
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top