Overview
The HD44780 alphanumeric display has been using for many years now. In early years, it is commonly found in some electronic and control system, laser printers, etc. At that time, interfacing this LCD with an 8-bit micro-controller and programming in Assembly language was common. This display controller uses the Motorola 6800 data bus with three control signals, Register Select (RS), Read/Write (R/W), and Enable (E). However it support a 4-bit data transfer mode that split the 8-bit data into higher nibble and lower nibble, in which the higher nibble sent and latched first.
![]() |
| A Blue Back LED 16x2 Character LCD |
![]() |
| A Blue Back LED 16x2 Character LCD |
Currently, this display controller still in used. It is very popular among students, engineer, hobbyists, and small electronic control projects. There are a lot of replacement controllers available at very low cost and riches in dimensions. Using this LCD with and Arduino is very popular due to its ready-to-use module and libraries. This display can be converted into a serial communication interface such as I2C or SPI.
PIC18F4550 and a 16x2 LCD Example
MikroC has a lot of hardware libraries even in free mode. We can follow its example programs in its reference manual. To get started, I repeat an example code in its Lcd Libary. There are some library functions that we need to know especially the LCD pins declaration.
Library Routines
The LCD pins declaration such as R/S, E, and D7:4 must be putted first at the head of C source code before these functions can be called. For more information please see its Help file in the compiler IDE.
Schematic
![]() |
| Schematic |
MikroC Source Code
- // LCD module connections
- sbit LCD_RS at RD2_bit;
- sbit LCD_EN at RD3_bit;
- sbit LCD_D4 at RD4_bit;
- sbit LCD_D5 at RD5_bit;
- sbit LCD_D6 at RD6_bit;
- sbit LCD_D7 at RD7_bit;
- sbit LCD_RS_Direction at TRISD2_bit;
- sbit LCD_EN_Direction at TRISD3_bit;
- sbit LCD_D4_Direction at TRISD4_bit;
- sbit LCD_D5_Direction at TRISD5_bit;
- sbit LCD_D6_Direction at TRISD6_bit;
- sbit LCD_D7_Direction at TRISD7_bit;
- // End LCD module connections
- char txt1[] = "mikroElektronika";
- char txt2[] = "EasyPIC6";
- char txt3[] = "Lcd4bit";
- char txt4[] = "example";
- char i; // Loop variable
- void Move_Delay() { // Function used for text moving
- Delay_ms(500); // You can change the moving speed here
- }
- void main(){
- Lcd_Init(); // Initialize LCD
- Lcd_Cmd(_LCD_CLEAR); // Clear display
- Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
- Lcd_Out(1,6,txt3); // Write text in first row
- Lcd_Out(2,6,txt4); // Write text in second row
- Delay_ms(2000);
- Lcd_Cmd(_LCD_CLEAR); // Clear display
- Lcd_Out(1,1,txt1); // Write text in first row
- Lcd_Out(2,5,txt2); // Write text in second row
- Delay_ms(2000);
- // Moving text
- for(i=0; i<4; i++) { // Move text to the right 4 times
- Lcd_Cmd(_LCD_SHIFT_RIGHT);
- Move_Delay();
- }
- while(1) { // Endless loop
- for(i=0; i<8; i++) { // Move text to the left 7 times
- Lcd_Cmd(_LCD_SHIFT_LEFT);
- Move_Delay();
- }
- for(i=0; i<8; i++) { // Move text to the right 7 times
- Lcd_Cmd(_LCD_SHIFT_RIGHT);
- Move_Delay();
- }
- }
- }
DIY PIC18F4550 Prototype Board
I tested this example on my DIY PIC18F4550 Prototype Board.
![]() |
| PIC18F4550 Prototype Board |
![]() |
| PIC18F4550 Prototype Board |
On-board Switches and LCD Example
In this example, when one of two on-board push buttons is pressed it will shows its state - Press or Released. The schematic is shown in the example above.
MikroC Source Code
- #define SW4 RB4_bit
- #define SW5 RB5_bit
- // LCD module connections
- sbit LCD_RS at RD2_bit;
- sbit LCD_EN at RD3_bit;
- sbit LCD_D4 at RD4_bit;
- sbit LCD_D5 at RD5_bit;
- sbit LCD_D6 at RD6_bit;
- sbit LCD_D7 at RD7_bit;
- sbit LCD_RS_Direction at TRISD2_bit;
- sbit LCD_EN_Direction at TRISD3_bit;
- sbit LCD_D4_Direction at TRISD4_bit;
- sbit LCD_D5_Direction at TRISD5_bit;
- sbit LCD_D6_Direction at TRISD6_bit;
- sbit LCD_D7_Direction at TRISD7_bit;
- // End LCD module connections
- void main(){
- /// PORTB AS INPUT
- PORTB = 0;
- LATB = 0;
- TRISB = (1<<5)|(1<<4);
-
- // ENABLE PORTB PULL-UP
- INTCON2 &=~(1<<7);
- // DISABLE ANALOG INPUTS
- ADCON1 = 0x0F;
-
- Lcd_Init(); // Initialize LCD
- Lcd_Cmd(_LCD_CLEAR); // Clear display
- Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
- Lcd_Out(1,1,"PIC18F4550 LCD");
- Lcd_out(2,1,"Buttons Example");
- Delay_ms(7000);
- Lcd_Cmd(_LCD_CLEAR); // Clear display
- Lcd_Out(1,1, "Press on SW4.");
- Lcd_Out(2,1, "Press on SW5.");
- while(1){
- if(SW4==0){
- Lcd_Out(1,1, "SW4 is Pressed.");
- while(SW4 == 0);
- Lcd_Out(1,1, "SW4 is Released.");
- }
- if(SW5==0){
- Lcd_Out(2,1, "SW5 is Pressed.");
- while(SW5 == 0);
- Lcd_Out(2,1, "SW5 is Released.");
- }
- }
- }
Example Pictures
I tested this example on my DIY PIC18F4550 Prototype Board.

My DIY PIC18F4550 Prototype Board
![]() |
| My DIY PIC18F4550 Prototype Board |
![]() |
| My DIY PIC18F4550 Prototype Board |


















.jpg)



