A PIC Serial LCD Project

This project shows you how to create a serial LCD module that you can drive from any serial RS232 interface.

You may be asking yourself why is this project using RS232 when computers are no longer even produced with a serial port as standard? 

There are three reasons:

  1. Most microcontrollers come with a UART built-in as a hardware module.
  2. RS232 can be setup with 2 signal wires and one ground connection.
  3. RS232 can be operated over long distance.

The last point means that signal transmission can be made fairly error free and robust (although you can achieve higher data rates and lower error rates by using the full RS232 spec). However it is probably better to move to a multi-drop interface such as RS485.

Since the hardware module is built in it becomes super-easy to use the internal UART which can use interrupts allowing fast and transparent operation.

The only problem now becomes what to do about the interface in the PC and you either buy an RS232 to USB adaptor cable that presents an RS232 interface as a COM port in the usual way at the PC but allows it to be plugged into a USB port or you can use a Digital to Serial USB converter. This last one does away with RS232 signals altogether and instead provides digital RX/TX signals to plug straight into the microcontroller i.e. you miss out the MAX232 chip. Ultimately both work fine and both look the same at the PC side.

Here is some more information on Serial RS232 to USB adaptors.

Project Design

The design here uses a pure ASCII command set so you can control it easily from a terminal program such as Tera Term (download from web = free).  

There are no 'odd' command sequences such as 0xef to define a command - you can type all commands at the terminal interface making it very easy to use i.e. this is a purely text based control system.

serial lcd block diagram

If you want to use it as a debugging terminal for your PIC projects then it makes sense to remove the level translator and just use the  0-5V input otherwise you would end up having two level translators for no real reason!

Note: Using it like this you will need to invert the RS232 output data so you either need an inverter chip if driven from the built in USART or you can drive it using a software USART (The transmitter part anyway) since you will have full control over the output signal.

Serial LCD Specification

Baud Rate 9600
Crystal 20Mhz -You can use  a lower value xtal but must re-compile the files and set the clock value into the MikroC chip settings.

Serial LCD Project Details

Serial LCD Project
Compiler Mikroelectronika MikroC compiler Free!
Target 16F877A (retargetable to other PICs that have enough pins and a built in USART).
Software level Easy.
Software notes Uses unget_char to reverse getchar action.
Hardware level easy.
Hardware notes No special notes.
Project version 1.01
Project files Enter your details to get the Download Link
and get the microcontroller newsletter:

(Your email is safe it will never be sold or rented).
You will get All the C source code and hex file.

Note: Check your email for the project code download link.

You can recompile the serial LCD files if you want examine code operation (using the built in simulator) or change the source code. Note the hex file is contained in the download.

Serial LCD Command set

All commands are prefixed with the hash character '#'.  In all cases except #X and #Y the single character following the '#' causes a command to execute.  For #X and #Y the decimal digits following (up to 2 digits) specify a position on the display.

Note: for #X and #Y the top left position is at 0,0.

Serial LCD Command Set list

You can use upper or lower case commands:

Serial LCD Commands
#C or #c Clear screen
#H or #h Cursor Home
#L or #l Cursor Left
#R or #r Cursor Right
#U or #u Cursor Underline mode
#B or #b Cursor Block mode
#I or #i Cursor Invisible
#F or #f Display OF
#O or #o Display On
#Xnn or #xnn Cursor X position (left nn=0)
#Ynn or #ynn Cursor Y position (top nn=0)
#> or #. Scroll display right (hash dot as easier to type!)
#< or #, Scroll display left (hash commaas easier to type!)
## Display a '#' character.

To clear the display you would type:


To set the cursor to block mode type:


X and Y commands

There must be at least two digits following the  #X or #Y command unless the following command is not a digit.   All this means is that you can finish an X or Y commands by typing a letter - if you type a digit the parser won't know if it is a digit to display or a digit to specify the position.

Here is a cursor positioning example command sequence:

#H Home Sets cursor position to (0,0) - top left.
#X3JFM < Set X and print Sets the X position to 3 and prints JFM
(Note the cursor is only moved once the J is entered).

You can also use the longer command:


It does exactly the same thing but the cursor is immediately moved after the '00' since the command parser knows that it is the end of the X cursor position command as it only accepts 2 digits.

These  commands are valid:

Command Result
#X10234 Cursor x position is set to 10 and 234 is displayed.
#Y1ABC Cursor y position is set to 1 and ABC is displayed.
#Y01ABC Same as above.
#X3HI Cursor x position is set to 3 and HI is displayed..
#X03HI Same as above.
#Y0BYE Cursor y position is set to 0 and BYE is displayed.

Text entry

If you enter any other ASCII text other than the '#' character then it is displayed on the LCD and the cursor is advanced to the right.

Note: to display a '#' character enter it twice '##'.

Serial LCD Hardware

Serial port lcd display (RS232  to LCD) circuit diagram
(click to open pdf)

serial lcd circuit

The circuit simply consists of a PIC micro, ICSP interface, an RS232 level translator and an HD44780 LCD.

Serial LCD display Software

The software is contained in two files (note there are many more created by the compiler):


bit.h contains bit manipulation macros.

Project Files


Output files:


For a tutorial on compiling these files click here.


Initially a scrolling message is displayed using show_intro.  When  a serial input is detected the main program starts.  All keys are now either text entry or commands.

An infinite loop keeps checking for key input. If the key is a hash symbol then the command is fetched using:


Otherwise the key value is displayed on the LCD at the current cursor position.

Note: the use of x and y addresses (&x,&y) to pass the variable address through to the called functions so that values of x and y in main() are updated (using pointers in the called functions).

get_prefix_and_execute_command calls execute_command which gets another key from the UART (or waits for one).  If it matches a valid command then the appropriate code is executed to control the LCD.  If not then UART1_unget_char is used to push the key back.

The most interesting commands in execute_command are #X and #Y which use get_and_Set_X and  get_and_Set_Y, again using pointers (this time the address & de-reference is not used as px is a pointer that returns its address when invoked).

These functions both use get_2dig_num which gets more characters expecting digits - if it does not get them it pushes the key back again using UART1_unget_char.

UART1_get_char, UART1_unget_char

These complementary functions are used in parsers (this program is a very small parser) where you need to look at the next character of the input to see if you want to continue. If you don't i.e. its not the character you were expecting then you use UART1_unget_char to put the current character into memory.

The function UART1_get_char always checks this memory first before getting a character from its normal input so the system works well - but you can only do one unget-char at a time.  For more you would need an array of unget storage etc.

The routines let you avoid complicated look ahead algorithms or indexing - you can concentrate on the current character without knowing where an index is.  For a bigger parser you work with complete words.


Have your say about what you just read! Leave me a comment in the box below.

Don’t see the comments box? Log in to your Facebook account, give Facebook consent, then return to this page and refresh it.

Privacy Policy | Contact | About Me

Site Map | Terms of Use