Universal Test Code for all Parallel Bus Alphanumeric LCD Configurations

inglewoodpete

Senior Member
Configuring your new LCD can be challenging task, particularly if your model does not use a serial interface.

The attached code simplifies the task by specifying a universal piece of executable code with a few, separate lines of "Symbols" to define the function of each pin. The code is independent of hardware constraints: gone are the days where you have to connect specific pins to each other for the LCD to work!

The code is an ideal way to do an initial test of a new PCB or stripboard design incorporating an LCD.

This code is designed to run the parallel LCD in 4-bit mode. All you have to do is connect a total of 8 wires between your PICAXE and the parallel LCD module. This assumes that you have an LCD module that runs at the same voltage as the PICAXE - usually this is 4.5 or 5 volts.

Edit: Some LCD boards the R/W pin tied to 0v to ensure that your can only write to the LCD. If your LCD module does not tie this line low already, then you will need to do this. Refer to post #6 for options. The R/W pin is pin 5 on the three different LCD connectors that I'm aware of.

  • Two of the wires are obviously the Ground or 0v line and the +5v line.
  • The 4 data lines (d4 - d7) and 2 control wires (Enable and Register Select) connect to any output pin that you have free on your PICAXE.
Having connected your hardware, paste the attached code into the Programming Editor. First, change the "PICAXE" directive to suit the model of your PICAXE.

Next adjust the 8 Symbol commands to point to the outputs that you have connected your LCD inputs to. Note that the actual leg numbers on the chip will differ according to the model you are using. Refer to Manual 1 - "Getting Started" for pinout diagrams.

Save the code and download it to your PICAXE. If you have configured everything correctly, you shoud see the "Hello World!" message on your LCD.

Code:
'Simple, flexible test routine for parallel LCDs (Tested on a 16 char x 2 row LCD)
'Should work on any PICAXE with 14 or more legs.
'#PICAXE 28X2    'Change to suit your processor
'
' **** Pins ****
'
' 4-bit mode: Uses a total of 8 wires between the PICAXE and LCD:
'              0v, +5v, Register Select and LCD Enable
'              4 data wires: Pins 4 to 7 on the LCD
'
' Flexible software:
'   (practically*) any pin of the PICAXE can connect to any of the 6 control pins of the LCD
'    *Note that leg 4 on the following PICAXEs is input-only and can't be used as an output
'     Don't use 14M2/C.3; 18M2/C.5; 20M2/C.6 and 20X2/C.6
'
'   After wiring up the LCD to the PICAXE (Data transfer is via pins 4 to 7 on the LCD),
'     define the following symbols to their function.
'  Note that the 4 data pins must be addressed in 2 two different ways
'
Symbol oLCDpin4   = outpinB.1   'B.1 for writing to the output pin directly 
Symbol oLCD4      = B.1
'
Symbol oLCDpin5   = outpinB.5   'B.5 for writing to the output pin directly
Symbol oLCD5      = B.5
'
Symbol oLCDpin6   = outpinB.6   'B.6 for writing to the output pin directly
Symbol oLCD6      = B.6
'
Symbol oLCDpin7   = outpinB.7   'B.7 for writing to the output pin directly
Symbol oLCD7      = B.7
'
Symbol oLCDRS     = C.0         'C.0 Register select: Low for Commands, High for Characters

