Menu

Adskeeper - header widge

728x90

Search This Blog

468x60

Navbar

AdsKeeper - IAB Display Standard Ad Unit

Wednesday, October 14, 2026

dsPIC30F2010 I2C PCF8574T HD44780 LCD

Introduction

In previous post, I use the PCF8574AP DIP-16 chip to expand the output of dsPIC30F2010. Since this chip is an 8-bit bi-directional I/O device, it can be used to connect to any I/O peripheral devices. even an HD44780 character LCD. 

 

dsPIC30F2010 I2C PCF8574T HD44780 LCD
Test Program

A character LCD module comes with a PCF8574T is very popular and low cost. It is commonly an Arduino LCD module widely used among the students and electronic hobbyists. There are a lot of Arduino programming examples for this stuffs. 

 

dsPIC30F2010 Simple I2C LCD using PCF8574T 

Controlling an HD44780 character LCD via a PCF8574T is very easy with some additional code to process the 4-bit data transfer mode of the LCD chip controller. In this example, the I2C master micro-controller send some character to a 16x2 character LCD via a PCF8574T chip. 

Schematic:

dsPIC30F2010 I2C PCF8574T HD44780 LCD
Schematic

 This post show a full I2C devices interfacing examples using an ATMega644P AVR chip.

MikroC Source Code:



  1. const char PCF8574_W=0x40;
  2. const char PCF8574_R=0x41;
  3. const char PCF8574T_LCD_W=0x4E;
  4. const char PCF8574T_LCD_R=0x4F;
  5. const char PCF8574A_W=0x70;
  6. const char PCF8574A_R=0x71;

  7. void pcf8574_write(char _data){
  8. I2C1_Start(); // issue I2C start signal
  9. I2C1_Write(PCF8574T_LCD_W); // send byte via I2C (device address + W)
  10. I2C1_Write(_data); // send byte (data address)
  11. I2C1_Stop(); // issue I2C stop signal
  12. }

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

  18. #define i2c_lcd_cursor_off() i2c_lcd_command(0x0C)
  19. #define i2c_lcd_line_1() i2c_lcd_command(0x80)
  20. #define i2c_lcd_line_2() i2c_lcd_command(0xC0)

  21. char backLight=1;

  22. void i2c_lcd_command(char command){
  23. char _data;
  24. _data=command&0xF0;
  25. pcf8574_write(_data|(backLight<<BL)|(1<<EN));
  26. //_delay_us(10);
  27. pcf8574_write(_data|(backLight<<BL));
  28. //_delay_us(50);

  29. _data=command<<4;
  30. pcf8574_write(_data|(backLight<<BL)|(1<<EN));
  31. //_delay_us(10);
  32. pcf8574_write(_data|(backLight<<BL));
  33. //_delay_us(50);
  34. }

  35. void i2c_lcd__data(char command){
  36. char _data;
  37. _data=command&0xF0;
  38. pcf8574_write(_data|(backLight<<BL)|(1<<EN)|(1<<RS));
  39. //_delay_us(10);
  40. pcf8574_write(_data|(backLight<<BL)|(1<<RS));
  41. Delay_us(50);

  42. _data=command<<4;
  43. pcf8574_write(_data|(backLight<<BL)|(1<<EN)|(1<<RS));
  44. //Delay_us(10);
  45. pcf8574_write(_data|(backLight<<BL)|(1<<RS));
  46. //Delay_us(50);
  47. }

  48. void i2c_lcd_xy(char x, char y){
  49. char addr[]={0x80,0xC0};
  50. i2c_lcd_command(addr[y-1]+x-1);
  51. }

  52. void i2c_lcd_text(char *txt){
  53. while(*txt) i2c_lcd__data(*txt++);
  54. }

  55. void i2c_lcd_clear(void){
  56. i2c_lcd_command(0x01);
  57. Delay_ms(5);
  58. }

  59. void i2c_lcd_init(void){
  60. pcf8574_write(0);
  61. Delay_ms(10);
  62. i2c_lcd_command(0x33);
  63. Delay_us(10);
  64. i2c_lcd_command(0x32);
  65. Delay_us(10);
  66. i2c_lcd_command(0x28);
  67. Delay_us(10);
  68. i2c_lcd_command(0x0F);
  69. Delay_us(10);
  70. i2c_lcd_command(0x01);
  71. Delay_ms(10);
  72. i2c_lcd_command(0x06);
  73. Delay_us(10);
  74. }

  75. void main(){
  76. char temp = 0, i = 0;
  77. I2C1_Init(10000); // initialize I2C communication
  78. Delay_ms(10);
  79. i2c_lcd_init();
  80. Delay_ms(10);
  81. i2c_lcd_text("dsPIC30F2010 I2C");
  82. i2c_lcd_line_2();
  83. i2c_lcd_text("PCF8574T LCD");
  84. i2c_lcd_cursor_off();

  85. while(1){

  86. }
  87. }


