PDA

View Full Version : serial LCD 1602 Backpack using PIC16F690 for Hitach HD44780



jackberg1
- 28th September 2025, 00:27
Hello everyone,

I'de like to share this project, may come handy for hobbyist working around LCD display.

My search for a serial LCD that can receive serial data from 300 to 19200 baud on the internet was not successful
then I roll-up my sleeves and build this LCD backpack that use a common Hitachi HD44780 display. (still popular today)

My project was simple with parts already on hand like PIC16F690, NPN smd transistor, potentiometer, resistor. and PBP3 Basic code.

So enjoy,


'''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''' Name : 16F690 LCD BACKPACK
' Date : Sep 27-2025
' Note : 393 words used of 2048
' Notes : Serin2 Baud Rate 300 ~ 19200 Intrc_OSC 8Mhz
'''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''
#CONFIG
cfg = _INTRC_OSC_NOCLKOUT
cfg&= _WDT_OFF
cfg&= _PWRTE_OFF
cfg&= _MCLRE_OFF
cfg&= _CP_OFF
cfg&= _CPD_OFF
cfg&= _BOD_OFF
cfg&= _IESO_OFF
cfg&= _FCMEN_OFF
__CONFIG cfg
#ENDCONFIG
DEFINE OSC 8 ' Core is running at EXT-CRYSTAL 16MHz PBP 33,217
ANSEL = 0 ' Set all pins digital
ANSELH = 0 ' Set all pins digital
OPTION_REG.7 = 0 ' PORTA/PORTB pull-ups are enabled by individual port latch values
CM1CON0 = 0 ' Analog comparators off


En var Portb.4 : low en
RS var Portb.6 : low rs
B1 var byte : b1 = 0


' 300=3313 600=1646 1200=813 2400=396 4800=188 9600=84 19200=32
BaudR var byte : baudr = 32


TRISA = 0 : TRISB = 100000 : TRISC = 0
PORTA = 0 : PORTB = 0 : PORTC = 0
OSCCON = $70


high Porta.0 ' Backlight ON


gosub LCDinit ' initialise LCD


'Serin2
main:
serin2 Portb.5,baudr,3,main,[b1]


if b1 < 253 then ' Characters
PORTC = b1
HIGH EN : PAUSEus 5 : LOW EN
goto main
elseif b1 = 254 then ' LCD Command
low RS
serin2 Portb.5,baudr,3,main,[b1]
PORTC = b1 ' output the data
HIGH EN : PAUSEus 5 : LOW EN
high RS ' character mode
goto main
elseif b1 = 255 then
low rs ' LCD Command


serin2 Portb.5,baudr,3,main,[b1]
if b1 = 0 then
low porta.0 ' Back Light OFF
high rs
endif
if b1 = 8 then
high porta.0 ' Back Light ON
high rs
endif
goto main ' loop back to top
ENDIF


LCDINIT: ' Standard LCD Module Initialisation
PORTC = 000001 ' 2, Clear Display
HIGH EN : PAUSEus 300 : LOW EN ' Send data
pause 4
PORTC = 000010 ' 4, Return Home
HIGH EN : PAUSEus 300 : LOW EN
pause 4
PORTC = 111000 ' 1, 8 bit, 2 line, 5x8 Characters
HIGH EN : PAUSEus 300 : LOW EN
pause 4
' PORTC = 001100 ' Display on, no cursor, no blink
PORTC = 001110 ' 1, Display on, cursor, blink
HIGH EN : PAUSEus 300 : LOW EN
pause 4
PORTC = 000110 ' 1, Entry mode
HIGH EN : PAUSEus 300 : LOW EN
pause 4
high rs ' character mode
RETURN


9989


9990

jackberg1
- 28th September 2025, 02:19
Here's an code update

on the LCD backpack code the line

BaudR var byte should be replace with: BaudR var Word

and here's the serial sender code updated as well. (use an 12F683)



'''''''''''''''''''''''''''''''''''''''''''''''''' ''''''''''''''''''''''''
'Project : 12F683 Serial LCD Test 300 ~ 19200 baud for 16F690 Lcd Backpack
'Date : Sep 27-2025
'Notes : 285 words used of 2048
'Notes : Serout2 300 ~ 19200 Intrc_OSC 8Mhz
'300=3313 600=1646 1200=813 2400=396 4800=188 9600=84 19200=32
'''''''''''''''''''''''''''''''''''''''''''''''''' ''''''''''''''''''''''''
#CONFIG
__config _INTOSCIO & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _BOD_OFF & _CP_OFF & _CPD_OFF
#ENDCONFIG
DEFINE OSC 8 ' Core is running at EXT-CRYSTAL 16MHz PBP 33,217
LCD Var GPIO.0 ' Serial out
ANSEL = 0 ' Set all digital PULLUP Resistor page:10
TRISIO = %00000000 ' INPUT=1 OUTPUT = 0
OSCCON = $70 ' $70=8Mhz $60=4mhz $50=2MHZ $40=1MHZ $30=500KHZ


BaudR var word
baudR = 32 ' 300=3313 600=1646 1200=813 2400=396 4800=188 9600=84 19200=32
Pace var byte ' for serout2
pace = 0


SEROUT2 lcd,baudR,pace,[ 254, 1] ' Clear LCD
pause 40


DO
' LCD 1602
sEROUT2 lcd,baudR,pace,[254,128,"ABCDEFGHIJKLMNOP"] ' Line 1 16 Char.
SEROUT2 lcd,baudR,pace,[254,192,"0123456789-=,./>"] ' Line 2 16 Char.


' LCD 2004
'SEROUT2 lcd,BaudR,pace,[254,128,"ABCDEFGHIJkLMNOPQRST"] ' Line 1 20 Char.
'SEROUT2 lcd,BaudR,pace,[254,192,"0123456789-=,./;!@#$"] ' Line 2 20 Char.
'SEROUT2 lcd,BaudR,pace,[254,148,"ABCDEFGHIJkLMNOPQRST"] ' Line 3 20 Char.
'SEROUT2 lcd,BaudR,pace,[254,212,"0123456789-=,./;!@#$"] ' Line 4 20 Char.


PAUSE 2000
SEROUT2 lcd,baudR,pace,[ 255, 0] ' Back Light OFF
PAUSE 200
SEROUT2 lcd,baudR,pace,[ 255, 8] ' Back Light ON
PAUSE 2000

SEROUT2 lcd,baudR,pace,[ 254, 1] ' Clear LCD
pause 1000
LOOP
END

jackberg1
- 28th September 2025, 19:25
final code update in "16F690 LCD BACKPACK"
the low rs and high rs lines are not needed, since it control PortA.0 and not the HD44780 chip.




elseif b1 = 255 then
' low rs ' LCD Command
serin2 Portb.5,baudr,3,main,[b1]
if b1 = 0 then
low porta.0 ' Back Light OFF
' high rs
endif
if b1 = 8 then
high porta.0 ' Back Light ON
' high rs
endif

Ioannis
- 28th September 2025, 22:08
Thanks for posting your project.

But why not use the Hardware USART instead of the Software one?

Ioannis

jackberg1
- 29th September 2025, 00:30
Hello Ioannis,

good question,

when I design the PCB I used the PortB.5 with a 20Mhz crystal with bigger pcb foot print 46x17mm
then I decided to lower the parts count and the PCB foot print to a bare minimum (41 x 17mm)
Also theses HD44780 are still in use by many hobbyist around the world, I guess, and the baud rate I was looking is plenty for this kind of display.

thank's for asking.

9991

jackberg1
- 29th September 2025, 12:01
Hello,

you're right
my assumption was that software or hardware control serial communication are the same
and one way or another I'll get the same result.

if I may ask in this project what the benefit of hardware over software serial control.

thank's again.

Ioannis
- 29th September 2025, 21:35
Less code usage. If for some reason you need Serin, it may hang if the device is not replying correctly. Hserin has timout and will save the day.

For your project it may not have any meaning, but I think it is good practice to use as much as you can the hardware features than the emulated software.

Ioannis

richard
- 30th September 2025, 07:27
if I may ask in this project what the benefit of hardware over software serial control.

doubtful there is any since the 690 does nothing else anyway and the lcd's speed is the real bottle neck

jackberg1
- 1st October 2025, 00:57
I aggree on both comment, Hserin is more convenient than Serin2

the goal of this project was to learn base on inexpensive parts on-hand

you can strech the total cost for less than $12 pcb included not bad for an hobbyist who's looking to add a simple but pratical alphanumeric display

I really appreciate comments

btw , what is happening with MELab Forum, is it close for good.

Ioannis
- 1st October 2025, 13:12
The Melabs Forum is(was?) supported by the company itself. So little is known as to what is happening.

The company does not really have a future.

Some of us here are also dinosaures and reluctant to switch to C or other platforms. So we stay and try to support its operation, as long as our host, honorable Lester, allows this forum to live.

Ioannis

jackberg1
- 1st October 2025, 15:25
very kind of you to reply,

Roughly 12 years ago, I started learning Basic Pic programming with Picaxe, then GCBasic
now I'm mostly using MELab PBP Pro, and Positron both are like twin of Pic Basic compiler.

my guess is these IDE Compilers are the last ones on the market, now the current trend is
with Arduino, Python etc..

if I may ask,

are you aware of any good sources on how,
to learn asm, and understand the asm files structure, to write assembler code, compile it and to download to a PIC

regards.

Ioannis
- 1st October 2025, 16:39
What is the use of learning ASM when C is better with great support and portable too?

I think it is a waste of time if you choose ASM. Also you have to deal with pages, Banks and will be very much difficult to keep your mind checking all the time if your code has to change banks, pages etc in order to access registers correctly.

But if you insist on diving in the deep dark waters of ASM, then I guess Microchip is the first to think. But these video tutorials also help https://www.youtube.com/@IESD2013

Ioannis

jackberg1
- 1st October 2025, 17:20
thanks for the advice, it's helping what to consider.

jackberg1
- 1st October 2025, 19:21
as for C is considered, which IDE/Compiler you use or recommend

jackberg1
- 1st October 2025, 21:32
quick update for the Backpack code: High RS line should be remove to avoid random character on screen when booting.

PORTC = %00000110 : High En : DelayUS 1 : Low En : DelayMS 1 ' Entry mode
' High RS
Return

jackberg1
- 1st October 2025, 22:21
correct order for display control

PORTC = %00001110 ' %00001DCB Display on/off, cursor on/off, blink y/n

Ioannis
- 2nd October 2025, 09:24
Regarding C, MPLABX is the one to try and sure the last. It includes also the MCC tool to setup any microcontroller with ease.

Tried a couple of times C but i guess i am too old to change ...

Ioannis

jackberg1
- 2nd October 2025, 11:10
I did try MPLAB X a year ago and it's was a bitter chalenge comparing to what I'm used to do with PBP3,Picaxe, Positron

jackberg1
- 2nd October 2025, 12:54
Oct 2 2025

update on 16F690 Backpack, new LCDINT pause to accomodate 28800,38400 baud rate for (Xtal = 20Mhz)

#CONFIG
__config _HS_OSC & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOD_OFF & _IESO_OFF & _FCMEN_OFF
#ENDCONFIG

LCDINIT: ' Standard LCD Module Initialisation
PORTC = %00000001 : HIGH EN : PAUSEus 1 : LOW EN : pause 4 ' Clear Display
PORTC = %00000010 : HIGH EN : PAUSEus 1 : LOW EN : pause 2 ' Return Home
PORTC = %00111000 : HIGH EN : PAUSEus 1 : LOW EN : Pause 2 ' 8 bit, 2 line, 5x8 Characters
PORTC = %00000110 : HIGH EN : PAUSEus 1 : LOW EN : Pause 2 ' Entry mode
PORTC = %00001110 : HIGH EN : PAUSEus 1 : LOW EN : Pause 2 ' %00001DCB Display on/off, Cursor on/off, Blink y/n
RETURN

Ioannis
- 2nd October 2025, 16:39
Agree that MPLABX is a bit scarry but has all the tools to complete a task regarding C at least.

You have MCC, Simulator, breakpoints etc. Basic does not give all these goodies.

As for your LCD driver, I think it is a little bit dependant on the specific LCD characteristics. Some are slow and some are a bit faster, so user has take that into account.

Ioannis

jackberg1
- 2nd October 2025, 19:12
totally agree, the LCD is kind of an old tech, but for an hobbyist it's a good learning tool.

to clarify the baud rate turn around, just include this chart to figure it out.

with each OSC setup, it can manage baud rate from 300 ~ 38400.


9992

Ioannis
- 3rd October 2025, 07:32
I meant the LCD timing specs that have differencies. So the end user may have to take into account that.

Things to adjust include these DEFINEs (from the manual):

' Set command delay time in us
DEFINE LCD_COMMANDUS 1500

' Set data delay time in us
DEFINE LCD_DATAUS 44

44 maybe on the edge. 50 maybe more safe.

Ioannis

jackberg1
- 3rd October 2025, 09:30
thanks, to clarify

Ioannis
- 3rd October 2025, 10:45
I know you have already done your PCBs, but an idea for future update, might be to include other type of Character LCDs like:

2x20,
2x40,
4x16
4x20

and be able the user to select these with jumpers. Or even sending serial commands only! This would better need feedback on the serial port but no need for jumpers, so can be implemented on your current PCB.

Ioannis

richard
- 3rd October 2025, 10:53
for my money i would let pbp do all the heavy lifting and leverage their nice efficent routines like this

works for 4 or 8 bit mode and all


'''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''' '
'Name : 16F690 LCD BACKPACK
' Date : oct 2025 richard
' Note : 300 words used of 2048
' Notes : Serin2 Baud Rate 300 ~ 19200 Intrc_OSC 8Mhz
'''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''
#CONFIG
cfg = _INTRC_OSC_NOCLKOUT
cfg&= _WDT_OFF
cfg&= _PWRTE_OFF
cfg&= _MCLRE_OFF
cfg&= _CP_OFF
cfg&= _CPD_OFF
cfg&= _BOD_OFF
cfg&= _IESO_OFF
cfg&= _FCMEN_OFF
__CONFIG cfg
#ENDCONFIG
DEFINE OSC 8
ANSEL = 0 ' Set all pins digital
ANSELH = 0 ' Set all pins digital
OPTION_REG.7 = 0 ' PORTA/PORTB pull-ups are enabled by individual port latch values