Symbol oLCDEn     = C.1         'C.1 Enable pin. Default condition is low. Pulse High to input data.
'
'   There is no need to touch the code of the test routine!!
'   After defining the above symbols, the code should compile, load and run.  Simple!
'
'       EEPROM and Message Pointer
Symbol eMsgStart  = 0
EEPROM eMsgStart, ("Hello World!", 0)
'
' ************************************************************
' **** Test routine - Uses byte registers b0 and b1       ****                  
' ************************************************************
'
'  DO NOT CHANGE THE CODE LISTED BELOW! 
'  
Init:    'Initialise the I/O Pins
         Output oLCD4, oLCD5, oLCD6, oLCD7, oLCDRS, oLCDEn
         '
         'Initialise the LCD module
         Low oLCDEn                   '(Default value is low)
         Low oLCD7, oLCD6: High oLCD5, oLCD4   'Pattern %0011 ("Function Set")
         PulsOut oLCDEn, 2            'Pulse enable pin 3 times to initialise
         Pause 50                     'Minimum 4.1mS (all clock speeds)
         PulsOut oLCDEn, 2            '2nd Function Set
         Pause 4                      'Minimum 100uS (all clock speeds)
         '
         'Send a series of 8-bit commands to configure the LCD
         b0 = %00110010               '$32 3rd Function Set, then 4-bit data, 2-line display
         Gosub Cmd2LCD                '    Send the command
         b0 = %00001000               '$08 Reset Display to the selected mode
         Gosub Cmd2LCD
         b0 = %00001100               '$0C Turn the Display On with hidden cursor
         Gosub Cmd2LCD
         b0 = %00000110               '$06 Move the input (Ie "cursor") point after each character
         Gosub Cmd2LCD
         b0 = %00000001               '$01 Clear the Display
         Gosub Cmd2LCD
         Pause 35                     '~4mS Required to let LCD clear (all clock speeds)
         '
         'Now send a simple "Hello World!" message to the LCD screen
         b1 = eMsgStart               'Point to the EEPROM Massage
         Read b1, b0                  'Fetch the first character
         Do                           'Loop through this code to send each character
            GoSub Chr2LCD             'Send the character to the LCD screen
            Inc b1                    'Move to next source location in EEPROM
            Read b1, b0               'Fetch the next character
         Loop Until b0 < " "          'Drop out of loop when first non-printing character is found
         '                            ' (The space $20/32d/" " is lowest printable ASCII character)
         Do: Loop
         '
'
' ************************************************************
' **** Subroutine: Write a Single Byte to the LCD         ****
' ************************************************************
'
'         Two different entry points: Either send command or character to LCD
'         Registers Used: b0 must be used due to bit addressing
'
Cmd2LCD: Low oLCDRS                   'Point to command register (Otherwise defaults to character reg)
         '
Chr2LCD: oLCDpin4 = bit4              'High nibble is sent first
         oLCDpin5 = bit5
         oLCDpin6 = bit6
         oLCDpin7 = bit7
         PulsOut oLCDEn, 2            'Clock 4 high bits of data into LCD
         oLCDpin4 = bit0              'Followed by the low nibble
         oLCDpin5 = bit1
         oLCDpin6 = bit2
         oLCDpin7 = bit3
         PulsOut oLCDEn, 2            'Clock 4 low bits of data into LCD
         High oLCDRS                  'Next received byte defaults to displayable character
         Return
'
' ************************************************************
 
Last edited:

nick12ab

Senior Member
And what if an 8-bit interface needs testing?

Is this test code really necessary? You can download your own code and see if it works, or the AXE133 firmware.
 

Paix

Senior Member
I'm unlikely to use your code IP, but I do appreciate the time and thought that you have taken to present an alternative approach for those that may not have the AXE133 firmware and wish to have a dabble.

Not all things in life need to be really necessary to be appreciated or found useful and if an 8-bit interface needs testing, then one can only imagine that a piece of code for that might eventually have been considered by IP if he had received encouragement.

It's raining heavily in some parts of the UK today I understand. :)
 

inglewoodpete

Senior Member
And what if an 8-bit interface needs testing?
Gee whizz Nick:rolleyes:. Often, one of the hardest challenges is to get an LCD working, particularly for beginners. We see those threads on the forum regularly. Anyway, if someone has an 8 bit interface, they can still test it in 4-bit mode and then move on to bigger things. Often, the question is: "Is my cheap LCD damaged? Will it ever work?" Perhaps you could write a flexible 8-bit universal version of my code but I suspect that your audience could be quite small.

Is this test code really necessary? You can download your own code and see if it works, or the AXE133 firmware.
  • Necessary? Yes - it promotes flexibility and discussion on PICAXE issues:).
  • Download my own code? I provided this code as an easy and flexible test solution for others to use.
  • The AXE133 firmware? The Rev-Ed firmware is great if you have the same physical connections as the AXE133 - however, you have to use Port B in a fairly rigid configuration. Some chips have i2c, PWM or Touch on the same pins that the AXE133 code needs to use. My offering is a more flexible alternative, available for those with open minds. It resulted from me buying a cheap Shield/Keypad off the net, which had a different pin configuration to the AXE133. I actually got the idea when I saw how flexible the Arduino LCD configuration and commands are for parallel LCDs.
It's raining heavily in some parts of the UK today I understand. :)
Yes, I noticed. Tomorrow will be a new day, though.
 

matherp