I test this example on my DIY dsPIC30F2010 Prototype Board. It works fine.

 

dsPIC30F2010 I2C PCF8574T HD44780 LCD
My DIY dsPIC30F2010 Prototype Board

dsPIC30F2010 5V DVM I2C LCD using PCF8574T 

There is one on-board POT. So I made a simple 5VDC Digital Volt Meter with this I2C LCD. The schematic remains the same a above.

 

dsPIC30F2010 I2C PCF8574T HD44780 LCD
Test Program

 

MikroC Source Code:



  1. const char PCF8574_W=0x40;
  2. const char PCF8574_R=0x41;
  3. const char PCF8574T_LCD_W=0x4E;
  4. const char PCF8574T_LCD_R=0x4F;
  5. const char PCF8574A_W=0x70;
  6. const char PCF8574A_R=0x71;

  7. void pcf8574_write(char _data){
  8. I2C1_Start(); // issue I2C start signal
  9. I2C1_Write(PCF8574T_LCD_W); // send byte via I2C (device address + W)
  10. I2C1_Write(_data); // send byte (data address)
  11. I2C1_Stop(); // issue I2C stop signal
  12. }

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

  18. #define i2c_lcd_cursor_off() i2c_lcd_command(0x0C)
  19. #define i2c_lcd_line_1() i2c_lcd_command(0x80)
  20. #define i2c_lcd_line_2() i2c_lcd_command(0xC0)

  21. char backLight=1;

  22. void i2c_lcd_command(char command){
  23. char _data;
  24. _data=command&0xF0;
  25. pcf8574_write(_data|(backLight<<BL)|(1<<EN));
  26. //_delay_us(10);
  27. pcf8574_write(_data|(backLight<<BL));
  28. //_delay_us(50);

  29. _data=command<<4;
  30. pcf8574_write(_data|(backLight<<BL)|(1<<EN));
  31. //_delay_us(10);
  32. pcf8574_write(_data|(backLight<<BL));
  33. //_delay_us(50);
  34. }

  35. void i2c_lcd__data(char command){
  36. char _data;
  37. _data=command&0xF0;
  38. pcf8574_write(_data|(backLight<<BL)|(1<<EN)|(1<<RS));
  39. //_delay_us(10);
  40. pcf8574_write(_data|(backLight<<BL)|(1<<RS));
  41. Delay_us(50);

  42. _data=command<<4;
  43. pcf8574_write(_data|(backLight<<BL)|(1<<EN)|(1<<RS));
  44. //Delay_us(10);
  45. pcf8574_write(_data|(backLight<<BL)|(1<<RS));
  46. //Delay_us(50);
  47. }

  48. void i2c_lcd_xy(char x, char y){
  49. char addr[]={0x80,0xC0};
  50. i2c_lcd_command(addr[y-1]+x-1);
  51. }

  52. void i2c_lcd_text(char *txt){
  53. while(*txt) i2c_lcd__data(*txt++);
  54. }

  55. void i2c_lcd_clear(void){
  56. i2c_lcd_command(0x01);
  57. Delay_ms(10);
  58. }

  59. void i2c_lcd_init(void){
  60. pcf8574_write(0);
  61. Delay_ms(10);
  62. i2c_lcd_command(0x33);
  63. Delay_us(10);
  64. i2c_lcd_command(0x32);
  65. Delay_us(10);
  66. i2c_lcd_command(0x28);
  67. Delay_us(10);
  68. i2c_lcd_command(0x0F);
  69. Delay_us(10);
  70. i2c_lcd_command(0x01);
  71. Delay_ms(10);
  72. i2c_lcd_command(0x06);
  73. Delay_us(10);
  74. }

  75. void main(){
  76. unsigned int adc_rd;
  77. char text[16];
  78. long tlong;
  79. float voltage;
  80. ADPCFG = 0xFFFF; // Configure AN pins as digital
  81. I2C1_Init(10000); // initialize I2C communication
  82. Delay_ms(10);
  83. i2c_lcd_init();
  84. Delay_ms(10);
  85. i2c_lcd_text("dsPIC30F2010 I2C");
  86. i2c_lcd_line_2();
  87. i2c_lcd_text("ADC PCF8574T LCD");
  88. i2c_lcd_cursor_off();
  89. Delay_ms(10000);
  90. i2c_lcd_clear();
  91. while(1){
  92. adc_rd = ADC1_read(4); // get ADC value from 2nd channel
  93. voltage = 5.0*adc_rd/1023;
  94. i2c_lcd_line_1();
  95. sprintf(text,"AN4 ADC: %4d 10", adc_rd);
  96. i2c_lcd_text(text);
  97. i2c_lcd_line_2();
  98. sprintf(text,"Voltage: %.2f V", voltage);
  99. i2c_lcd_text(text);
  100. Delay_ms(500);
  101. }
  102. }

 

