LCD 16×2 using I2C in LPC2148

In this tutorial, I am going to show you How to connect LCD using I2C with an ARM7 mcrocontroller. I am using LPC2148 but the process is same for other ARM7 devices. PCF8574 acts as an I2C extender and is being used to connect LCD with the LPC2148.

First of all let’s see the connections between the PCF8574 and the LCD.

As shown in the figure, connect the first pin of the PCF8574 to the VSS of the LCD, 2nd pin to the VCC and so on. The input pins of the PCF8574 i.e. SCL and SDA should be connected with the SCL and SDA of the microcontroller. LPC2148 do not have internal pull-ups so we need to connect external pull-up resistors (around 4k)  with the SCL and SDA pins. More connections are given below…

Data transmission via I2C require some steps to be followed. They are as follows:

Start -> Write Address -> Write data -> Stop to write data to the slave. I am going to cover only writing data to the slave and not reading from slave.

The following are the functions used during an I2C transmission:

void waitforsi (void)  // wait for interrupt to set
	while (!(I2C0CONSET & SI));  //while interrupt in not set /wait till SI goes 1

void i2c_send_start (void)
	I2C0CONSET = STA;  // set start bit
	waitforsi();  //wait for interrupt to set it will transmit previous condition

void i2c_write (unsigned char data)

	I2C0DAT = data;  // load data
	I2C0CONCLR = SI|STA|AA;  //clear interrupt, start, ack
	waitforsi ();  // wait for condition  to transmit

void i2c_send_stop (void)
	I2C0CONCLR = AA|SI;  // clear ack and interrupt
	I2C0CONSET = STO;  // send stop

void i2c_init (void)
	PINSEL0 = (1<<4)|(1<<6);  // for i2c line
	I2C0SCLH = 75;  // 15MHz/150 = 100000 speed i2c
	I2C0SCLL = 75;
	I2C0CONCLR = STA|STO|AA|SI;  // clear all bits
	I2C0CONSET = I2EN;  // enable bit set

The following are the functions used for writing data to the LCD:

void lcd_write_data (unsigned char data)
	unsigned char data_l, data_u;
	data_l = (data<<4)&0xf0;  //select lower nibble by moving it to the upper nibble position
	data_u = data&0xf0;  //select upper nibble

	i2c_write (address);
	i2c_write (data_u|0x0D);  //enable=1 and rs =1
	i2c_write (data_u|0x09);  //enable=0 and rs =1

	i2c_write (data_l|0x0D);  //enable =1 and rs =1
	i2c_write (data_l|0x09);  //enable=0 and rs =1


void lcd_send_string (char *data)
	while (*data) lcd_write_data (*data++);

void lcd_write_cmd (unsigned char cmd)
	unsigned char cmd_l, cmd_u;
	cmd_l = (cmd<<4)&0xf0;  //select lower nibble by moving it to the upper nibble position
	cmd_u = cmd&0xf0;  //selct upper nibble

	i2c_send_start ();
	i2c_write (address);
	i2c_write (cmd_u|0x0C);  //enable =1, rs =0
	i2c_write (cmd_u|0x08);  //enable =0, rs =0

	i2c_write (cmd_l|0x0C);  //enable =1, rs =0
	i2c_write (cmd_l|0x08);  //enable =0, rs =0

	i2c_send_stop ();

void lcd_init ()
 i2c_init ();
 lcd_write_cmd (0x02);
 lcd_write_cmd (0x28);
 lcd_write_cmd (0x0c);
 lcd_write_cmd (0x80);

The above functions are part of header files. The files are lcd_i2c.h for lcd related functions, i2c.h for i2c functions, pll.h for the PLL clock functions.

Copy all these header files to a location and add the path to the C/C++ in the project setting as shown in the picture below



You can see the “hello!” is printed on the display in the proteus. For more working, see the video below

Check out the VIDEO Below

Notify of
Oldest Most Voted
Inline Feedbacks
View all comments