Senior Member
Very useful. I nearly always use parallel connect LCDs and it is always a pain to dig up old code and modify it for whatever combination of pins are in use particularly as my code is often optimised to match the hardware using byte writes etc. where possible.

One minor enhancement. Some development boards connect the LCD R/W pin to the processor. An additional symbol for oLDCRW which is then set low would avoid this being a stumbling block.
 

inglewoodpete

Senior Member
Just when I thought I had all bases covered

One minor enhancement. Some development boards connect the LCD R/W pin to the processor. An additional symbol for oLDCRW which is then set low would avoid this being a stumbling block.
Peter, thanks for pointing that out. I thought I had all the bases covered. My LCD/Keypad shield from Deal Extreme actually has the R/W pin soldered to the ground plane, so 'write' is the only option.

The R/W pin is pin 5 on the three LCD connectors that I'm familiar with: the top left SIL, bottom left SIL and the left-hand 2x8 DIL connector. People should check the circuit and pinout for their particular LCD (or OLED).

The R/W pin can either be connected to 0v (Gnd) pin or be connected through to another output pin on the PICAXE. If you choose the second option, as matherp suggests, this pin should be added to the Symbol definitions and an additional pin can be added to the 'Output' and first 'Low' commands - refer to the code, below.

If it's any help when making the decision: I've used parallel LCDs on several occasions over the past few years and have never had a need to read data from the LCD, so I've always soldered the R/W pin to 0v. This also saves using another PICAXE pin.

Code:
'
'Where you need to read data from the LCD and choose not tie the R/W pin to 0v
Symbol oLDCRW     = C.3         'C.3 Read/Not_Write pin (refer to the PICAXE Forum notes)

'Replace the first five lines of code with these (Yes, I know it says "DO NOT CHANGE.....):
Init:    'Initialise the I/O Pins
         Output oLCD4, oLCD5, oLCD6, oLCD7, oLCDRS, oLCDEn, oLDCRW    'Note oLDCRW is optional
         '
         'Initialise the LCD module
         Low oLCDEn, oLDCRW           'Default value is low (oLDCRW pin is optional)
 

mfs

New Member
I'm new and appreciate your code, Peter, it has got me up and running, thank you. That said, I have been having problems getting the LCD to write on the second line, everything works fine on the first line. If I move the cursor to the second line by sending a $C0 right after the clear the display code and before the Hello World output routine:
Your code:
b0 = %00000001 '$01 Clear the Display
Gosub Cmd2LCD
Pause 35 '~4mS Required to let LCD clear (all clock speeds)
my code:
b0 = %11000000 '$C0 Move to second line
Gosub Cmd2LCD

nothing shows up on the second line of the display. After trying a bunch of different things (such as long character strings that I would expect to wrap to second line) and not being able to write to the second line, I'm thinking it may not be initialized correctly for a 2 line display (or I'm really missing something)

When I look at the LCD reference, I would expect $28 would be the correct initialization sequence to set data length, number of display lines and font. I have looked at different LCD initialization code for other processors and they all seem to use $28 in their initialization sequence. Your code:

b0 = %00110010 '$32 3rd Function Set, then 4-bit data, 2-line display

is different and works (for 1 line at least) for me. How did you come to use $32 when that would seem to configure it for 8bit data and 1 line display? When I try the $28 it does not work for either line so I'm stumped and would appreciate any pointers, thoughts.

Thanks, Mike
 

Rick100

Senior Member
Hello Mike,

I have an lcd wired up on my breadboard, so I tried inglewoodpete's code on an 18m2 with both a 4X20 and a 1X16 display. Both had 2 logical lines. The code worked as expected, displaying "Hello World!" on the first line.
Adding your code:
Code:
b0 = %11000000 '$C0 Move to second line
Gosub Cmd2LCD
after the line "Pause 35 '~4mS Required to let LCD clear (all clock speeds)" displayed the message on the second line.

When I look at the LCD reference, I would expect $28 would be the correct initialization sequence to set data length, number of display lines and font. I have looked at different LCD initialization code for other processors and they all seem to use $28 in their initialization sequence. Your code:

b0 = %00110010 '$32 3rd Function Set, then 4-bit data, 2-line display

is different and works (for 1 line at least) for me. How did you come to use $32 when that would seem to configure it for 8bit data and 1 line display? When I try the $28 it does not work for either line so I'm stumped and would appreciate any pointers, thoughts.
I would expect to find a $28 also. I believe the high nibble of $32 is the 3rd 8 bit function set and the low nibble is the 1st 4 bit function set.
Try adding:

Code:
b0 = %00101000               '$28 4-bit data, 2-line display
Gosub Cmd2LCD
after the "Gosub Cmd2LCD" for the $32. Make sure you leave the $32 sequence in. I tried it on my test setup and it still worked on both lcds.

Just out of curiosity I remove the $28 command from my own lcd initialization code and tried it. Both displays worked the same with or without it. I guess the default is 2 lines. I thought I read they defaulted to 1 line. Your display may default to 1 line. Of course, you may just have a bad lcd. What kind of lcd do you have and which Picaxe are you using?

Good luck,
Rick
 

john2051

New Member
Hi Iglewoodpete, I've already used your code (thank you) to test some rally bought large character 20x4 displays. I'l try and adapt it for some 40x4
what look like dual controllers.
This forum seems to be falling into the arduino trap, where if you ask a genuine question, you tend to get ridiculed, or even insulted. Sometime ago a friend of mine bought some
rtc modules with eeprom, and 3 holes for a ds18b20. He enquired as to the reasoning why no one had used them, and one idiot said why would you want to measure
the temperature of the board!
I think what you've done is good, and if that helps even just one person, then you have helped. Isnt that what all these forums should be about?
Keep writing code please, some of us regardless of age or experience always miss something.
regards john
 

inglewoodpete

Senior Member
Keep writing code please, some of us regardless of age or experience always miss something.
regards john
Thanks for the kind words John. Your post brought this thread to my attention again. I had missed the discussion back in May, where there had been issues with configuring (1- and) 2-line displays. Fortunately, Rick100 seems to have found a solution to mfs' (Mike's) problem. I can see that I was lucky that my display defaulted to 2x16 characters. I am reluctant to change the sample code that I provided until I can test Rick's solution on my hardware. The suggested sequence of commands to initialise the LCD concerns me.

P.S. I have fond memories of a day I spent in Lincoln with a friend from Nottingham over 30 years ago. I only had a few hours in Lincoln, seeing the cathedral and castle, with lunch at "The Wig & Mitre"(?) - I might have got that name wrong: as I say, it was long time ago.
Peter
 

rchadwic

New Member
View attachment Picaxe 18M WDC2401 display driver.bas

A tip of the hat to inglewoodpete for his Universal Test Code for LCD displays. I have been working with a WD-C-2401 24x1 display based on the Hitachi 66717 controller and, using pete’s code as modified by what I learned both “the hard way” and from some data gleaned from the Arduino forums, I finally got the display to say “Hello World!”
The code is attached. Hopefully adequately commented. ‘Twas an interesting experience; I am not the world’s greatest programmer. If someone can profit, and wants to use this, have at it.
And again, thanks, pete, and Good On Ya, Mate!!!
(Spent 2 years in Perth, 1962-64. Loved the place. )

Bob Chadwick W1MTX (ex VK6CH)
Palm Bay, Florida USA
 

Willie...

New Member
I know this thread is a little old, but I was searching for a post *I* made years ago, asking about sending parallel data out of a PICAXE port. I found this, and plan to use it with a beautiful VFD unit I have. It works similarly to the common LCD protocol, but with some differences. I can take this code and tweak it, and hopefully get something meaningful onto that display. :) It turns out, this model of display was discontinued by the manufacturer a number of years ago... and so the pulled the documentation from their site! :( Thankfully, I got a reply to my e-mail to them, from one of their staff. He sent me the docs. :) I bought some PICAXE chips, because I used them a few years ago for a former employer. I've done some tinkering with the Arduino as well, but I'm struggling to get the C++ programming. BASIC is what I've used since 1977! (LONG TIME!) So I love the PICAXE! I can get my ideas into the chip MUCH more easily, and they WORK! :)
 

Willie...

New Member
Just a little update... turns out, that beautiful VFD is bad. :'( Oh well. The Code worked perfectly on an LCD I have, so I know that the Code, PICAXE, and wiring were all correct. The only thing left to do with that display is wire up a 5V supply, and put it into a box as a night light. (WHAT? You say!) It powers-up, and is locked into self-test mode. Even after several e-mail exchanges with a Tech at the manufacturer, we could NOT get that display out of self-test mode. So, it will be an interesting night light... because I truly hate to toss it. I love the PICAXE! :)
Now, I used this code on a 30+ year old LCD I had in my parts bins. Still works! :)
 

Attachments

Last edited:
Top