Using program C sprintf function is very easy to convert any data type into an array of ASCII characters. But it requires a lot of memory space. For limited ROM and RAM space, we can process the text, character, integer and floating point numbers one-by-one before sending it to UART or LCD stream. This post shows a simple number to ASCII character converting.

Archive: 

dsPIC30F2010 I2C PCF8574T HD44780 LCD
ADC Read Voltage 0.00 V

dsPIC30F2010 I2C PCF8574T HD44780 LCD
ADC Read Voltage 2.74 V

dsPIC30F2010 I2C PCF8574T HD44780 LCD
ADC Read Voltage 5.00 V


 See this short video on Youtube:

 


 

 



 

 




 

 

 

 

dsPIC30F2010 I2C and PCF8574 Interfacing using MikroC

Introduction

The dsPIC30F2010 is a 16-bit micro-controller. It means that its internal data bus is 16-bit wide. Additionally its I/O data is also 16-bit wide. However a small foot-print 16-bit MCU like the dsPIC30F2010 has only 28 pins including supply voltage pins, ADC voltage pins, clock pins ,etc. So we can get a full 16-bit input output from its pins.

 

dsPIC30F2010 I2C and PCF8574 Interfacing
Pin Diagrams

 

To get a full 8-bit or 16-bit external I/O, we need to add any I/O expansion chips. These chips implement the SPI or I2C interface. Here I use the PCF8574 I2C I/O expansion chip. This chip an 8-bit bidirectional micro-processor expansion chip. 

 

The PCF8574 Series 

The device features an 8-bit quasi-bidirectional I/O port (P0–P7), including latched outputs with high current drive capability for directly driving LEDs. Each quasi-bidirectional I/O can be used as an input or output without the use of a data-direction control signal. At power on, the I/Os are high. In this mode, only a current source to VCC is active.

This chip is suitable for,

  • Telecom Shelters: Filter Units
  • Servers
  • Routers (Telecom Switching Equipment)
  • Personal Computers
  • Personal Electronics
  • Industrial Automation
  • Products with GPIO-Limited Processors 
dsPIC30F2010 I2C and PCF8574 Interfacing using MikroC
PCF8574 Interfacing Diagram


dsPIC30F2010 I2C and PCF8574 Interfacing using MikroC
PCF8574AP DIP-16

We can event use this chip for a 4x4 matrix keypad, or driving an HD44780-base character LCD.

 

dsPIC30F2010 I2C and PCF8574 Interfacing using MikroC
Pin Configuration and Functions

This device has various package types. A PDIP-16 or a SOIC-16 are common for most of electronics hobbyists.

 

dsPIC30F2010 I2C and PCF8574 Interfacing using MikroC
Simplified Block Diagram of Device