CLEAR
DEFINE LCD_BITS 8 'defines the number of data interface lines (4 or 8)
DEFINE LCD_DREG PORTC 'defines the port where data lines are connected to
DEFINE LCD_RSREG PORTB 'defines the port where RS line is connected to
DEFINE LCD_RSBIT 6 'defines the pin where RS line is connected to
DEFINE LCD_EREG PORTB 'defines the port where E line is connected to
DEFINE LCD_EBIT 4 'defines the pin where E line is connected
DEFINE LCD_COMMANDUS 1500 'defines the delay after LCDOUT statement
DEFINE LCD_DATAUS 50 'delay in micro seconds


B1 var byte
Bl var byte


' 300=3313 600=1646 1200=813 2400=396 4800=188 9600=84 19200=32
BaudR var byte : baudr = 32

TRISC = 0
TRISA = % 11111110
OSCCON = $70



PAUSE 500
Porta.0 = 1 ' Backlight ON

LCDOUT $FE,1
' LCDOUT "ready @19200"
@ bsf LCD_RSREG ,LCD_RSBIT






main:
serin2 Portb.5,baudr,3,main,[b1]
if bl then
if b1 = 0 then
porta.0 = 0 ' Back Light OFF
endif
if b1 = 8 then
porta.0 = 1 ' Back Light ON
endif
bl = 0
goto main
endif
if b1 = 255 then
bl = 1
goto main
endif
if b1 = 254 then
@ bcf LCD_RSREG ,LCD_RSBIT
goto main
endif
@ MOVE?BB _B1,R3
@ L?CALL lcdsend
@ bsf LCD_RSREG ,LCD_RSBIT
goto main ' loop back to top

