PDA

View Full Version : help with 4 x 20 LCD



keithv
- 22nd February 2018, 19:30
I'm trying to use a 4x20 LCD with a 16F887 but without any luck. I have the LAB-X1 with a 2x20 LCD. The 4x20 module has the same 16 pins as the 2x20, so I'm assuming it can be connected to the PIC the same what it is connected on the LAB-X1. I'm not using the external crystal though. There was no define statement in the sample code that sets the number of lines, so I added it.


' Name : LCDX.pbp'
Compiler : PICBASIC PRO
Compiler 2.60' Assembler : PM or MPASM'
Target PIC : 40-pin 16F887'
Hardware : LAB-X1 Experimenter Board'
Oscillator : 4MHz external crystal'
Keywords : LCDOUT'
Description : PICBASIC PRO program to display "Hello World" on' LAB-X1 LCD.'' Define LCD registers and bits

Define LCD_DREG PORTD
Define LCD_DBIT 4
Define LCD_RSREG PORTE
Define LCD_RSBIT 0
Define LCD_EREG PORTE
Define LCD_EBIT 1
Define LCD_LINES 4 'code works in LAB-X1 without this line
ANSEL = %00000000 ' Make AN0-AN7 digital
ANSELH= %00000000 ' Make AN8-AN13 digital
Low PORTE.2 ' LCD R/W line low (W)
Pause 100 ' Wait for LCD to start up

mainloop:
Lcdout $fe, 1 ' Clear screen
Pause 500 ' Wait .5 second
Lcdout "Hello" ' Display "Hello"
Pause 500 ' Wait .5 second
Lcdout $fe, $c0, "World" ' Move to line 2 and display "World"
Pause 500 ' Wait .5 second
Goto mainloop ' Do it forever
End

keithv
- 22nd February 2018, 19:31
sorry. I'm editing the format now.

mpgmike
- 22nd February 2018, 20:47
Each line has its own address in the HD44780.

Line 1 = $80
Line 2 = $C0
Line 3 = $90
Line 4 = $D0

You would need RS = 0 to send a command and send your line address, then RS = 1 and send the string.

keithv
- 22nd February 2018, 22:54
Each line has its own address in the HD44780.

Line 1 = $80
Line 2 = $C0
Line 3 = $90
Line 4 = $D0

You would need RS = 0 to send a command and send your line address, then RS = 1 and send the string.

I'm sorry. I'm not following. I think I understand how to move the cursor around. But what is RS? The register select bit? I'm not getting it to display anything even on lines 1 and 2. What would you do differently here to get it to display "hello" on line 1 and then "world" on line 2?

Lcdout $fe, 1 ' Clear screen
Pause 500 ' Wait .5 second
Lcdout "Hello" ' Display "Hello"
Pause 500 ' Wait .5 second
Lcdout $fe, $c0, "World" ' Move to line 2 and display "World"
Pause 500 ' Wait .5 second

Scampy
- 22nd February 2018, 23:02
The following code works for me with a 4 x 20 LCD



;----[LCD ]---------------------------------------------------------------------

DEFINE LCD_DREG PORTB ' LCD Data port
DEFINE LCD_DBIT 0 ' starting Data bit (0 or 4)
DEFINE LCD_EREG PORTB ' LCD Enable port
DEFINE LCD_EBIT 5 ' Enable bit (on EasyPIC 5 LCD)
DEFINE LCD_RSREG PORTB ' LCD Register Select port
DEFINE LCD_RSBIT 4 ' Register Select bit (on EasyPIC 5 LCD)
DEFINE LCD_BITS 4 ' LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 4 ' number of lines on LCD
DEFINE LCD_COMMANDUS 2000 ' Command delay time in us
DEFINE LCD_DATAUS 50 ' Data delay time in us

LCDOUT $FE,1:FLAGS=0:PAUSE 250:LCDOUT $FE,1:PAUSE 250 ' Initialize LCD


Obviously change the port/pin assignments to match your hardware