This device has an 8-bit customizable slave address with R/W bit.


dsPIC30F2010 I2C and PCF8574 Interfacing using MikroC
PCF8574 Interface Definition
 

We can custom its optional slave address via A2...A0 bits. Its default write address when A2...A0 are wired to GND is 0x40.

 

dsPIC30F2010 I2C and PCF8574 Interfacing using MikroC
Address Reference

 

The Master I2C device need to write device slave address followed by output port data twice.


dsPIC30F2010 I2C and PCF8574 Interfacing using MikroC
PCF8574 Write Mode

To read from this I2C slave device, the microprocessor need to write device read address (eg. 0x41), followed by I2C in read mode.


dsPIC30F2010 I2C and PCF8574 Interfacing using MikroC
PCF8574 Read Mode
 

We can use various I/O devices with this chip.

 

dsPIC30F2010 I2C and PCF8574 Interfacing using MikroC
PCF8574 Typical Application

 Interrupt Output (INT) pin is optional.
 

dsPIC30F2010 I2C Programming using MikroC

MikroC for dsPIC offer a build-in dedicated and software I2C libraries. Both of them are stable and reliable for most of applications. It excepts that the software I2C operates at lower clock frequency.

Here I use its dedicated I2C module. Most of dsPIC30F MCUs have more than one I2C module. 

Important :

  • I²C library routines require you to specify the module you want to use. To select the desired I²C module, simply change the letter x in the routine prototype for a number from 1 to 3.
  • Number of I²C modules per MCU differs from chip to chip. Please, read the appropriate datasheet before utilizing this library.

These are its library routines:

Library Routines

Generic Routines

 For more information about using the I2C module, please see this page.

PCF8574AP Output LEDs Example

For an introductory example, the dsPIC30F2010 send an 8-bit data to this chip. The 8-bit output of PCF8574AP connect individual LED.

 

Schematic:

dsPIC30F2010 I2C and PCF8574 Interfacing using MikroC
Schematic

 MikroC Source Code:

 



  1. const char PCF8574_W=0x40;
  2. const char PCF8574_R=0x41;
  3. const char PCF8574A_W=0x70;
  4. const char PCF8574A_R=0x71;

  5. void pcf8574_write(char device, char _data){
  6. I2C1_Start(); // issue I2C start signal
  7. I2C1_Write(device); // send byte via I2C (device address + W)
  8. I2C1_Write(_data); // send byte (data address)
  9. I2C1_Stop(); // issue I2C stop signal
  10. }

  11. void blink(unsigned int duration, unsigned int counts){
  12. while(counts>0){
  13. pcf8574_write(PCF8574A_W,0x00);
  14. Vdelay_ms(duration);
  15. pcf8574_write(PCF8574A_W,0xFF);
  16. Vdelay_ms(duration);
  17. counts--;
  18. }
  19. pcf8574_write(PCF8574A_W,0x00);
  20. }
  21. void main(){
  22. char temp = 0, i = 0;
  23. I2C1_Init(100000); // initialize I2C communication
  24. Delay_ms(10);
  25. pcf8574_write(PCF8574A_W,0x00);
  26. blink(100,100);
  27. while(1){
  28. pcf8574_write(PCF8574A_W,temp);
  29. temp+=(1<<i);
  30. i++;
  31. if(i > 8) i = temp = 0;
  32. Delay_ms(200);
  33. }
  34. }

 

 I tested this code on my DIY dsPIC30F2010 Prototype Board.

 

dsPIC30F2010 I2C and PCF8574 Interfacing using MikroC
 I tested this code on my DIY dsPIC30F2010 Prototype Board.

dsPIC30F2010 I2C and PCF8574 Interfacing using MikroC
 I tested this code on my DIY dsPIC30F2010 Prototype Board.

dsPIC30F2010 I2C and PCF8574 Interfacing using MikroC
 I tested this code on my DIY dsPIC30F2010 Prototype Board.

dsPIC30F2010 I2C and PCF8574 Interfacing using MikroC
 I tested this code on my DIY dsPIC30F2010 Prototype Board.

 For a full I2C devices interfacing example using the ATMega644P chip see this post.

 

 

 