ps forgot to add it is now so easy to add a flash screen on boot

Ioannis
- 3rd October 2025, 11:50
what is that bl (second line after main)? I guess bl should be b1.

But then, if b1 gets a 0 from the serial in, how the if-then's will work?

Ioannis

richard
- 3rd October 2025, 14:40
One var is B1 the other is BL, as in bl for bachlight .
I would need to paid more for properly named vars and valid meaningful comments

Ioannis
- 3rd October 2025, 14:49
Well, ok then. BL stands for the back light. But where does it get set?

Ioannis

richard
- 3rd October 2025, 16:15
When B1=255

Ioannis
- 3rd October 2025, 16:51
Oops...!

Ioannis

jackberg1
- 4th October 2025, 01:13
yes that's a very good idea, the one I have tested are 1601, 1602, 2004

jackberg1
- 5th October 2025, 01:14
Here's a shrink down version for displaying messages from internal arrays no serial input involved.
practical if just an operating device with control buttons attach to the remaining 5 ports is needed





'''''''''''''''''''''''''''''''''''''''''''''''''' ''''''''''''''''''''''''''
' Project : LCD Backpack Self Text (Write text on LCD no serial port)
' Name : 16F690 LCD BACKPACK for Hitachi HD44780 1601 / 1602 / 2004
' Date : Oct 3 2025
' Notes : 320 words used of 4096
'''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''
Device = 16F690
'Declare Xtal = 8
'Config INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_OFF, MCLRE_OFF, CP_OFF, CPD_OFF, IESO_OFF, FCMEN_OFF
Declare Xtal = 20
Config HS_OSC, WDT_OFF, PWRTE_OFF, MCLRE_OFF, CP_OFF, CPD_OFF, IESO_OFF, FCMEN_OFF
ANSEL = 0 ' Set all pins digital
ANSELH = 0 ' Set all pins digital
TRISA = 0 : TRISB = %00100000 : TRISC = 0 : PORTA = 0 : PORTB = 0 : PORTC = 0
OSCCON = $70


Dim I As Byte


' 1601 1602 16 Char 1/2 Lines
Dim MyArrayA[16] As Byte = "0123456789ABCDEF"
Dim MyArrayB[16] As Byte = "abcdefghijklmnop"


' 2004 20 Char 4 Lines
'Dim MyArrayC[20] As Byte = "ABCDDE1234567890ABCD"
'Dim MyArrayD[20] As Byte = "abcdefghijklmnop1234"
'Dim MyArrayE[20] As Byte = "ABCDDE1234567890abcd"
'Dim MyArrayF[20] As Byte = "abcdefghijklmnop1234"


GoSub LCDINIT ' initialise LCD
PORTA = 1 ' Backlight ON


main:
' 1601 / 1602
PORTB = 0 : PORTC = 128 : PORTB = %00010000 : DelayUS 1 : PORTB = 0 : PORTB = %01000000 : DelayMS 3 ' Line 1
For I = 0 To 15
PORTC = MyArrayA[I] : PORTB = %01010000 : DelayUS 1 : PORTB = %01000000 : DelayMS 1
Next I


PORTB = 0 : PORTC = 192 : PORTB = %00010000 : DelayUS 1 : PORTB = 0 : PORTB = %01000000 : DelayMS 3 ' Line 2
For I = 0 To 15
PORTC = MyArrayB[I] : PORTB = %01010000 : DelayUS 1 : PORTB = %01000000 : DelayMS 1
Next I


' 2004
(*PORTB = 0 : PORTC = 128 : PORTB = %00010000 : DelayUS 1 : PORTB = 0 : PORTB = %01000000 : DelayMS 3 ' Line 1
For I = 0 To 19
PORTC = MyArrayC[I] : PORTB = %01010000 : DelayUS 1 : PORTB = %01000000 : DelayMS 1
Next I
PORTB = 0 : PORTC = 192 : PORTB = %00010000 : DelayUS 1 : PORTB = 0 : PORTB = %01000000 : DelayMS 3 ' Line 2
For I = 0 To 19
PORTC = MyArrayD[I] : PORTB = %01010000 : DelayUS 1 : PORTB = %01000000 : DelayMS 1
Next I
PORTB = 0 : PORTC = 148 : PORTB = %00010000 : DelayUS 1 : PORTB = 0 : PORTB = %01000000 : DelayMS 3 ' Line 3
For I = 0 To 19
PORTC = MyArrayE[I] : PORTB = %01010000 : DelayUS 1 : PORTB = %01000000 : DelayMS 1
Next I
PORTB = 0 : PORTC = 212 : PORTB = %00010000 : DelayUS 1 : PORTB = 0 : PORTB = %01000000 : DelayMS 3 ' Line 4
For I = 0 To 19
PORTC = MyArrayF[I] : PORTB = %01010000 : DelayUS 1 : PORTB = %01000000 : DelayMS 1
Next I*)


DelayMS 2000
PORTB = 0 : PORTC = 1 : PORTB = %00010000 : DelayUS 1 : PORTB = 0 : PORTB = %01000000 : DelayMS 4 ' Clear display
DelayMS 255
PORTA = 0 ' Bacck Light off
DelayMS 255
PORTA = %00000001 ' Bacck Light on
DelayMS 255


GoTo main


LCDINIT:
PORTC = %00000001 : PORTB = %00010000 : DelayUS 1 : PORTB = 0 : DelayMS 4 ' Clear display
PORTC = %00000010 : PORTB = %00010000 : DelayUS 1 : PORTB = 0 : DelayMS 2 ' Return Home
PORTC = %00111000 : PORTB = %00010000 : DelayUS 1 : PORTB = 0 : DelayMS 2 ' 5x8 Character 8 Bit, 2 Line
PORTC = %00001100 : PORTB = %00010000 : DelayUS 1 : PORTB = 0 : DelayMS 2 ' %00001DCB Display on/off, cursor on/off, blink y/n
PORTC = %00000110 : PORTB = %00010000 : DelayUS 1 : PORTB = 0 : DelayMS 2 ' Entry mode
Return

Ioannis
- 5th October 2025, 18:52
This code is not for PicBasic dialect...

Ioannis

Ioannis
- 5th October 2025, 21:39
Tried to test Richards code, but seems i cant make the LCD work at all.

For starters the Backlight does not turn off.

What is the sequence that should be sent over the serial port to control backlight and then send some text over to LCD?

Ioannis

Ioannis
- 5th October 2025, 22:05
The backlight is controlled by 255d and 0d or 255d and 8d.

Have yet to send some text over the LCD.

Ioannis

jackberg1
- 6th October 2025, 01:03
OOP'S!

usualy I code in both Positron & PBP3.

here's the PBP3 code. (added Pause C)





'''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''
' Name : 16F690 LCD BACKPACK Self Text
' Date : Oct 4-2025
'''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''
' Serin2
'#CONFIG
' __config _INTRC_OSC_CLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOD_OFF & _IESO_OFF & _FCMEN_OFF
'#ENDCONFIG


' HSERIN
#CONFIG
__config _HS_OSC & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOD_OFF & _IESO_OFF & _FCMEN_OFF
#ENDCONFIG


DEFINE OSC 20 ' Core is running at EXT-CRYSTAL 20MHz PBP 33,217
ANSEL = 0 ' Set all pins digital
ANSELH = 0 ' Set all pins digital
OPTION_REG.7 = 0 ' PORTA/PORTB pull-ups are enabled by individual port latch values
CM1CON0 = 0 ' Analog comparators off


En var Portb.4 : low en
RS var Portb.6 : low rs
B1 var byte : b1 = 0
C VAR BYTE : C = 10
I VAR BYTE


' 1601 - 1602
ArrayA var Byte [16] : ARRAYWRITE ArrayA,["ABCDEF1234567890"] ' Line 1
ArrayB var Byte [16] : ARRAYWRITE ArrayB,["1234567890!@#$%^"] ' Line 2
' 2004
'ArrayC var Byte [20] : ARRAYWRITE ArrayC,["ABCDEF1234567890!@#$"] ' Line 1
'ArrayD var Byte [20] : ARRAYWRITE ArrayD,["1234567890!@#$%^!@#$"] ' Line 2
'ArrayE var Byte [20] : ARRAYWRITE ArrayE,["ABCDEF1234567890!@#$"] ' Line 3
'ArrayF var Byte [20] : ARRAYWRITE ArrayF,["1234567890!@#$%^!@#$"] ' Line 4


TRISA = 0 : TRISB = %00100000 : TRISC = 0
PORTA = 0 : PORTB = 0 : PORTC = 0
OSCCON = $70


pause 100
high Porta.0 ' Backlight ON
gosub LCDinit ' initialise LCD
pause 100


main:
' 1601 - 1602
Low RS : PORTC = 128 : High En : PauseUS 1 : Low En : High RS : Pause 3 ' Line 1
For I = 0 To 15
PORTC = ArrayA[I]
High En : PauseUS 1 : Low En
Pause C
Next I
Low RS : PORTC = 192 : High En : PauseUS 1 : Low En : High RS : Pause 3 ' Line 2
For I = 0 To 15
PORTC = ArrayB[I]
High En : PauseUS 1 : Low En
Pause C
Next I


' 2004
'Low RS : PORTC = 128 : High En : PauseUS 1 : Low En : High RS : Pause 3 ' Line 1
'For I = 0 To 19
' PORTC = ArrayC[I]
' High En : PauseUS 1 : Low En
' Pause C
'Next I
'Low RS : PORTC = 192 : High En : PauseUS 1 : Low En : High RS : Pause 3 ' Line 2
'For I = 0 To 19
' PORTC = ArrayD[I]
' High En : PauseUS 1 : Low En
' Pause C
'Next I
'Low RS : PORTC = 148 : High En : PauseUS 1 : Low En : High RS : Pause 3 ' Line 3
'For I = 0 To 19
' PORTC = ArrayE[I]
' High En : PauseUS 1 : Low En
' Pause C
'Next I
'Low RS : PORTC = 212 : High En : PauseUS 1 : Low En : High RS : Pause 3 ' Line 4
'For I = 0 To 19
' PORTC = ArrayF[I]
' High En : PauseUS 1 : Low En
' Pause C
'Next I

Pause 1000
Low RS : PORTC = 1 : High En : PauseUS 1 : Low En : High RS : PauseUS 4 ' Clear display
Pause 500
'Low PORTA.0 ' Bacck Light off
Pause 200
High PORTA.0 ' Bacck Light on
Pause 200


GoTo main

LCDINIT: ' Standard LCD Module Initialisation
PORTC = %00000001 : HIGH EN : PAUSEus 1 : LOW EN : pause 4 ' Clear Display
PORTC = %00000010 : HIGH EN : PAUSEus 1 : LOW EN : pause 2 ' Return Home
PORTC = %00111000 : HIGH EN : PAUSEus 1 : LOW EN : Pause 2 ' 8 bit, 2 line, 5x8 Characters
PORTC = %00000110 : HIGH EN : PAUSEus 1 : LOW EN : Pause 2 ' Entry mode
PORTC = %00001100 : HIGH EN : PAUSEus 1 : LOW EN : Pause 2 ' %00001DCB Display on/off, Cursor on/off, Blink y/n
RETURN

jackberg1
- 6th October 2025, 01:37
the code I use are similar, you can try to adapt.

for the Hitachi HD44780 the decimal 254 represent the low RS then you need ot receive the line # as 128 line #1, 192 line #2, 148 line #3, 212 line #4

sEROUT2 lcd,baudR,pace,[254,128,"ABCDEFGHIJKLMNOP"] ' Line 1 16 Char


as for Richard code , for the Back Light he's using a toggle on,off with b1. (by receiving b1 turn On, then again turn Off)

richard
- 6th October 2025, 02:16
as for Richard code , for the Back Light he's using a toggle on,off with b1. (by receiving b1 turn On, then again turn Off)

Or more like
SEROUT2 lcd,baudR,pace,[ 255, 8] ' Back Light OFF
SEROUT2 lcd,baudR,pace,[ 255, 0] ' Back Light ON

depending on how you connected the backlight of course

jackberg1
- 6th October 2025, 02:48
just set:

BaudR var word


work fine here

jackberg1
- 6th October 2025, 03:23
tested richard code, work fine 300 to 9600 at 8Mhz (_INTRC_OSC_NOCLKOUT)

19200 not working at 8Mhz and 20Mhz Xtal

back light working fine 300~19200


9993

richard
- 6th October 2025, 06:32
My code honours the timing as specified by the lcd defines , timing that most lcd displays need esp the cheapest and oldest examples of them.
If you send data at a rate that exceeds the specified time constraints as defined it will of course fall. The solution is to either pace data transmission or set the defines to the actual speed the lcd can tolerate . The intent of my code is to match data rate to the real speed that the lcd can manage

jackberg1
- 6th October 2025, 11:57
set pace to 1 , and it's working
sEROUT2 lcd,baudR,pace,[254,128,"ABCDEFGHIJKLMNOP"]

thanks.

Ioannis
- 6th October 2025, 15:39
I only tested at 19200 and the Backlight works OK.

But text, could not send up to this moment.

WIll try different Baud Rate. Though I test on a PIC16F1827 at 32MHz.

Ioannis

jackberg1
- 6th October 2025, 16:12
when testing baud rate, usualy I start at 300 and up

when it stopped working then I set pace = 1

and re-start from the last baud rate tested.

16F690 Xtal 20Mhz

set pace to 1
sEROUT2 lcd,baudR,pace,[254,128,"ABCDEFGHIJKLMNOP"]


from my code here's the tested baud rate .
and when booting the PIC's at different baud rate the sender 12F683 and receiver 16F690 the LCD screen light up right away and start displaying text, and back light on/off
there's no lag for the first receiving if I remember correctly the pace for the sender is set = 0.


9994


Also I add baud rate selection jumpers on the Backpack''


9995




' Jumpers
'
J3 300 600 1200 2400 4800 9600 14400 19200 28800 38400
' 1--2 RB7 On On On On On On
' 3--4 RA2 On On On On
' 5--6 RA1 On On On On
' 7--8 RA3 On On On



' Baud Rate SW Selection (PCB J3)
If PORTA = 001110 And PORTB.7 = 1 Then BaudR = 3313 ' 300
If PORTA = 001110 And PORTB.7 = 0 Then BaudR = 1646 ' 600
If PORTA = 001010 And PORTB.7 = 1 Then BaudR = 813 ' 1200
If PORTA = 001100 And PORTB.7 = 1 Then BaudR = 396 ' 2400
If PORTA = 000110 And PORTB.7 = 1 Then BaudR = 188 ' 4800
If PORTA = 001010 And PORTB.7 = 0 Then BaudR = 84 ' 9600
If PORTA = 001100 And PORTB.7 = 0 Then BaudR = 49 ' 14400
If PORTA = 000110 And PORTB.7 = 0 Then BaudR = 32 ' 19200
If PORTA = 001000 And PORTB.7 = 0 Then BaudR = 15 ' 28800
If PORTA = 000000 And PORTB.7 = 0 Then BaudR = 6 ' 38400

jackberg1
- 6th October 2025, 16:47
from my last edit,

' Jumpers
' J3 300 600 1200 2400 4800 9600 14400 19200 28800 38400
' 1--2 RB7 On On On On On On
' 3--4 RA2 On On On On
' 5--6 RA1 On On On On
' 7--8 RA3 On On On

I think courier new does not take spaces !
better use screen cap


9996

jackberg1
- 6th October 2025, 20:10
edited BaudR var word : baudr = 3313 and TRISA = 111110

1st receiving random characters
2nd normal

what could be done to avoid the first
thanks.

9997

richard
- 7th October 2025, 02:57
its always better to use the hardware than bit-banged routines and there is nothing better than a ring-buffer to overcome traffic snarls



'''''''''''''''''''''''''''''''''''''''''''''''''' ''''''''''''''''''''''''''''
' Name : 16F690 LCD BACKPACK
' Date : oct 2025 richard
' Note : RING BUFFERED
' Notes : 19200 Intrc_OSC 8Mhz
'''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''
#CONFIG
cfg = _INTRC_OSC_NOCLKOUT
cfg&= _WDT_OFF
cfg&= _PWRTE_OFF
cfg&= _MCLRE_OFF
cfg&= _CP_OFF
cfg&= _CPD_OFF
cfg&= _BOD_OFF
cfg&= _IESO_OFF
cfg&= _FCMEN_OFF
__CONFIG cfg
#ENDCONFIG
DEFINE OSC 8
DEFINE INTHAND myint
ANSEL = 0 ' Set all pins digital
ANSELH = 0 ' Set all pins digital
OPTION_REG.7 = 0 ' PORTA/PORTB pull-ups are enabled by individual port latch values

CLEAR
DEFINE LCD_BITS 8 'defines the number of data interface lines (4 or 8)
DEFINE LCD_DREG PORTC 'defines the port where data lines are connected to
DEFINE LCD_RSREG PORTB 'defines the port where RS line is connected to
DEFINE LCD_RSBIT 6 'defines the pin where RS line is connected to
DEFINE LCD_EREG PORTB 'defines the port where E line is connected to
DEFINE LCD_EBIT 4 'defines the pin where E line is connected
DEFINE LCD_COMMANDUS 1500 'defines the delay after LCDOUT statement
DEFINE LCD_DATAUS 50 'delay in micro seconds


RCSTA = $90 ' Enable serial port & continuous receive
TXSTA = $20 ' Enable transmit, BRGH = 0
SPBRG = 25 ' 19200 Baud @ 8MHz, 0.16%
SPBRGH = 0
BAUDCTL.3 = 1 ' Enable 16 bit baudrate generator


wsave VAR BYTE $70 SYSTEM ;wsave in access RAM
ssave VAR BYTE BANK0 SYSTEM
psave VAR BYTE BANK0 SYSTEM
index_in VAR BYTE bank0 ' Pointer - next empty location in buffer
index_out VAR BYTE bank0 ' Pointer - location of oldest character in buffer
errflag VAR BYTE bank0 ' Error flag
UartFlag VAR errflag.0
BufferFlag VAR errflag.1
buffer_size CON 32 ' Sets the size of the ring buffer
buffer VAR BYTE[buffer_size] ' Array variable for holding received characters
bufchar VAR BYTE ' Stores the character retrieved from the buffer
Bl var byte




GOTO overint ' Jump over the interrupt handler
ASM
myint
if CODE_SIZE <= 2 ; If less than 2K code space
; Save the state of critical registers (PIC12/PIC16)
movwf wsave ; Save W
swapf STATUS,W ; Swap STATUS to W (swap avoids changing STATUS)
clrf STATUS ; Clear STATUS
movwf ssave ; Save swapped STATUS
movf PCLATH,W ; Move PCLATH to W
movwf psave ; Save PCLATH
endif
; Check for hardware overrun error
btfsc RCSTA,OERR ; Check for usart overrun
goto usart_err ; jump to assembly error routine
; Test for buffer overrun
incf _index_in,W ; Increment index_in to W
subwf _index_out,W ; Subtract indexes to test for buffer overrun
btfsc STATUS,Z ; check for zero (index_in = index_out)
goto buffer_err ; jump to error routine if zero
; Increment the index_in pointer and reset it if it's outside the ring buffer
incf _index_in,F ; Increment index_in to index_in
movf _index_in,W ; Move new index_in to W
sublw _buffer_size-1; Subtract index_in from buffer_size-1
btfss STATUS, C ; If index_in => buffer_size
clrf _index_in ; Clear index_in
; Set FSR with the location of the next empty location in buffer
movlw _buffer ;Store the High byte of buffer to FSR
movwf FSR
addwf _index_in,W ; Add index_in to point to next empty slot
movwf FSR ; Store Low byte of pointer in FSR
; Read and store the character from the USART
movf RCREG,W ; Read the received character
movwf INDF ; Put the received character in FSR location
BTFSC PIR1,RCIF ;ANY MORE ?
goto myint
finished
; Restore the state of critical registers (PIC12/PIC16)
movf psave,W ; restore PCLATH
movwf PCLATH
swapf ssave,W ; restore STATUS
movwf STATUS
swapf wsave,F ; restore W (swap avoids changing STATUS)
swapf wsave,W
retfie ; Return from interrupt
; Error routines
buffer_err ; Jump here on buffer error
bsf _errflag,1 ; Set the buffer flag
usart_err ; Jump here on USART error
bsf _errflag,0 ; Set the USART flag
movf RCREG, W ; Trash the received character
goto finished ; Restore state and return to program
ENDASM
overint:
TRISC = 0
TRISB = % 10101111
TRISA = % 11111110
OSCCON = $70
PAUSE 500
hserout ["ready @19200"]
LCDOUT $FE,1
LCDOUT "ready @19200"
PAUSE 500
@ bsf LCD_RSREG ,LCD_RSBIT
INTCON = $C0
PIE1.5 = 1
GOSUB ERROR
main:
IF errflag Then GOSUB error ' Goto error routine if needed
IF index_in = index_out Then main ' loop if nothing in buffer
GoSub getbuf ' Get a character from buffer
' hserout [bufchar] ' Send the character to terminal
if bl then
if bufchar = 0 then
porta.0 = 0 ' Back Light OFF
endif
if bufchar = 8 then
porta.0 = 1 ' Back Light ON
endif
bl = 0
goto main
endif
if bufchar = 255 then
bl = 1
goto main
endif
if bufchar = 254 then
@ bcf LCD_RSREG ,LCD_RSBIT
goto main
endif
@ MOVE?BB _bufchar,R3
@ L?CALL lcdsend
@ bsf LCD_RSREG ,LCD_RSBIT
goto main ' loop back to top



error: ' Display error message
INTCON = 0 ' Disable interrupts while in the error routine
IF errflag.1 Then ' Determine the error
hserout ["B!",13]' Display buffer error on line-2
Else
hserout ["U!",13] ' Display usart error on line_2
EndIF
PIR1.5=0
errflag = 0 ' Reset the error flag ;clear any rcsta error
RCSTA.4=0 'CREN = 0 Disable continuous receive to clear hardware error
RCSTA.4=1 'CREN = 1 Enable continuous receive
INTCON = %11000000 ' Enable interrupts
RETURN ' repeat



getbuf: ' Move the next character in buffer to bufchar
index_out = index_out + 1 ' Increment index_out pointer (0 to 31)
IF index_out => buffer_size Then index_out = 0 ' Reset pointer if outside buffer
bufchar = buffer[index_out] ' Read buffer location(index_out)
Return

jackberg1
- 7th October 2025, 08:17
ASM , very impressif code,

thanks.

jackberg1
- 7th October 2025, 11:26
here's the revised baud rate test chart

9998

Ioannis
- 8th October 2025, 23:34
Tried different baud rate but still only Backlight work. The rest is just irrelevant characters on screen.

Then tried the new code of Richards, but have 1827 chip, so asm code is not compatible.

Gave up...

Ioannis