Interfacing 16X2 LCD With LPC2148 Tutorial
Interfacing 16X2 LCD With LPC2148 Tutorial
News Reviews Guides & Tutorials Embedded Previews & Unboxing More
Email Address
Subscribe
Introduction GOOGLE+
Interfacing a 16X2 or 16X4 LCD module with a 3.3V MCU is not same as interfacing with MCUs like
AVR which operate on 5Volts. As per request by some of the readers of previous articles on lpc2148
this article is on Interfacing a 5V LCD Module with LPC2148 MCU and in general for any ARM or 3.3V
MCU .
Whats next? : A simple Library for LCD interfacing with LPC214x and LPC176x MCUs. And more
tutorials on Timer , PWM , UART .. for lpc214x , lpc176x.
For this article I’ve used the readily available Chinese 16X2 LCD Module : JHD-162A. The Data sheet
for JHD-162A 16X2 LCD Module is located at :
http://www.egochina.net.cn/eBay/Download/JHD162A.pdf I would strongly suggest that you keep
OCFreaks!
that datasheet open when reading this article to avoid any sort of confusion.
google.com/+Ocfreaks
http://www.ocfreaks.com/interfacing-16x2-lcd-with-lpc2148-tutorial/ 1/12
29/3/2017 Interfacing 16X2 LCD with LPC2148 tutorial
1) Instruction Mode : Used for initializing and con guring LCD before we can use it & during
operation.
2) Data Mode : Displays the respective characters for codes supplied to it via Data Pins.
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 speci cally the it is
executed at the falling edge of the pulse.
If you want to know the fundamentals and internal operation of LCD Modules I would recommend
visiting these links :
http://lcd-linux.sourceforge.net/pdfdocs/lcd1.pdf
http://lcd-linux.sourceforge.net/pdfdocs/lcd2.pdf
http://www.8051projects.net/lcd-interfacing/ (Covers a lot of basics .. I found it really helpful.)
Some of the bu ers / level shifters than can be used are : SN74AHC244N , SN74AC241N ,
http://www.ocfreaks.com/interfacing-16x2-lcd-with-lpc2148-tutorial/ 2/12
29/3/2017 Interfacing 16X2 LCD with LPC2148 tutorial
Some of the bu ers / level shifters than can be used are : SN74AHC244N , SN74AC241N ,
CD74AC244E , CD4050B , etc.. out of which CD4050B is readily available. I purchased a few HCF4050
which is same as CD4050B except it is manufactured by ST Microelectronics and not Texas
Instruments.
HCF4050B is a non-inverting Hex Bu er. In our case we’ll be needing 2 of them at minimum since we
are going to use 8+2=10 pins from MCU which need to be shifted to 5Volts. There are going to be 8
Data pins and 2 control pins connected from MCU to the LCD Module using 2x HCF4050B.
NOTE : As far as possible use the 1st eight consecutive pins(at any cost!) from any port of the
MCU as Data Pins which will make sending character data or commands(Instructions) to LCD
very easy. For e.g. in our case we will use P0.0 to P0.7 as data pins and P1.16 as RS pin and
P1.17 as Enable pin.
Connections from lpc214x to LCD module will be as shown below. I’ve also made a PCB for the
schematic if bread-board is not your cup of tea.(Frankly , since I was running out of time I did it
using a bread-board. If some one is having any problems with PCB please let me know.)
http://www.ocfreaks.com/interfacing-16x2-lcd-with-lpc2148-tutorial/ 3/12
29/3/2017 Interfacing 16X2 LCD with LPC2148 tutorial
Download links to PCB pdf and Eagle 6.2+ (Schematic+Board) Design Files:
1) lcd_interface_arm_mcu_PCB-pdf.rar
2) lcd_interface_arm_mcu-EAGLE-6.2+design- les.rar
NOTE : You need to connect the ‘GND’ from MCU Board to ‘LCD’s GND’ else its not gonna work.
Diode D1 and Decoupling Capacitors C1 & C2 are optional. D1 can be replaced by a short and
C1,C2 can be ignored.
The 1st thing required for this is that RS must be held LOW and Enable also LOW in the beginning.
Now we must supply some commands using the Data Pins to LCD. But this command wont be
executed until we supply a pulse to Enable Pin. After supplying the command we make enable High
and then Low after a short delay(i.e a Pulse) and the command is executed.
Codes for various instructions can be obtained from below table : (Refer to page 12 of the
Datasheet)
http://www.ocfreaks.com/interfacing-16x2-lcd-with-lpc2148-tutorial/ 4/12
29/3/2017 Interfacing 16X2 LCD with LPC2148 tutorial
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.
After Initializing the LCD you would see a Cursor Blinking at in 1st column at row 1 :
http://www.ocfreaks.com/interfacing-16x2-lcd-with-lpc2148-tutorial/ 5/12
29/3/2017 Interfacing 16X2 LCD with LPC2148 tutorial
Hence to print a character on LCD we just need to apply the 8bit ASCII code to Data pins. This can
be done easily by type casting the character into an integer (which is done automatically by the
compiler – but we are doing it here explicitly). Refer to Page 14 of datasheet for font table.
Now , after printing 16 characters you might wanna print more characters in 2nd Row. This is done
by entering into Instruction Mode by holding RS=LOW and giving command 0xC0 which repositions
the cursor at 2nd Row & 1st column. Needless to say that we need to again give a Pulse on Enable
pin to process it. After that we put RS to high and get back in Data mode.
Note on Repositioning the Cursor : As we have seen , the command for repositioning the
cursor at home is 0x80. Think of 0x80 as the base address of Display Data Ram(DDRAM).
Hence 0x80 will set cursor at 1st Row, 1st Column. If you add 0x01 to 0x80 the cursor will go
to 2nd column in 1st row. Likewise if you add 0x0F to 0x80 you’ll end up at 1st row , last
column. Similar to this the base address for 2nd Row is 0x40 and not 0x10! 0x10 is the base
address of 3rd row and 0x50 is base address for 4th row in the case of 16×4 LCD Modules. So
to position the cursor at 2nd row, 1st column we must add 0x40 to 0x80 which gives
0x80+0x40=0xC0. Hence after giving command ‘0xC0’ cursor comes down to 2nd row & 1st col.
More on DDRAM and CGROM @ http://www.8051projects.net/lcd-interfacing/basics.php
/*
(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>
http://www.ocfreaks.com/interfacing-16x2-lcd-with-lpc2148-tutorial/ 7/12
29/3/2017 Interfacing 16X2 LCD with LPC2148 tutorial
#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)
{
http://www.ocfreaks.com/interfacing-16x2-lcd-with-lpc2148-tutorial/ 8/12
29/3/2017 Interfacing 16X2 LCD with LPC2148 tutorial
{
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 ashing any of the above code to MCU (Successfully Tested on Lpc2148 and Lpc1768) :
http://www.ocfreaks.com/interfacing-16x2-lcd-with-lpc2148-tutorial/ 9/12
29/3/2017 Interfacing 16X2 LCD with LPC2148 tutorial
Share this:
Share
Previous Next
Kingston HyperX blu PC3-12800 (1600MHz) Know your GPU
8GB Kit review
Umang Gajera
18 Comments OCFreaks!
1 Login
http://www.ocfreaks.com/interfacing-16x2-lcd-with-lpc2148-tutorial/ 10/12
29/3/2017 Interfacing 16X2 LCD with LPC2148 tutorial
ADC block is not! I will update the post with a clarification. Thanks for pointing it out.
△ ▽ • Reply • Share ›
this is the tutorial link of oc freaks lcd 16X2 interface program with ARM lpc2148 , i follow this program
...
first i followed the oc freaks program for interfacing of lcd 16X2 with ARM lpc2148. i can understand
the coding and successfully execute the program in my ARM lpc2148 development board. what the
program in oc freak tutorial followed is they using port 1 (RS = P1.16 & EN = P1.17) for control pins
and port 0 for data pins( D0 t0 D7 ..... P0.0 to P0.7 respectively ) but what i am trying to implement is i
want to configure both data pins and control pin in port one itself( port 0) . i wrote program for that task
but what the problem i faced is , the command is clearly executing , i saw the cursor in the LCD
display but the letter are displayed like junk values.
see more
△ ▽ • Reply • Share ›
-Regards
△ ▽ • Reply • Share ›
Thanks.
△ ▽ • Reply • Share ›
http://www.ocfreaks.com/interfacing-16x2-lcd-with-lpc2148-tutorial/ 11/12
29/3/2017 Interfacing 16X2 LCD with LPC2148 tutorial
-Regards
△ ▽ • Reply • Share ›
Also is it true that Fast Interrupt requests will work only on those MCUs having speed > 60MHz.
Thank you.
△ ▽ • Reply • Share ›
http://www.ocfreaks.com/interfacing-16x2-lcd-with-lpc2148-tutorial/ 12/12