To inform the LCD which line to start displaying text on use;


$fe,$80,
$fe,$C0,
$fe,$94,
$fe,$d4,

Scampy
- 22nd February 2018, 23:07
I'm sorry. I'm not following. I think I understand how to move the cursor around. But what is RS? The register select bit? I'm not getting it to display anything even on lines 1 and 2. What would you do differently here to get it to display "hello" on line 1 and then "world" on line 2?

Lcdout $fe, 1 ' Clear screen
Pause 500 ' Wait .5 second
Lcdout "Hello" ' Display "Hello"
Pause 500 ' Wait .5 second
Lcdout $fe, $c0, "World" ' Move to line 2 and display "World"
Pause 500 ' Wait .5 second


You forgot to designate the line one position



LCDOUT $FE,1
lcdout $FE,$80,"Hello"
pause 500
lcdout $FE,$C0,"World"
pause 500

richard
- 22nd February 2018, 23:20
LCDOUT $FE,1
lcdout $FE,$80,"Hello"

the $FE,$80 is tolally unnecessary , the $FE,1 not only clears the screen it homes the cursor to
line 1 pos 0 too


LCDOUT $FE,1:FLAGS=0:PAUSE 250:LCDOUT $FE,1:PAUSE 250 ' Initialize LCD
is a waste of code space and indicates that the power on lcd wait may be too short



Pause xxx ' Wait for LCD to start up
LCDOUT $FE,1

is adequate , I have had displays that need the pause xxx to be as long as 500mS


its also possible that the default config settings in your pic16f887.inc file don't match your setup

can you blink a led at defined rate correctly ?

keithv
- 22nd February 2018, 23:41
its also possible that the default config settings in your pic16f887.inc file don't match your setup

can you blink a led at defined rate correctly ?

I added the address for good measure. No luck. I increased the start up wait time. No luck still. I added a blinking LED and that works - on for half a second, off for 1 second. Stuff highlighted in RED is what was added/changed.




TRISB = %00000000
pause 500
mainloop:
Lcdout $fe, 1 ' Clear screen
Pause 500 ' Wait .5 second
Lcdout $fe, $80, "Hello" ' Display "Hello"
PORTB.7 = 1 'LED on
Pause 500 ' Wait .5 second
Lcdout $fe, $c0, "World" ' Move to line 2 and display "World"
PORTB.7 = 0 'LED off
Pause 500 ' Wait .5 second
Goto mainloop ' Do it forever
End

richard
- 22nd February 2018, 23:46
wiring ?
contrast setting ?
unused data pins on lcd are grounded not left floating ?

