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.

Adapting LCD code for 16F876

Status
Not open for further replies.

bh00

New Member
Hi,

I'm trying to adapt the code I found here to run on a 16F876 at 20Mhz. I changed the BASE memory location to 0C. However it still doesn't run and I just get black squares on the top line of the LCD. Putting an LED on RB7 shows it flashing on and off when you first power the PIC up. Can anyone please tell me what else I'd need to change to get it working? I'm using PORTB and the basic m_lcd.asm file just trying to get the example to work!

Thanks
 
Hi,

Didn't see your code before but I tried the first lot of code from tutorial 3.1. changed the processor lines and the include line to the processor I'm using. also tried changing the config bit as well. Still couldn't get it to work. I'm starting to think its a dud LCD. I'll check my wiring again but can't see anything wrong - after all its not a very complex circuit - and it works fine with some other LED flasher examples I've used.

Cheers
 
Have you checked that the contrast is set to something sensible. You should be able to adjust it from fully dark to fully light.

Mike.
 
Like Pommie suggests, the contrast is fairly critical - even without the LCD initialised (or even connected to a PIC) as you turn the contrast up you will get a single row of black squares, turn it down and you get nothing. This is a reasonably good indication the LCD is working, when it's powered up, try turning the contrast slowly from end to end.
 
Last edited:
bh00 said:
Hi,

I'm trying to adapt the code I found here to run on a 16F876 at 20Mhz. I changed the BASE memory location to 0C. However it still doesn't run and I just get black squares on the top line of the LCD. Putting an LED on RB7 shows it flashing on and off when you first power the PIC up. Can anyone please tell me what else I'd need to change to get it working? I'm using PORTB and the basic m_lcd.asm file just trying to get the example to work!

Thanks

I would check the delay routines, since you've changed the oscillator frequency. They must meet the requirements or the LCD won't get initialised.
 
hi bh,

The asm prog you are converting was written to suit a 4mHz osc.

The LCD controller is a slow device and requires delays, especially during the initialising sequence.
Also the BUSY line [D7] is not used/tested, so delays are required in writing the control commands to the LCD controller.

One of the 'slower' control lines is the E-nable.[min cycle time 1uSEc]

As you are using 20mHz xtal, I would suggest a starting point in the delays would be to increase them by a factor of 5.

Also pad out the 'E-nb' low period with about 5 NOP's.

From the start of the program have a delay of about 50 mSec before you start the LCD initialise seq

This should give you a working LCD.

I assume you have followed prev posts re the contrast pot.

Once the LCD is working, you can reduce the delays in increments until you get the optimum speed.

If you do optimise it for a particular LCD, if possible try with another LCD of the same type, the 'speeds' do vary.


EricG
 
Nigel Goodwin said:
You might try my tutorial LCD code?, it's tested and working on 14 bit series PIC's from 4MHz to 20MHz.
Hi Guys, I'll retry the original code with Eric's advice.

I've tried Nigels code as well. No success with that either. Attached is the file as I've written it to the chip. I've tried both a 20MHz and a 4MHz crystal just to see if it works on either.