Tuesday, October 13, 2026

dsPIC30F2010 and Nokia 5110 LCD Software SPI in MikroC

Introduction

Nokia 5510 LCD Module is 84x48 monochrome graphical LCD that use a Philip PCD8544 pixel matrix LCD controller/driver. It is very easy to use since it uses only three wires SPI interface with some additional control pin. It configuration setting is simple that is very similar to the KS0108 LCD controller except the three wires SPI interface. Using this interface is easy to connect and maintenance with a master MCU. 

 

dsPIC30F2010 and Nokia 5110 LCD Software SPI in MikroC
Program Testing

 

 This graphical LCD is widely available at very low cost. Most electronic hobbyists use this LCD with an Arduino. However different micro-controllers can control this display via a dedicated or software SPI.

 

dsPIC30F2010 and Nokia 5110 LCD Programming using MikroC

MikroC doesn't have a build-in library for this LCD module. But it has both hardware and software SPI to communicate with any devices. Hardware or dedicated SPI is very fast even at the speed of Fosc/4 of a micro-controller clock.

 

dsPIC30F2010 and Nokia 5110 LCD Software SPI in MikroC
Program Testing

 

I can not properly configure the hardware SPI module of the dsPIC30F2010 at this time. So I use its software SPI library instead due to its select-able pins and lower transmission speed. Commonly the Nokia 5110 LCD is unable to operates at high clock frequency. It should be below 500kbps.

Schematic:

dsPIC30F2010 and Nokia 5110 LCD Software SPI in MikroC
Schematic Diagram

 

In this example, I use this LCD to shows some texts on screen. I can not put any additional graphic due to its limited ROM. The dsPIC30F2010 has only 12kBytes of ROM space. 

MikroC Source Code:


  1. #include "font.c"

  2. sbit Chip_Select at LATE0_bit;
  3. sbit SoftSpi_CLK at LATE1_bit;
  4. sbit SoftSpi_SDI at RE2_bit;
  5. sbit SoftSpi_SDO at LATE3_bit;

  6. sbit RST at LATE4_bit;
  7. //sbit CS at LATE5_bit;
  8. sbit D_C at LATE5_bit;

  9. sbit Chip_Select_Direction at TRISE0_bit;
  10. sbit SoftSpi_CLK_Direction at TRISE1_bit;
  11. sbit SoftSpi_SDI_Direction at TRISE2_bit;
  12. sbit SoftSpi_SDO_Direction at TRISE3_bit;

  13. sbit RST_Direction at TRISE4_bit;
  14. //sbit CS_Direction at TRISE5_bit;
  15. sbit D_C_Direction at TRISE5_bit;

  16. #define LCD_C 0
  17. #define LCD_D 1

  18. #define LCD_X 84
  19. #define LCD_Y 48

  20. void LcdCharacter( char charactor);
  21. void LcdClear(void);
  22. void LcdInitialize(void);
  23. void LcdString( char *charactor);
  24. void LcdWrite( char dc,unsigned char _data);
  25. void setXy(char x,char y);

  26. void main() {
  27. LcdInitialize();
  28. LcdClear();
  29. setXy(0,0);
  30. LcdString("MikroC dsPIC");
  31. setXy(0,1);
  32. LcdString("Nokia 5510");
  33. setXy(0,2);
  34. LcdString("Monochrome");
  35. setXy(0,3);
  36. LcdString("LCD Example");
  37. setXy(0,4);
  38. LcdString("dsPIC30F2010");
  39. setXy(0,5);
  40. LcdString("16-bit MCU");

  41. while(1){

  42. }
  43. }

  44. void LcdCharacter( char character){
  45. int i;
  46. LcdWrite(LCD_D,0x00);
  47. for(i=0;i<5;i++) LcdWrite(LCD_D,ASCII[character-0x20][i]);
  48. LcdWrite(LCD_D,0x00);
  49. }

  50. void LcdClear(void){
  51. int i;
  52. for(i=0;i<LCD_X*LCD_Y/8;i++) LcdWrite(LCD_D,0x00);
  53. }

  54. void LcdInitialize(void){
  55. Chip_Select_Direction = 0; // Set CS# pin as Output
  56. RST_Direction = 0;
  57. D_C_Direction = 0;
  58. Soft_SPI_Init(); // Initialize Soft_SPI

  59. RST=0;
  60. RST=1;
  61. Chip_Select=1;

  62. LcdWrite(LCD_C,0x21); // LCD Extended Commands
  63. LcdWrite(LCD_C,0xB0); // SET LCD CONTRAST
  64. LcdWrite(LCD_C,0x04); // set temp coefficient 0x04
  65. LcdWrite(LCD_C,0x14); // LCD bias 1:48 0x13
  66. LcdWrite(LCD_C,0x20);
  67. LcdWrite(LCD_C,0x0C); // LCD normal Mode
  68. }

  69. void LcdString( char *character){
  70. while(*character) LcdCharacter(*character++);
  71. }

  72. void LcdWrite( char _dc, char _data){
  73. D_C =_dc;
  74. Chip_Select=0;
  75. Soft_SPI_Write(_data);
  76. Chip_Select=1;
  77. }

  78. /*Set the cursor*/
  79. void setXy(char x,char y){
  80. /*x ranges from 0 to 83*/
  81. LcdWrite(LCD_C, 0x80+(6*x));
  82. /*y ranges from 0 to 5*/
  83. LcdWrite(LCD_C, 0x40+y);
  84. }

 