keithv
- 22nd February 2018, 23:53
Just FYI, this is the LCD Module (https://www.ebay.com/itm/2004-204-20x4-Character-LCD-Display-Module-HD44780-Controller-Blue-Blacklight/121848267903?ssPageName=STRK%3AMEBIDX%3AIT&_trksid=p2057872.m2749.l2649) I'm using.

I've got it connected just like the LAB-1X:

VSS > ground
VDD > +5v
V0 > ground
RS > RE0
R/W > RE2
E > RE1
D0 > RD4
D1 > RD5
D2 > RD6
D3 > RD7
D4 > RD0
D5 > RD1
D6 > RD2
D7 > RD3
A > +5V
K > ground

richard
- 23rd February 2018, 00:03
seems a strange way to connect it
I would
D0 > gnd
D1 > gnd
D2 > gnd
D3 > gnd

plus r/w can be grounded
it you connect it to e2 then that needs to be defined for correct operation
Define LCD_DREG PORTD
Define LCD_DBIT 4
Define LCD_RSREG PORTE
Define LCD_RSBIT 0
Define LCD_EREG PORTE
Define LCD_EBIT 1
Define LCD_LINES 4 'code works in LAB-X1 without this line
DEFINE LCD_RWREG PORTE 'LCDOUT/IN read/write port
DEFINE LCD_RWBIT 2 'LCDOUT/IN read/write bit

and vo is connected to wiper of contrast pot (10k) that's connected between vcc-gnd

with vo grounded thats max contrast and display shows all black squares

keithv
- 23rd February 2018, 18:18
CLEAR
DEFINE LOADER_USED 1
DEFINE OSC4
DEFINE LCD_DREG PORTD
DEFINE LCD_DBIT 4
DEFINE LCD_RSREG PORTE
DEFINE LCD_RSBIT 0
DEFINE LCD_EREG PORTE
DEFINE LCD_EBIT 1
DEFINE LCD_RWREG PORTE
DEFINE LCD_RWBIT 2
DEFINE LCD_BITS 8
DEFINE LCD_LINES 4
DEFINE LCD_COMMANDUS 2000
DEFINE LCD_DATAUS 50

ANSEL = %00000000
TRISD = %00000000
TRISE = %00000000
PAUSE 500

Mainloop:
LCDOUT $fe, 1
pause 500
LCDOUT $fe, $80, "hello"
pause 500
LCDOUT $fe, $C0, "world"
pause 500
goto mainloop
end


This is the older example code that is in the LAB-X1 Tutorial and Reference book. With the addition of the contrast pot on V0, I now at least get it to display something. Although it's not displaying English characters or anything that I recognize for that matter.....it looks more like Klingon or Greek. And it's not displaying in the correct locations. It only displays 1 string of gibberish over and over again (I'd assume it would display different 2 if it was incorrectly translating 2 different strings). It displays this first string of gibberish at the beginning of line 1 as expected. But instead of moving to the beginning of line 2, it repeats the string at the end of the first. Each time it blinks, it repeats the string at the end of the previous string. But instead of wrapping around to the second line, it jumps to the 3rd line. Once it fills the 3rd line, it stops adding new strings and just flashes forever without ever clearing the display.

I tried removing D0~3 and D4~7. It only works with all 8 data busses connected.

keithv
- 23rd February 2018, 18:50
Maybe I have an I2C version (https://www.crystalfontz.com/product/cfah2004actmiew-20x4-i2c-character-lcd?kw=&origin=pla&gclid=EAIaIQobChMI2qKrsci62QIVilt-Ch0ktApzEAYYAyABEgKz6_D_BwE)? I've contacted the seller to see if I can get a datasheet.

richard
- 23rd February 2018, 21:03
.....it looks more like Klingon or Greek.

because you still have it wrong





DEFINE LCD_DREG PORTD

DEFINE LCD_DBIT 4 from manual ' Set starting Data bit (0 or 4) if 4-bit bus



DEFINE LCD_RSREG PORTE
DEFINE LCD_RSBIT 0
DEFINE LCD_EREG PORTE
DEFINE LCD_EBIT 1
DEFINE LCD_RWREG PORTE
DEFINE LCD_RWBIT 2


DEFINE LCD_BITS 8 from manual Set LCD bus size (4 or 8 bits)

The LCD may be connected to the PIC MCU using either a 4-bit bus or an 8-bit
bus. If an 8-bit bus is used, all 8 bits must be on one port. If a 4-bit bus is used,
the top 4 LCD data bits must be connected to either the bottom 4 or top 4 bits of
one port.




DEFINE LCD_LINES 4
DEFINE LCD_COMMANDUS 2000
DEFINE LCD_DATAUS 50


the one thing not mentioned in the manual is to ground the unused pins d0-d3 if using a 4 bit bus.
it can be difficult to init disp under some conditions if this is not done.

if you use 8bit bus then the pins should be connected sequentially port.0 -> d0 ..... port.7 -> d7

keithv
- 26th February 2018, 23:12
because you still have it wrong






the one thing not mentioned in the manual is to ground the unused pins d0-d3 if using a 4 bit bus.
it can be difficult to init disp under some conditions if this is not done.

if you use 8bit bus then the pins should be connected sequentially port.0 -> d0 ..... port.7 -> d7

Yes! That fixed it. And I actually understand what's going on now. Thanks so much, Richard and everyone!