0% found this document useful (0 votes)
17 views6 pages

Lap 9 155

The report details the interfacing of a 16x2 LCD with an ATmega328P microcontroller using I2C communication, including tasks such as displaying messages with a blinking effect and measuring analog voltage via ADC. It compares UART, SPI, and I2C protocols, highlighting their respective advantages and use cases. The successful integration of these components demonstrates effective real-time monitoring and control in embedded systems.

Uploaded by

mefasihrehman
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views6 pages

Lap 9 155

The report details the interfacing of a 16x2 LCD with an ATmega328P microcontroller using I2C communication, including tasks such as displaying messages with a blinking effect and measuring analog voltage via ADC. It compares UART, SPI, and I2C protocols, highlighting their respective advantages and use cases. The successful integration of these components demonstrates effective real-time monitoring and control in embedded systems.

Uploaded by

mefasihrehman
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 6

EMBEDDED SYSTEMS REPORT (LAB 9)

Name: Fasih ur Rehman

Roll No: EE-22155

Course Code: EE-354 (Embedded Systems)

Instructor: Miss Aiman Najeeb

Objective:

To interface a 16x2 LCD display with ATmega328P microcontroller in 4-bit


mode using the I2C communication protocol. The tasks include:

1. Displaying a message with a blinking effect using the I2C expander.


2. Displaying an analog voltage value measured via ADC on the LCD.
3. Comparing UART, SPI, and I2C protocols.

TASK 1: LCD Interface in 4-bit Mode via I2C


Steps:

1. Program ATmega328P to control a 16x2 LCD using I2C communication.


2. Connect the PCF8574 I2C LCD module to the microcontroller.
3. Use TWI (Two-Wire Interface) pins for communication.
4. Modify the code to create a blinking effect on the LCD using display
ON/OFF commands and delays.

Code:

#include <avr/io.h> #include <util/delay.h> #include <stdlib.h>


// Including I2C functions void i2c_init() { TWBR = 0x62; //
Setting bit rate TWCR = (1<<TWEN); // Enable I2C TWSR = 0x00; //
Prescaler set to 1 }

// Start condition void i2c_start() { TWCR = (1<<TWINT) |


(1<<TWEN) | (1<<TWSTA); while (!(TWCR & (1<<TWINT))); // Wait
for start condition }

// I2C write (for sending address and data) void i2c_write(char


x) { TWDR = x; TWCR = (1<<TWINT) | (1<<TWEN); while (!(TWCR &
(1<<TWINT))); }

// Toggle function for LCD enable pulse void toggle()


{ i2c_write((TWDR |= 0x04)); _delay_us(1); i2c_write((TWDR &=
~0x04)); _delay_us(100); }

// Send command to LCD void lcd_cmd(char v2) { i2c_write((TWDR


&= ~0x03)); i2c_write((TWDR &= 0x0F)); i2c_write((TWDR |= (v2 &
0xF0))); toggle(); i2c_write((TWDR &= 0x0F)); i2c_write((TWDR |=
((v2 & 0x0F)<<4))); toggle(); }

// Write data to LCD void lcd_dwr(char v3) { i2c_write((TWDR |=


0x01)); i2c_write((TWDR &= 0x0F)); i2c_write((TWDR |= (v3 &
0xF0))); toggle(); i2c_write((TWDR &= 0x0F)); i2c_write((TWDR |=
((v3 & 0x0F)<<4))); toggle(); }

// Send string message to LCD void lcd_msg(char *c) { while(*c !


= 0) lcd_dwr(*c++); }

// LCD Initialization void lcd_init() { _delay_ms(100);


lcd_cmd(0x30); _delay_ms(10); lcd_cmd(0x30); _delay_ms(5);
lcd_cmd(0x30); _delay_ms(5); lcd_cmd(0x02); _delay_ms(1);
lcd_cmd(0x28); _delay_ms(1); lcd_cmd(0x0C); lcd_cmd(0x06);
lcd_cmd(0x01); _delay_ms(4); }

int main(void) { i2c_init(); i2c_start(); i2c_write(0x4E); //


Device Address

lcd_init();

float Percentage = 75.5; char buffer_str[10];


dtostrf(Percentage, 5, 1, buffer_str);
lcd_cmd(0x80); lcd_msg("Expected ES Lab");

lcd_cmd(0xC0); lcd_msg("Result "); lcd_msg(buffer_str);


lcd_msg("% :)");

while(1) { _delay_ms(1000); lcd_cmd(0x08); _delay_ms(1000);


lcd_cmd(0x0C); } }

