16X2 LCD Basics:: LCD Pin Description: Pin No Symbol I/O Description
16X2 LCD Basics:: LCD Pin Description: Pin No Symbol I/O Description
16X2 LCD Basics:: LCD Pin Description: Pin No Symbol I/O Description
The Chinese LCD used here is JHD162A. It has a KS0066U/ HD44780U controller. It has a 16 pin interface device
which consists of 2 rows with 16 characters each. The operating voltage is 5V. Also, it has an LED backlight. There
are 2 modes of operation:
1) Instruction Mode: To initialize and configure the LCD before its use
2) Data Mode: Displays the characters for the respective codes that are given to the LCD via Data Pins.
1 VSS - Ground
2 VCC +5V
6 E Input/Output Enable
Once you have verified all the connections from MCU to HFC4050 to LCD Module, we can go ahead to display text on
the LCD. But first, the LCD needs to be initialized properly. (According to the Datasheet) Before initializing the LCD,
you will need to wait for a minimum time of about 15 milliseconds after the input voltage supply is stable and greater
than 4.5 Volts.
The first step is to make sure that the RS and Enable are held LOW. Next is to input some commands to the LCD
using the Data pins. These commands will not be executed until a pulse is supplied to the Enable pin. After supplying
the command with a pulse, Enable has to be made High and then Low after a short delay. Then, the command is
executed.
The LCD can be configured in 4-bit mode by sending the appropriate command which is called “Function set” to it.
The Function set is a hexadecimal command of the LCD MPU unit, which selects working modes of the LCD. The
“Function Set” is mentioned in following table:
Description:
According to the table, the value of Function Set for 4 –bit mode will be 0010 0000(0x20) because DL=0. The value
“Function Set” for the LCD configuration 2 line (N=1), 5X7 dots (F=0) and 4-bit (DL=0) mode will be 0010
1000(0x28).
When the power supply is given to the LCD, it remains in 8-bit mode. Now, if 0x20 is sent, lower nibble will not be
received by LCD because four data lines (D4-D7) are connected, so 0x02 is sent instead of 0x20. For more details
about the LCD interfacing refer these Links.
In this section, we will start creating a project in Keil MDK we have already installed Keil µVision and Co-MDK Plug-in
+ CoLinkEx Drivers required for the CoLinkEx programming adapter. You can start by downloading the project files
and kick start your practical experiment.
Code.rar
Code Description:
These functions explained are included by making a LCD library and included in the coding files.
Lcd_DataWrite ()
1) Instruction Mode : Used for initializing and configuring LCD before we can use it & during
operation.
2) Data Mode : Displays the respective characters for codes supplied to it via Data Pins.
Standard Pinout is as follows :
To keep things simple lets group the pins into 3 :
1) Power Pins : Pin 1,2,3,15,16
2) Control Pins : Pin 4,5,6
3) Data Pins : Pin 7 to 14
Now lets see some of the important pins before we actually start writing programs for LCD:
Contrast Voltage (VEE) : Instead of using a trim pot just connect a 1K resistor to VEE in
series and ground it. That gives the best contrast of what I’ve seen.
RS – short for Register select (Control Pin) : Used to switch been Instruction and Data
Mode. RS = High for Instruction Mode and RS = Low for Data mode.
R/W – Read or Write (Control Pin): R/W = High for Read Mode and R/W = Low for Write.
Since we are going to use Write Mode only we will permanently ground it using a pull-down
resistor of 4.7K Ohms. Caution : If you are planning to use Read Mode with 3.3V MCUs
you’ll need a Bi-directional level shifter which can shift 5V to 3.3V and Vice-Versa.
Enable (Control Pin) : This is similar to a trigger pin. Each Data/Instruction is executed by
the LCD module only when a pulse is applied to Enable pin. More specifically the it is
executed at the falling edge of the pulse.
For beginners we are only interested in following commands (which are also executed in given order
during initialization):
1. Function Set
2. Display Switch
3. Input Set
4. Screen Clear Command
5. DDRAM AD Set – Resposition Cursor Command
In our case we are going to use 8Bit Mode with 2Rows and 5×10 Font style which gives
Function set as 0x3C.
Next we issue Display On , Cursor On , Blink On which gives Display Switch as 0x0F.
Next we select Increment Mode which gives Input Set as 0x06.
Now we clear the screen and set cursor at Home which gives Screen Clear as 0x01.
Also the command to reposition the cursor at Home at anytime is 0x80 and to reposition it at
the 1st column of the second row is 0xC0.
To cut-short or in simple words: We need to supply 5 commands in given order to the Data Pins
with a small amount of delay in between to initialize the LCD properly. These commands are : 0x3C ,
0x0F , 0x06 , 0x01 , 0x80(actually not required). Now since we have used the the 1st eight pins of
port 0 on lpc214x we can directly assign these values to the IO0PIN register. Note that Bit 0 i.e LSB
in IO0PIN is towards extreme right and the bit number increases as we move towards the left
approaching the MSB. Also since we have connected P0.0 to Data Bit 0 pin , P0.1 to Data bit 1 and
so on … we have a one to one consecutive mapping between them MCU pins and LCD Data pins.
NOTE: During Initialization , issuing 0x80 command to reposition the cursor at home will be of no
use since it would already be at Home after issuing Screen Clear Command. Also we need to
Supply a Pulse to Enable after issuing each command and wait for a short while for the LCD
controller to process it. Datasheet says a delay of 40us is required at minimum. But even a delay of
1ms wont hurt us to be on the safer side.
1. After LCD Module is powered on and MCU boots wait for 20ms (Specifically >15ms)
2. Now make RS and Enable LOW making sure that R/W is permanently grounded.
3. Issue Function set command – 0x3C and Pulse Enable (wait for >40us after pulsing).
4. Issue Display Switch – 0x0F and Pulse Enable (wait for >40us after pulsing).
5. Issue Input Set – 0x06 and Pulse Enable (wait for >40us after pulsing).
6. Issue Screen Clear – 0x01 and Pulse Enable (wait for >1.64ms after pulsing).
7. Issue DDRAM AD Set – 0x80 and Pulse Enable (wait for >40us after pulsing).
Now LCD is ready for Printing!
After Initializing the LCD you would see a Cursor Blinking at in 1st column at row 1 :
/*
(C) OCFreaks! | Umang Gajera 2012-13.
More Embedded tutorials @ www.ocfreaks.com/cat/embedded
>>Program for Interfacing 16X2 LCD Module with LPC2148
*/
#include <lpc214x.h>
/*
Connections from LPC2148 to LCD Module:
P0.0 to P0.7 used as Data bits.
P1.16 connected to pin4 i.e. RS - Command / Data
P1.17 connected to pin6 i.e. E - Enable
Pin5 of LCD Module i.e. 'R/W' connected to ground
*/
void initLCD(void);
void enable(void);
void LCD_WriteChar(char c);
void LCD_WriteString(char * string);
void LCD_Cmd(unsigned int cmd);
void delay(void);
int main(void)
{
initLCD(); //LCD Now intialized and ready to Print!
LCD_WriteString(".: Welcome to :.");
LCD_Cmd(0x80 + 0x40); //Come to 2nd Row
LCD_WriteString("www.OCFreaks.com");
while(1); // Loop forever
return 0; //This won't execute :P
}
void initLCD(void)
{
IO0DIR = 0xFF; //P0.0 to P0.7 configured as Output - Using 8 Bit mode
IO1DIR |= (1<<16) | (1<<17); //P1.16 and P1.17 configured as Output -
Control Pins
IO0PIN = 0x0; //Reset Port0 to 0.
IO1PIN = 0x0; //Reset Port1 to 0 - Which also makes RS and Enable LOW.
void enable(void)
{
delay();
IO1PIN |= (1<<17);//Enable=High
delay();
IO1PIN &= ~(1<<17);//Enable=Low
delay();
}
void LCD_WriteChar(char c)
{
IO1PIN |= (1<<16); //Switch to Data Mode
IO0PIN = (int) c; //Supply Character Code
enable(); //Pulse Enable to process it
}
void delay(void)
{
int i=0,x=0;
for(i=0; i<19999; i++){ x++; }
}
/*
(C) OCFreaks! | Umang Gajera 2012-13.
More Embedded tutorials @ www.ocfreaks.com/cat/embedded
>>Program2 for Interfacing 16X2 LCD Module with LPC2148
>>using Timer0 and CPU @ 60Mhz
*/
#include <lpc214x.h>
/*
XTAL Freq=12 Mhz , CCLK=60Mhz , PCLK=60Mhz
Using common delay of 2ms for all operations
void initLCD(void);
void enable(void);
void LCD_WriteChar(char c);
void LCD_WriteString(char * string);
void LCD_Cmd(unsigned int cmd);
void delayMS(unsigned int milliseconds);
void setupPLL0(void);
void feedSeq(void);
void connectPLL0(void);
int main(void)
{
setupPLL0();
feedSeq(); //sequence for locking PLL to desired freq.
connectPLL0();
feedSeq(); //sequence for connecting the PLL as system clock
void initLCD(void)
{
IO0DIR = 0xFF; //P0.0 to P0.7 configured as Output - Using 8 Bit mode
IO1DIR |= (1<<16) | (1<<17); //P1.16 and P1.17 configured as Output - Control
Pins
IO0PIN = 0x0; //Reset Port0 to 0.
IO1PIN = 0x0; //Reset Port1 to 0 - Which also makes RS and Enable LOW.
void enable(void)
{
//Using common delay of 2ms
delayMS(2);
IO1PIN |= (1<<17);//Enable=High
delayMS(2);
IO1PIN &= ~(1<<17);//Enable=Low
delayMS(2);
}
void LCD_WriteChar(char c)
{
IO1PIN |= (1<<16); //Switch to Data Mode
IO0PIN = (int) c; //Supply Character Code
enable(); //Pulse Enable to process it
}
T0IR = 0;
T0CTCR = 0;
T0PR = 60000; //60000 clock cycles @60Mhz = 1 mS
T0PC = 0;
T0TC = 0;
T0TCR = 0x01; //enable timer
void setupPLL0(void)
{
PLL0CON = 0x01; // PPLE=1 & PPLC=0 so it will be enabled
// but not connected after FEED sequence
PLL0CFG = 0x24; // set the multipler to 5 (i.e actually 4)
// i.e 12x5 = 60 Mhz (M - 1 = 4)!!!
// Set P=2 since we want FCCO in range!!!
// So , Assign PSEL =01 in PLL0CFG as per the table.
}
void feedSeq(void)
{
PLL0FEED = 0xAA;
PLL0FEED = 0x55;
}
void connectPLL0(void)
{
// check whether PLL has locked on to the desired freq by reading the lock
bit
// in the PPL0STAT register
Output after flashing any of the above code to MCU (Successfully Tested on Lpc2148 and
Lpc1768) :
Download Links to Source Code using KEIL UV4 Project IDE :
1) Program #1 : OCFreaks.com_LPC2148_LCD_Interfacing.rar
2) Program #2 : OCFreaks.com_LPC2148_LCD_Interfacing_precise.rar
Registers
The two 8-bit registers in the HD44780U 16 x 2 character LCD display are
Instruction Register (IR)
Instruction functions are written from the micro-controller to this register for Display Data RAM
(DDRAM) and Character Generator RAM (CGRAM).
Data Register (IR)
This register temporarily holds the data to be written into the DDRAM or the CGRAM from the
micro-controller. It also temporarily holds the data that is being read from the two registers.
Programming
Interfacing the LCD module with any micro-controller is very easy. It involves
only a few functions that instruct the LCD to perform specific tasks and read or
write data in the LCD.
Here, we will be doing an 8-bit interfacing with the LPC1768 micro-controller
and only perform write operation on the LCD.
DEFINITIONS:
Default
1 //***********************************************************************************************
******
2
// Default DATA PORT in OpenLab is PORTB. P0[16:23]
3
// Default CONTROL PORT in OpenLab is PORTC P1[16:23]
4
//***********************************************************************************************
5
******
6
#define DATA_BUS LPC_GPIO0->FIODIR
7
#define CONTROL_BUS LPC_GPIO1->FIODIR
8
//***********************************************************************************************
9 ******
1
0
//***********************************************************************************************
1 ******
1
// Control Port definitions
1
//***********************************************************************************************
2
******
1
#define CONTROL_SET LPC_GPIO1->FIOSET
3
1 #define RW 17
5
#define EN 16
1
//***********************************************************************************************
6
******
1
7
//***********************************************************************************************
1
******
8
******
2
0 #define DATA_SET LPC_GPIO0->FIOSET
#define DATA2 18
2
3 #define DATA3 19
2
4 #define DATA4 20
2 #define DATA5 21
5
#define DATA6 22
2
#define DATA7 23
6
//***********************************************************************************************
2
******
7
2
8 //***********************************************************************************************
******
2
9 //Control and Data Mask
3 //***********************************************************************************************
0 ******
3
4
3
5
3
6
3
7
3
8
3
9
PORT INITIALIZATION: The directions of the three instruction register pins and
the 8 data register pins must be set as output.
We have defined mask bits to achieve this.
Default
1 void INIT_PORTS()
2{
3 DATA_BUS = DATA_MASK;
4 CONTROL_BUS = CONTROL_MASK;
5 INIT_LCD();
6}
2{
3 SEND_BITWISE(cmd);
4 CONTROL_CLEAR = (1<<RS)|(1<<RW);
5 CONTROL_SET = (1<<EN);
6 delay_ms(1);
7 CONTROL_CLEAR = (1<<EN);
8}
COMMANDS: A basic set of commands that must be written to the LCD for
initialization are as follows. This will set the LCD in 8 bit mode. It can access
both the lines and display matrix is 5*7.
Default
1 void INIT_LCD()
2{
8}
2{
3 SEND_BITWISE(data);
4 CONTROL_CLEAR = (1<<RS)|(1<<RW);
5 CONTROL_SET = (1<<RS)|(1<<EN);
6 delay_ms(1);
7 CONTROL_CLEAR = (1<<EN);
8 CONTROL_CLEAR = (1<<RS);
9}
The character LCD can be used to display sensor values, count values or
display any kind of texts.
Another write function is created in order to send a string of data to the lcd
controller.
Default
1 void SEND_STRING_DATA(char *str)
2{
3 while(*str!='\0')
4 {
5 SEND_CHAR_DATA(*str);
6 str++;
7 }
8}
Summary
The above tutorial will guide you to interface an 16*2 Character LCD using a 32
bit LPC1768 ARM cortex M3 microcontroller. The sample code based on this
tutorial is available in the Code Library under the section ARM.
LCD Commands
HD44780 instruction set
Execution
Code
Description time**
Instruction RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
Read from
Reads data from CGRAM or
CGRAM or 1 1 read data 40uS
DDRAM.
DDRAM
Notes:
Bit names
Bit Settings
Clear Display
RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
=== === === === === === === === === ===
0 0 0 0 0 0 0 0 0 1
Clears all display and returns the cursor to the home position (Address 0).
Details
Writes space code (20h) into all DD RAM addresses. Sets address counter to DD
RAM location 0. Returns display to its original state if it was shifted. In other words,
the display disappears and the cursor or blink goes to the left edge of the display (the
first line if 2 lines are displayed). Sets entry mode I/D to 1 (Increment Mode). Entry
mode shift (S) bit remains unchanged.
Cursor Home
RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 0 0 0 0 1 *
Returns the cursor to the home position (Address 0). Returns display to its original
state if it was shifted.
Details
Sets the address counter to DD RAM location 0 in the address counter. Returns
display to its original state if it was shifted. DD RAM contents remain unchanged.
The cursor or blink goes to the left edge of the display (the first line if 2 lines are
displayed).
Details
Specifies whether to increment (I/D = 1) or decrement (I/D = 0) the address counter
after subsequent DD RAM read or write operations.
If S = 1 the display will be shifted to the left (if I/D = 1) or right (if I/D = 0) on
subsequent DD RAM write operations. This makes it looks as if the cursor stands still
and the display moves when each character is written to the DD RAM. if S = 0 the
display will not shift on subsequent DD RAM write operations.
Display ON/OFF
RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
=== === === === === === === === === ===
0 0 0 0 0 0 1 D C B
Details
D: The display is ON when D = 1 and OFF when D = 0. The DD RAM contents
remain unchanged.
Function Set
RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
=== === === === === === === === === ===
0 0 0 0 1 DL N F * *
Sets interface data length (DL), number of display lines (N) and character font (F)
Details
This command should be issued only after automatic power-on initialization has
occurred, or as part of the module initialization sequence.
DL: Sets interface data length
When the 4 bit length is selected, data must be sent or received in pairs of 4-
bits each. The most-significant 4 bits are sent or received first.
Sets the CG RAM address. Subsequent read or write operations refer to the CG RAM.
Details
Sets the specified value (AAAAAA) into the address counter. Subsequent read or
write operations transfer data from, or to, the character generator RAM.
Sets the DD RAM address. Subsequent read or writes refer to the DD RAM.
Details
Sets the specified value (AAAAAAA) into the address counter. Subsequent read or
write operations transfer data from, or to, the display RAM. Note: Adjacent display
RAM locations do not necessarily refer to adjacent display positions.
Reads the state of the busy flag (BF) and the contents of the address counter.
Details
Reads the busy flag (BF) that indicates the state of the LCD module. BF = 1 indicates
that the module is busy processing the previous command. BF = 0 indicates that the
module is ready to perform another command.
The value of the address counter is also returned. The same address counter is used for
both CG and DD RAM transfers.
This command can be issued at any time. It is the only command which the LCD
module will accept while a previous command is still being processed.
Details
Writes a byte (DDDDDDDD) to the CG or the DD RAM. The destination (CG RAM
or DD RAM) is determined by the most recent `Set RAM Address' command. The
location to which the byte will be written is the current value of the address counter.
After the byte is written the address counter is automatically incremented or
decremented according to the entry mode. The entry mode also determines whether or
not the display will shift.