I tested this example, on my DIY dsPIC30F2010 Prototype Board. The LCD dots is not clear due to its poor quality.

  

 

Adskeep- Standard Ads

336x280

DIY Electronic Projects And Instruments

AdsKeeper - 2091654

Labels

23K256 (1) 24C16B (2) 25AA010A (2) 8051 (7) 93AA46B (1) ADC (40) Analog Comparator (1) Arduino (16) ARM (32) AT89C52 (7) ATMega32 (59) ATMega644P (27) AVR (88) AVR PCB (2) Bootloader (1) CCS PICC (31) Change Notify Interrupt (CNI) (2) DAC (2) DHT11 (5) Display (156) Distance Sensor (3) dot matrix (1) ds1307 (10) DS18B20 (6) ds3231 (1) ds3232 (2) dsPIC (15) dsPIC30F1010 (3) dsPIC30F2010 (15) EEPROM (5) Environment Sensor (6) ESP32 (1) esp8266 (1) Graphical LCD (3) HD44780 (11) I2C (40) ILI9341 (1) Input/Output (83) Interrupt (22) IoT PCB (1) Keil (5) Keypad (16) KS0108 (3) LCD (86) LM35 (4) Master/Slave (2) MAX7221 (1) MCP23017 (8) MCP23S17 (7) MCP4921 (1) MCP4922 (2) Meter (3) MikroC (2) MikroC ARM (1) MikroC dsPIC (10) Module PCB (2) Motor (15) MPLABX (73) Nokia 5110 LCD (5) OLED (2) One-Wire (7) Oscillator (8) PCB (13) PCD8544 (3) PCF8574 (12) PIC (119) PIC12F (3) PIC16 (105) PIC16F628A (3) PIC16F630 (2) PIC16F716 (4) PIC16F818 (11) PIC16F818/819 (3) PIC16F84A (16) PIC16F876A (2) PIC16F877A (9) PIC16F88 (2) PIC16F887 (60) PIC18 (19) PIC18F1220 (5) PIC18F2550 (5) PIC18F4550 (12) PICKit2 (1) PICMicro PCB (4) Pin Change Interrupt (1) PWM (12) RTC (12) SBN0064G (1) Sensor (15) SH1106 (3) Shift Register (15) Shift Registers (19) SN74HC595N (9) Software SPI (1) Software TWI (2) SPI (44) sprinf (3) ST7735 (1) STM32 (29) STM32 Black Pill (1) STM32 Blue Pill (12) STM32 HAL (23) STM32CubeIDE (32) STM32F103C8T6 (9) STM32F103R6 (18) STM32F401CCU6 (1) SysTick (7) temperature sensor (15) TFT (1) TG12864A (1) Thermometer (22) Timer/Counter (32) TM1637 (2) twi (10) UART (11) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (96)