728x90

728x90

Monday, February 2, 2026

ATMega644P TWI LCD RTC and Keypad Example

The PCF8574/PCF8574A series can interface to many parallel port I/O devices such as matrix keypad or even an HD44780 character LCD. Its 8-bit port can control the HD44780-based character LCD using the controller 4-bit data transfer mode without any auxiliary chip. Even the display is a one-line, two-line or 4-line display we can set its DDRAM via LCD command.

ATMega644P TWI LCD RTC and Keypad Example

In this introductory example I use a popular Arduino PCF8574T character LCD interface module with the ATMega644P TWI to control a 16x2 character LCD.

ATMega644P TWI LCD RTC and Keypad Example
A sample picture

ATMega644P TWI LCD RTC and Keypad Example
Running Program on my ATMega644P Experiment Board

 

The I2C default address of this module is 0x4E since the A2:A0 pins are pulled high. For the Arduino IDE its TWI address is 0x27. I draw and make my own DIY using the PCF8574AP. Its schematic is shown below.

A DIY I2C character LCD built with PCF8574AP For PIC AVR and Arduino
Schematic Diagram

However it works the same function except its I2C slave address. For more information about this DIY module please visit this blog.

Source Code: "main.c"

  1. /*
  2. * 10-i2c_pcf8574T_1602.c
  3. *
  4. * Created: 2/3/2026 11:05:19 AM
  5. * Author : Admin
  6. */

  7. #include <stdio.h>
  8. #include <avr/io.h>
  9. #include <util/delay.h>
  10. #define F_CPU 16000000UL

  11. /*TWI LCD Driver*/
  12. #define RS 0
  13. #define RW 1
  14. #define EN 2
  15. #define BL 3

  16. char backLight=0;

  17. void i2c_lcdCommand(uint8_t command){
  18. uint8_t data;
  19. data=command&0xF0;
  20. pcf8574Write(data|(backLight<<BL)|(1<<EN));
  21. //_delay_us(10);
  22. pcf8574Write(data|(backLight<<BL));
  23. //_delay_us(50);
  24. data=command<<4;
  25. pcf8574Write(data|(backLight<<BL)|(1<<EN));
  26. //_delay_us(10);
  27. pcf8574Write(data|(backLight<<BL));
  28. //_delay_us(50);
  29. }

  30. void i2c_lcdData(uint8_t command){
  31. uint8_t data;
  32. data=command&0xF0;
  33. pcf8574Write(data|(backLight<<BL)|(1<<EN)|(1<<RS));
  34. //_delay_us(10);
  35. pcf8574Write(data|(backLight<<BL)|(1<<RS));
  36. _delay_us(50);
  37. data=command<<4;
  38. pcf8574Write(data|(backLight<<BL)|(1<<EN)|(1<<RS));
  39. //_delay_us(10);
  40. pcf8574Write(data|(backLight<<BL)|(1<<RS));
  41. //_delay_us(50);
  42. }

  43. void i2c_lcdXY(int8_t x, int8_t y){
  44. int8_t addr[]={0x80,0xC0};
  45. i2c_lcdCommand(addr[y-1]+x-1);
  46. }

  47. void i2c_lcdText(int8_t *txt){
  48. while(*txt) i2c_lcdData(*txt++);
  49. }

  50. void i2c_lcdClear(void){
  51. i2c_lcdCommand(0x01);
  52. //_delay_ms(5);
  53. }

  54. void i2c_lcdInit(void){
  55. i2cInit();
  56. //_delay_us(10);
  57. pcf8574Write(0);
  58. //_delay_ms(10);
  59. i2c_lcdCommand(0x33);
  60. //_delay_us(10);
  61. i2c_lcdCommand(0x32);
  62. //_delay_us(10);
  63. i2c_lcdCommand(0x28);
  64. //_delay_us(10);
  65. i2c_lcdCommand(0x0F);
  66. //_delay_us(10);
  67. i2c_lcdCommand(0x01);
  68. //_delay_ms(5);
  69. i2c_lcdCommand(0x06);
  70. //_delay_us(10);
  71. }
  72. int main(void)
  73. {
  74. /* Replace with your application code */
  75. _delay_ms(1000);
  76. backLight=1;
  77. i2c_lcdInit();
  78. i2c_lcdText("ATMega644P I2C");
  79. i2c_lcdXY(1,2);
  80. i2c_lcdText(" PCF8574AP LCD");
  81. long counter=0;
  82. uint8_t msg[10];
  83. _delay_ms(10000);
  84. i2c_lcdClear();
  85. i2c_lcdCommand(0x0C);
  86. i2c_lcdText("Counter:");
  87. while (1)
  88. {
  89. sprintf(msg,"%u",counter);
  90. i2c_lcdXY(1,2);
  91. i2c_lcdText(msg);
  92. counter++;
  93. _delay_ms(500);
  94. }
  95. }