Observation:

The message "Expected ES Lab" was displayed on the first line, and the
percentage result (75.5%) appeared on the second line. The LCD display
blinked every 1000 ms using lcd_cmd(0x08) and lcd_cmd(0x0C).

Conclusion:

The LCD was successfully interfaced using I2C. The use of display ON/OFF
commands allowed the blinking effect to be achieved.

TASK 2: Comparison of UART, SPI, and I2C


Feature UART SPI I2C
Asynchronous (No Synchronous (Uses
Type Synchronous (Uses clock)
clock) clock)
4 (MOSI, MISO,
Wires 2 (TX, RX) 2 (SDA, SCL)
SCK, SS)
Speed Up to 1 Mbps >10 Mbps 100 kbps – 3.4 Mbps
Devices Multiple (via SS
2 (Point-to-point) Multiple (via addresses)
Supported lines)
Clock
Not required Required Required
Requirement
Complexity Simple Moderate High
Serial with PC, Memory, sensors, EEPROMs, sensors in
Use Cases
Bluetooth displays embedded systems

Conclusion:
Each communication protocol has its pros and cons. UART is simplest, SPI is
fastest, and I2C is efficient for multiple low-speed peripherals.

TASK 3: Displaying Analog Voltage via ADC


on I2C LCD
Steps:

1. Use the ADC module of ATmega328P to read analog voltage.


2. Convert ADC value to a voltage.
3. Display the measured voltage on the LCD screen using I2C.

Code:

#include <avr/io.h> #include <util/delay.h> #include <stdlib.h>

// Including I2C functions void i2c_init() { TWBR = 0x62; TWCR =


(1 << TWEN); TWSR = 0x00; }

void i2c_start() { TWCR = (1 << TWINT) | (1 << TWEN) | (1 <<


TWSTA); while (!(TWCR & (1 << TWINT))); }

void i2c_write(char x) { TWDR = x; TWCR = (1 << TWINT) | (1 <<


TWEN); while (!(TWCR & (1 << TWINT))); }

void toggle() { i2c_write((TWDR |= 0x04)); _delay_us(1);


i2c_write((TWDR &= ~0x04)); _delay_us(100); }

void lcd_cmd(char v2) { i2c_write((TWDR &= ~0x03));


i2c_write((TWDR &= 0x0F)); i2c_write((TWDR |= (v2 & 0xF0)));
toggle(); i2c_write((TWDR &= 0x0F)); i2c_write((TWDR |= ((v2 &
0x0F) << 4))); toggle(); }

void lcd_dwr(char v3) { i2c_write((TWDR |= 0x01));


i2c_write((TWDR &= 0x0F)); i2c_write((TWDR |= (v3 & 0xF0)));
toggle(); i2c_write((TWDR &= 0x0F)); i2c_write((TWDR |= ((v3 &
0x0F) << 4))); toggle(); }
void lcd_init() { _delay_ms(100); lcd_cmd(0x30); _delay_ms(10);
lcd_cmd(0x30); _delay_ms(5); lcd_cmd(0x30); _delay_ms(5);
lcd_cmd(0x02); _delay_ms(1); lcd_cmd(0x28); _delay_ms(1);
lcd_cmd(0x0C); lcd_cmd(0x06); lcd_cmd(0x01); _delay_ms(4); }

void lcd_msg(char *c) { while (*c != 0) lcd_dwr(*c++); }

int main(void) { DDRC = 0x00; ADCSRA = 0x87; ADMUX = 0x60;

i2c_init(); i2c_start(); i2c_write(0x20 << 1); // Address for


PCF8574

lcd_init();

while (1) { ADCSRA |= (1 << ADSC); while ((ADCSRA & (1 << ADIF))
== 0);

char buffer_str[10];
float Percentage = ADCH * 5.0 / 255;
dtostrf(Percentage, 5, 1, buffer_str);

lcd_cmd(0x80);
lcd_msg("Measured Voltage");

lcd_cmd(0xC0);
lcd_msg("Result ");
lcd_msg(buffer_str);
lcd_msg("V");

} }

Observation:

The analog voltage, calculated from the ADC, was correctly displayed on the
LCD. The output format was as follows:
Measured Voltage
Result 2.5V

Conclusion:

Successful integration of ADC and I2C LCD allowed for real-time monitoring
of analog signals, demonstrating the ability to combine peripherals in
embedded systems.

You might also like