The 16×2 character Liquid Crystal Display (LCD) is a basic display module and it can display 16 characters each in two rows. The individual characters are displayed using a 5×7 dot matrix. The character LCD Module is used to display Alphanumeric Characters and it supports all the ASCII characters. The HD44780 LCD controller is used commonly in this type of LCD. The LCD module has lower power consumption and is compact. We will discuss more details about character LCD modules and character LCD interfacing with PIC16F877A in this tutorial.
The LCD Module will have an 8-bit wide Databus D0-D7. The data bus is used to send data or command to the LCD module. The LCD module can also be operated in 4-bit mode and in this mode we can send data/cmd as 4-bit chunks. The 4-bit mode utilizes only four data pins.
The two registers present in the LCD module are data register and command register The command which has to be executed is written to the command register and the data which needs to be displayed can be written to the data register. The Value of the RS pin selects between data and command register. the RS=0 writes the arrived data to command register and RS=1 writes the arrived data to the data register. The R/W signal is used to read or write to the LCD. The active-low on this pin indicates write operation and a high indicates a read. Here we are using the LCD as the output device and we write to the LCD making this pin as low and it can also be used to read the busy flag. We have to write a high to low pulse on the enable pin to trigger the LCD. The enable trigger is sent after placing the data on the data port and it will latch the data to the corresponding register according to RS signal value. Interfacing LCD in firmware involves mainly writing into the LCD different commands for its configuration and data that is to be displayed.
The LCD Module has a set of instructions to perform predefined tasks. The commonly used LCD commands and their respective functions are given below.
[fusion_table fusion_table_type=”1″ fusion_table_columns=”2″ hide_on_mobile=”small-visibility,medium-visibility,large-visibility” class=”” id=”” animation_type=”” animation_direction=”left” animation_speed=”0.3″ animation_offset=””]
Hex Code | Command to LCD instruction Register |
---|---|
1 | Clear display screen |
2 | Return home |
4 | Decrement cursor (shift cursor to left) |
6 | Increment cursor (shift cursor to right) |
5 | Shift display right |
7 | Shift display left |
8 | Display off, cursor off |
0A | Display off, cursor on |
0C | Display on, cursor off |
0E | Display on, cursor blinking |
0F | Display on, cursor blinking |
10 | Shift cursor position to left |
14 | Shift cursor position to the right |
18 | Shift the entire display to the left |
1C | Shift the entire display to the right |
80 | Force cursor to the beginning ( 1st line) |
C0 | Force cursor to the beginning ( 2nd line) |
38 | 2 lines and 5×7 matrix |
[/fusion_table]
We will consider the LCD module in the 8-bit mode and write the data to it. The LCD commands need to be sent prior to the data. The commands perform the predefined tasks such as initialization, shifting the cursor, clearing the screen, etc. we have to create the functions for sending command and writing the data. The sequence of operations that needs to be performed while creating the command and the data function are discussed below.
The xc.h header file is included in the beginning and the clock frequency is defined for __delay_ms() function
#define _XTAL_FREQ 20000000 #include <xc.h>
The macros are defined to create a simple readable format for the firmware. The PORTB is connected with 8 data pins of the LCD and is defined as the Data Port. TRISB register is defined as the Data Port direction register. The control pins of the LCD(RS, EN) are connected with PORTD so that TRISD is defined as Control port direction register.
#define DATA_PORT PORTB #define DATA_PORT_DIR TRISB #define CTRLPORT_DIR TRISC #define EN PORTCbits.RC0 #define RW PORTCbits.RC1 #define RS PORTCbits.RC2
We have to define a command function to send the appropriate commands to the LCD Module. The command register selected by setting logic low in the RS pin.
LCD_cmd(unsigned char command) { RS=0; RW=0; DATA_PORT=command; EN=1; __delay_ms(5); EN=0; }
Before the LCD can display any character it needs to be initialized. The initialization process of the module involves writing some initialization commands into the command register in the device. The previously defined command function is used to send the appropriate command to the LCD module.
void lcd_init() { CTRLPORT_DIR = 0x00; /* Direction of control port as Output */ DATA_PORT_DIR =0x00; /* Direction of data port as Output */ LCD_cmd(0x38); /* LCD command - 5x7 matrix */ LCD_cmd(0x80); /* LCD command - Force cursor to the bigining of first line */ LCD_cmd(0x0C); /* LCD command - Display ON, cursor OFF */ LCD_cmd(0x01); /* LCD command - Clear display */}
Sending data to the LCD module follows the same procedure as sending the commands except that the RS pin should be at high state to select the data register.
LCD_data(unsigned char data) { RS=1; RW=0; DATA_PORT=data; EN=1; __delay_ms(5); EN=0; }
We can create a string display function using the LCD_cmd function. The single character printing function is repeatedly called until the “\0” character.
void display(const char *p) // Function to display the string { while(*p!='\0') { LCD_cmd(*p); p++; } }
The list of pins which we have to interface with the controller apart from the supply line (VDD), Ground(VSS), and contrast adjust (VEE) are as follows
16*2 Character LCD is interfaced with PIC16F877A in 8-bit mode as shown in the figure. Similar way you can interface 16*2 Character LCD in 4-bit mode, and the difference is that in 4bit mode you will only have 4 data lines.
Below code is the example using the above functions. After initialization, the program prints an “Hello World” to the screen.
[fusion_global id=”18383″]