I putted the pcf8574.c in a a separated file that's needed to copy and add in project source folder. But it's not include in the main C source file.

The "pcf8574.c": 

  1. /*
  2. * pcf8574.c
  3. *
  4. * Created: 2/3/2026 11:06:53 AM
  5. * Author: Admin
  6. */

  7. #include <avr/io.h>
  8. #include <util/delay.h>
  9. #define F_CPU 16000000UL

  10. //DIY PCF8574AP LCD Module (A2:A0=0)
  11. const char pcf8574_w=0x40;
  12. const char pcf8574_r=0x41;
  13. //PCF8574 (A2:A0=0)
  14. const char pcf8574a_w=0x70;
  15. const char pcf8574a_r=0x71;
  16. //DIY Arduino PCF8574T LCD Module
  17. const char pcf8574T_LCD_W=0x4E;
  18. const char pcf8574T_LCD_R=0x4F;

  19. void i2cInit(void){
  20. TWSR|=0x00; //Prescaler Selection Bit
  21. TWBR=0xF0; //Baud Rate Generator
  22. TWCR=(1<<TWEN); //Enable The TWI Module
  23. PORTC|=(1<<0);
  24. PORTC|=(1<<1);
  25. }

  26. void i2cStart(void){
  27. TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
  28. while((TWCR&(1<<TWINT))==0);
  29. }

  30. void i2cWrite(unsigned char data){
  31. TWDR=data;
  32. TWCR=(1<<TWINT)|(1<<TWEN);
  33. while((TWCR&(1<<TWINT))==0);
  34. }

  35. unsigned char i2cRead(char ACK){
  36. if(ACK==0)
  37. TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWEA);
  38. else
  39. TWCR=(1<<TWINT)|(1<<TWEN);
  40. while((TWCR&(1<<TWINT))==0);
  41. return TWDR;
  42. }

  43. void i2cStop(){
  44. TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
  45. _delay_us(10);
  46. }

  47. void pcf8574Write(char data){
  48. i2cStart();
  49. i2cWrite(pcf8574T_LCD_W);
  50. i2cWrite(data);
  51. i2cStop();
  52. }

  53. char pcf8574Read(void){
  54. i2cStart();
  55. i2cWrite(pcf8574T_LCD_R);
  56. char temp=i2cRead(1);
  57. i2cStop();
  58. return temp;
  59. }

Schematic:

ATMega644P TWI LCD RTC and Keypad Example
Schematic Diagram and Simulation

ATMega644P TWI LCD RTC and Keypad Example
Simulating Program

ATMega644 Experiment Board: 

ATMega644P TWI LCD RTC and Keypad Example
ATMega644 Experiment Board

 

 

ATMega644P TWI LCD RTC and Keypad Example
ATMega644 Experiment Board

 Now I replace with a TC1604A-01(R) I posses that is a 16x4 character LCD. It almost identical to the previous one's. 

ATMega644P TWI LCD RTC and Keypad Example
TC1604A-01(R) MODULE OUTLINE DRAWING