Contrast is setup with a 20k:eek:hm: pot to let me adjust it. I can vary it between a completely blank screen to a top row of dark squares. I've tried playing with it and it doesn't magically start working when I change the contrast :(

I'll try and post a picture of my board later.

Cheers
 

Attachments

  • nigelscode.txt
    5 KB · Views: 353
hi bh,

Post the code you are using and I'll try it on my simulator for you.

Eric
 
Hi,

The current code I'm trying to get working is Nigels code as attached in the previous post. I know the PIC and the programmer works, as a basic LED flash routine works, and I've used the LCD with PICAXE circuits successfully before so I'm just guessing its some sort of code issue.

I've got the data lines D4-D7 connected to RB0-3 with D4 connected to RB0, D5 to RB1, etc... The control lines are connected with Enable (pin 6) to RB5, RW (pin 5) to RB6 and RS (pin 4) to RB7. Everything seems to have power fine. Both the 4Mhz crystal and the 20Mhz one has the same thing - nothing initialises. I've tried some variations on Nigel's code, eg changing the delays which doesn't seem to have an affect. I'm sure I've got the start of his code setup right (the PORTB, LCD_RS, LCD_RW values, etc). So I'm a little stumped!

Thanks
 
hi bh,

Just run Nigel's code thru simulator, runs as expected, no problems.
[ignore the 4 line display on my pic, just using prev setting]

Check that RB6/RW is really low when you have programmed the PIC,
it should be, BUT.

Its not used in the prog, it should be tied to 0v.

What type of LCD controller is it?

Eric
 
Last edited:
Hi All,

Not quite sure why but it's suddenly started working. Just flashed the chip with the following code which does a perfect 16 bit counter!

Thanks guys for all your help so far!

Code:
;LCD text demo - 4 bit mode
;Nigel Goodwin 2002

	LIST	p=16F876		;tell assembler what chip we are using
	include "P16F876.inc"		;include the defaults for the chip
	ERRORLEVEL	0,	-302	;suppress bank selection messages
	__config 0x3D1A			;sets the configuration settings (oscillator type etc.)




		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

        		NumL			;Binary inputs for decimal convert routine
	        	NumH	

        		TenK			;Decimal outputs from convert routine
	        	Thou	
        		Hund	
	        	Tens	
        		Ones	
		endc

LCD_PORT	Equ	PORTB
LCD_TRIS	Equ	TRISB
LCD_RS		Equ	0x07			;LCD handshake lines
LCD_RW		Equ	0x06
LCD_E		Equ	0x05

		org	0x0000
		goto	Start

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	'1'
		retlw	'6'
		retlw	' '
		retlw	'B'
		retlw	'i'
		retlw	't'
		retlw	' '
		retlw	'C'
		retlw	'o'
		retlw	'u'
		retlw	'n'
		retlw	't'
		retlw	'e'
		retlw	'r'
		retlw	'.'
		retlw	0x00

Start	;	movlw	0x07
	;	movwf	CMCON			;turn comparators off (make it like a 16F84)

Initialise	clrf	count
		clrf	PORTA
		clrf	PORTB
		clrf	NumL
		clrf	NumH



SetPorts	bsf 	STATUS,		RP0	;select bank 1
		movlw	0x00			;make all pins outputs
		movwf	LCD_TRIS
		movwf	TRISB
		bcf 	STATUS,		RP0	;select bank 0

		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
		incf	count, f
		goto	Message

NextMessage	movlw	d'2'
		call	LCD_Line2W		;move to 2nd row, third column
	
		call	Convert			;convert to decimal
		movf	TenK,	w		;display decimal characters
		call	LCD_CharD		;using LCD_CharD to convert to ASCII
		movf	Thou,	w
		call	LCD_CharD
		movf	Hund,	w
		call	LCD_CharD		
		movf	Tens,	w
		call	LCD_CharD
		movf	Ones,	w
		call	LCD_CharD
		movlw	' '			;display a 'space'
		call	LCD_Char
		movf	NumH,	w		;and counter in hexadecimal
		call	LCD_HEX
		movf	NumL,	w
		call	LCD_HEX
		incfsz	NumL, 	f
		goto	Next
		incf	NumH,	f
Next		call	Delay255		;wait so you can see the digits change
		goto	NextMessage


;Subroutines and text tables

;LCD routines

;Initialise LCD
LCD_Init	call 	LCD_Busy		;wait for LCD to settle

		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	0x0c			;Set display on/off and cursor command
		call	LCD_Cmd			;Set cursor off

		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 	LCD_Busy
		retlw	0x00

LCD_CharD	addlw	0x30			;add 0x30 to convert to ASCII
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 	LCD_Busy
		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

LCD_Busy
		bsf	STATUS,	RP0		;set bank 1
		movlw	0x0f			;set Port for input
		movwf	LCD_TRIS
		bcf	STATUS,	RP0		;set bank 0
		bcf	LCD_PORT, LCD_RS	;set LCD for command mode
		bsf	LCD_PORT, LCD_RW	;setup to read busy flag
		bsf	LCD_PORT, LCD_E
		swapf	LCD_PORT, w		;read upper nibble (busy flag)
		bcf	LCD_PORT, LCD_E		
		movwf	templcd2 
		bsf	LCD_PORT, LCD_E		;dummy read of lower nibble
		bcf	LCD_PORT, LCD_E
		btfsc	templcd2, 7		;check busy flag, high = busy
		goto	LCD_Busy		;if busy check again
		bcf	LCD_PORT, LCD_RW
		bsf	STATUS,	RP0		;set bank 1
		movlw	0x00			;set Port for output
		movwf	LCD_TRIS
		bcf	STATUS,	RP0		;set bank 0
		return

;end of LCD routines



;This routine downloaded from http://www.piclist.com
Convert:                        ; Takes number in NumH:NumL
                                ; Returns decimal in
                                ; TenK:Thou:Hund:Tens:Ones
        swapf   NumH, w
	iorlw	B'11110000'
        movwf   Thou
        addwf   Thou,f
        addlw   0XE2
        movwf   Hund
        addlw   0X32
        movwf   Ones

        movf    NumH,w
        andlw   0X0F
        addwf   Hund,f
        addwf   Hund,f
        addwf   Ones,f
        addlw   0XE9
        movwf   Tens
        addwf   Tens,f
        addwf   Tens,f

        swapf   NumL,w
        andlw   0X0F
        addwf   Tens,f
        addwf   Ones,f

        rlf     Tens,f
        rlf     Ones,f
        comf    Ones,f
        rlf     Ones,f

        movf    NumL,w
        andlw   0X0F
        addwf   Ones,f
        rlf     Thou,f

        movlw   0X07
        movwf   TenK

                    ; At this point, the original number is
                    ; equal to
                    ; TenK*10000+Thou*1000+Hund*100+Tens*10+Ones
                    ; if those entities are regarded as two's
                    ; complement binary.  To be precise, all of
                    ; them are negative except TenK.  Now the number
                    ; needs to be normalized, but this can all be
                    ; done with simple byte arithmetic.

        movlw   0X0A                             ; Ten
Lb1:
        addwf   Ones,f
        decf    Tens,f
        btfss   3,0
        goto   Lb1
Lb2:
        addwf   Tens,f
        decf    Hund,f
        btfss   3,0
        goto   Lb2
Lb3:
        addwf   Hund,f
        decf    Thou,f
        btfss   3,0
        goto   Lb3
Lb4:
        addwf   Thou,f
        decf    TenK,f
        btfss   3,0
        goto   Lb4

        retlw	0x00


		end
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top