Its display data RAM address is listed below.

ATMega644P TWI LCD RTC and Keypad Example

Source Code "main.c":

  1. /*
  2. * 10-i2c_pcf8574T_1604.c
  3. *
  4. * Created: 2/3/2026 3:01:44 PM
  5. * Author : Admin
  6. */

  7. #include <stdio.h>
  8. #include <avr/io.h>
  9. #include <util/delay.h>
  10. #define F_CPU 16000000UL

  11. /*TWI LCD Driver*/
  12. #define RS 0
  13. #define RW 1
  14. #define EN 2
  15. #define BL 3

  16. char backLight=0;

  17. void i2c_lcdCommand(char command){
  18. char data;
  19. data=command&0xF0;
  20. pcf8574Write(data|(backLight<<BL)|(1<<EN));
  21. //_delay_us(10);
  22. pcf8574Write(data|(backLight<<BL));
  23. //_delay_us(50);
  24. data=command<<4;
  25. pcf8574Write(data|(backLight<<BL)|(1<<EN));
  26. //_delay_us(10);
  27. pcf8574Write(data|(backLight<<BL));
  28. //_delay_us(50);
  29. }

  30. void i2c_lcdData(char command){
  31. char data;
  32. data=command&0xF0;
  33. pcf8574Write(data|(backLight<<BL)|(1<<EN)|(1<<RS));
  34. //_delay_us(10);
  35. pcf8574Write(data|(backLight<<BL)|(1<<RS));
  36. _delay_us(50);
  37. data=command<<4;
  38. pcf8574Write(data|(backLight<<BL)|(1<<EN)|(1<<RS));
  39. //_delay_us(10);
  40. pcf8574Write(data|(backLight<<BL)|(1<<RS));
  41. //_delay_us(50);
  42. }

  43. void i2c_lcdXY(int8_t x, int8_t y){
  44. //16x2
  45. //char addr[]={0x80,0xC0};
  46. //16x4
  47. char addr[]={0x80,0xC0,0x90,0xD0};
  48. i2c_lcdCommand(addr[y-1]+x-1);
  49. }

  50. void i2c_lcdText(int8_t *txt){
  51. while(*txt) i2c_lcdData(*txt++);
  52. }

  53. void i2c_lcdClear(void){
  54. i2c_lcdCommand(0x01);
  55. //_delay_ms(5);
  56. }

  57. void i2c_lcdInit(void){
  58. i2cInit();
  59. //_delay_us(10);
  60. pcf8574Write(0);
  61. //_delay_ms(10);
  62. i2c_lcdCommand(0x33);
  63. //_delay_us(10);
  64. i2c_lcdCommand(0x32);
  65. //_delay_us(10);
  66. i2c_lcdCommand(0x28);
  67. //_delay_us(10);
  68. i2c_lcdCommand(0x0F);
  69. //_delay_us(10);
  70. i2c_lcdCommand(0x01);
  71. //_delay_ms(5);
  72. i2c_lcdCommand(0x06);
  73. //_delay_us(10);
  74. }
  75. int main(void)
  76. {
  77. /* Replace with your application code */
  78. _delay_ms(1000);
  79. backLight=1;
  80. i2c_lcdInit();
  81. i2c_lcdText("ATMega644P TWI");
  82. i2c_lcdXY(1,2);
  83. i2c_lcdText("PCF8574T LCD");
  84. i2c_lcdXY(1,3);
  85. i2c_lcdText("TC1604A-01(R)");
  86. i2c_lcdXY(1,4);
  87. i2c_lcdText("16x4 Lines LCD");
  88. while (1)
  89. {
  90. }
  91. }




Schematic:

ATMega644P TWI LCD RTC and Keypad Example
Schematic

ATMega644 Prototype Board:

ATMega644P TWI LCD RTC and Keypad Example
PCF8574T TC1604A-01(R) 16x4 LCD

 

No comments:

Post a Comment

320x50

Search This Blog

tyro-728x90