728x90

728x90

Showing posts with label PCF8574. Show all posts
Showing posts with label PCF8574. Show all posts

Saturday, January 20, 2024

PIC16F887 PCF8574AP I2C LCD Example using XC8

The PCF8574 could be used for a HD44780 based character LCD controlling using the 4-bit data transfer mode. The popular one's is an Arduino TWI LCD driving using this chip.

PIC16F887 PCF8574AP I2C LCD Example using XC8
A long hours running program


This chip has only 8 bits inputs/outputs. So it can interface with an 8-bit character LCD using the 4-bit data transfer mode. Using this method the micro-processor need to send the 8-bit command or data two time, first the higher nibble and then the lower nibble. For more information about using the PCF8574 please see this post.  If you are a beginner in micro-controller programming you can see this post about 4-bit LCD interfacing.

PIC16F887 PCF8574AP I2C LCD Example using XC8
Program Testing on Prototype Board

 I use use my own DIY PCF8574AP character LCD module. Its schematic is shown below.

PIC16F887 PCF8574AP I2C LCD Example using XC8
PCF8574AP Character LCD Module Schematic

Its slave address are 0x70 and 0x71.

PIC16F887 PCF8574AP I2C LCD Example using XC8
DIY PCF8574AP Character LCD Module

PIC16F887 PCF8574AP I2C LCD Example using XC8
DIY PCF8574AP Character LCD Module

You can use an Arduino PCF8574 LCD module with different address.

PIC16F887 PCF8574AP I2C LCD Example using XC8
Arduino PCF8574 LCD module

PIC16F887 PCF8574AP I2C LCD Example using XC8
Arduino PCF8574 LCD module

In this example, The micro-controller send a counter variable to the display. It updates for every 250ms. I use the I2C module of PIC16F887. The program written in C using MPLABX IDE and its XC8 C compiler. It's free to use.

  1. /*
  2.  * File: main.c
  3.  * Author: Admin
  4.  *
  5.  * Created on January 19, 2024, 3:36 PM
  6.  */
  7.  
  8. #include <xc.h>
  9. #include "config.h"
  10. #include "pcf8574.h"
  11. #include <stdio.h>
  12.  
  13. #define _XTAL_FREQ 8000000UL
  14.  
  15. #define RS 0
  16. #define RW 1
  17. #define EN 2
  18. #define BL 3
  19.  
  20. __bit backLight=0;
  21.  
  22. void i2c_lcdCommand(uint8_t command){
  23. uint8_t data;
  24. data=command&0xF0;
  25. pcf8574Write(data|(backLight<<BL)|(1<<EN));
  26. __delay_us(10);
  27. pcf8574Write(data|(backLight<<BL));
  28. __delay_us(50);
  29.  
  30. data=command<<4;
  31. pcf8574Write(data|(backLight<<BL)|(1<<EN));
  32. __delay_us(10);
  33. pcf8574Write(data|(backLight<<BL));
  34. __delay_us(50);
  35. }
  36.  
  37. void i2c_lcdData(uint8_t command){
  38. uint8_t data;
  39. data=command&0xF0;
  40. pcf8574Write(data|(backLight<<BL)|(1<<EN)|(1<<RS));
  41. __delay_us(10);
  42. pcf8574Write(data|(backLight<<BL)|(1<<RS));
  43. __delay_us(50);
  44.  
  45. data=command<<4;
  46. pcf8574Write(data|(backLight<<BL)|(1<<EN)|(1<<RS));
  47. __delay_us(10);
  48. pcf8574Write(data|(backLight<<BL)|(1<<RS));
  49. __delay_us(50);
  50. }
  51.  
  52. void i2c_lcdXY(int8_t x, int8_t y){
  53. int8_t addr[]={0x80,0xC0};
  54. i2c_lcdCommand(addr[y-1]+x-1);
  55. }
  56.  
  57. void i2c_lcdText(int8_t *txt){
  58. while(*txt) i2c_lcdData(*txt++);
  59. }
  60.  
  61. void i2c_lcdClear(void){
  62. i2c_lcdCommand(0x01);
  63. __delay_ms(5);
  64. }
  65.  
  66. void i2c_lcdInit(void){
  67. i2c_init(100000);
  68. __delay_us(10);
  69. pcf8574Write(0);
  70. __delay_ms(10);
  71. i2c_lcdCommand(0x33);
  72. __delay_us(10);
  73. i2c_lcdCommand(0x32);
  74. __delay_us(10);
  75. i2c_lcdCommand(0x28);
  76. __delay_us(10);
  77. i2c_lcdCommand(0x0F);
  78. __delay_us(10);
  79. i2c_lcdCommand(0x01);
  80. __delay_ms(5);
  81. i2c_lcdCommand(0x06);
  82. __delay_us(10);
  83. }
  84.  
  85. void main(void) {
  86. OSCCONbits.IRCF=7;
  87. i2c_lcdInit();
  88. backLight=1;
  89. __delay_ms(1000);
  90. i2c_lcdText(" PIC16F887 I2C");
  91. i2c_lcdXY(1,2);
  92. i2c_lcdText(" PCF8574AP LCD");
  93. long counter=0;
  94. uint8_t msg[10];
  95. __delay_ms(2000);
  96. i2c_lcdClear();
  97. i2c_lcdCommand(0x0C);
  98. i2c_lcdText("Counter Variable");
  99. while(1){
  100. sprintf(msg,"%u",counter);
  101. i2c_lcdXY(1,2);
  102. i2c_lcdText(msg);
  103. counter++;
  104. __delay_ms(250);
  105. }
  106. return;
  107. }
  108.  

I use Proteus VSM to design and simulating this program before it will be tested on a prototype board.

PIC16F887 PCF8574AP I2C LCD Example using XC8
Simulating Program in Proteus

PIC16F887 PCF8574AP I2C LCD Example using XC8
Simulating Program in Proteus


Click here to download this example from GitHub.

Thursday, January 18, 2024

PIC16F887 PCF8574AP I2C 4x4 KeyPad using XC8

The PCF8574 series is popular among Arduino users especially the character LCD driving. Its output port is 8-bit bi-directional. So we can use this chip to make a 4x4 matrix keypad. The microprocessor uses only two pins (SDA and SCL) via its I2C communication module to interface with this serial matrix keypad.

PIC16F887 PCF8574AP I2C 4x4 KeyPad using XC8
Hardware Experiment on PIC16F887 Prototype Board

I use a 4x4 membrane keypad module for Arduino. It's low cost that we doesn't need to make our own PCB.

PIC16F887 PCF8574AP I2C 4x4 KeyPad using XC8
16 Key Membrane Switch Keypad 4X4 3X4 Matrix Keyboard For Arduino Diy Kit
 

The I2C slave address of PCF8574AP (DIP-16) is 0x70 (write) and 0x71 (read) when A2...A0 are wired to GND.

PIC16F887 PCF8574AP I2C 4x4 KeyPad using XC8
PCF8574AP 16-Pin DIP

I use the on-board TinSharp TC1604A-01 16x4 character LCD module I posses.

PIC16F887 PCF8574AP I2C 4x4 KeyPad using XC8

I use the 4-bit data transfer mode to save the I/O pins of micro-controller.

PIC16F887 PCF8574AP I2C 4x4 KeyPad using XC8

Using the MPLABX IDE and its XC8 C compiler is pretty easy. Generated firmware is light-weight comparable the Assembly language. This program keep scanning the key press. Key value will show on the character LCD. The display is auto make a new line when ever the character counts reach 16. The the display is full it will clear the display and return home.

  1. /*
  2.  * File: main.c
  3.  * Author: Admin
  4.  *
  5.  * Created on January 17, 2024, 9:07 PM
  6.  */
  7.  
  8. #include <xc.h>
  9. #include "config.h"
  10. #include "lcd.h"
  11. #include "pcf8574.h"
  12.  
  13. #define _XTAL_FREQ 8000000UL
  14.  
  15. uint8_t key_16[][4]={'1','2','3','A',
  16. '4','5','6','B',
  17. '7','8','9','C',
  18. '*','0','#','D'};
  19.  
  20. uint8_t keyScan(void){
  21. char data=0,temp,key;
  22. for(uint8_t i=0;i<4;i++){
  23. data=0xFF;
  24. data&=~(1<<i);
  25. pcf8574Write(data);
  26. __delay_ms(5);
  27. data=pcf8574Read();
  28. data&=0xF0;
  29. if((data&0x10)==0) {temp=key_16[i][0]; break;}
  30. else if((data&0x20)==0){temp=key_16[i][1]; break;}
  31. else if((data&0x40)==0){temp=key_16[i][2]; break;}
  32. else if((data&0x80)==0){temp=key_16[i][3]; break;}
  33. else temp=0;
  34. __delay_ms(10);
  35. }
  36. return temp;
  37. }
  38.  
  39. void main(void) {
  40. OSCCONbits.IRCF=7;
  41. i2c_init(100000);
  42. lcdInit();
  43. __delay_ms(100);
  44. uint8_t temp,charCount=0,newLine=0,line=1;
  45. while(1){
  46. temp=keyScan();
  47. if(temp!=0){
  48. lcdData(temp);
  49. charCount++;
  50. __delay_ms(250);
  51. }
  52. if(charCount>=16){
  53. newLine=1;
  54. charCount=0;
  55. line+=1;
  56. }
  57. if(newLine){
  58. newLine=0;
  59. if(line==2) lcdXY(1,2);
  60. else if(line==3) lcdXY(1,3);
  61. else if(line==4) lcdXY(1,4);
  62. else{
  63. lcdCommand(0x01);
  64. __delay_ms(5);
  65. line=1;
  66. }
  67. }
  68. }
  69. return;
  70. }
  71.  

Click here to download this example from GitHub. I use Proteus to draw its schematic.

PIC16F887 PCF8574AP I2C 4x4 KeyPad using XC8
Program Simulation

Proteus simulation will work at slow speed due to custom firmware simulation. Using the prototype board, the firmware operation works very well without error and slowness. 

PIC16F887 PCF8574AP I2C 4x4 KeyPad using XC8

This DIY PCB has a 20MHz crystal oscillator. But the PIC16F887 has an internal 8MHz RC oscillator. So I left the XTAL1 and XTAL2 pin unconnected.

PIC16F887 PCF8574AP I2C 4x4 KeyPad using XC8

Keypad scanning runs very flexible without error on this PIC DIY prototype board.

PIC16F887 PCF8574AP I2C 4x4 KeyPad using XC8


 

If you use the PCF8574 you need to change its I2C slave address.

Monday, January 15, 2024

PIC16F887 PCF8574 I2C Example using XC8

Overview

The PCF8574 is an 8-bit input/output (I/O) expander for the two-wire bidirectional bus (I2C), designed for 2.5V to 6V VCC operation. 

The PCF8574 device provides general-purpose remote I/O expansion for most micro-controller
families by way of the I2C interface [serial clock (SCL), serial data (SDA)]. 

PIC16F887 PCF8574 I2C Example using XC8
Simulating Program

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

PIC16F887 PCF8574 I2C Example using XC8
PCF8574 Interfacing Diagram


PIC16F887 PCF8574 I2C Example using XC8
PCF8574AP DIP-16

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

PIC16F887 PCF8574 I2C Example using XC8
Pin Configuration and Functions

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

PIC16F887 PCF8574 I2C Example using XC8
Simplified Block Diagram of Device

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

PIC16F887 PCF8574 I2C Example using XC8
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.

PIC16F887 PCF8574 I2C Example using XC8
Address Reference
The Master I2C device need to write device slave address followed by output port data twice.
 
PIC16F887 PCF8574 I2C Example using XC8
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.

PIC16F887 PCF8574 I2C Example using XC8
PCF8574 Read Mode
We can use various I/O devices with this chip.

PIC16F887 PCF8574 I2C Example using XC8
PCF8574 Typical Application

 Interrupt Output (INT) pin is optional.

PIC16F887 MPLABX IDE and XC8 Programming

The PIC16F887 micro-controller has a high speed Inter Integrated Circuit (I2C) module that can operate in both master and slave mode.

In this example, I set up its I2C module to operate in master mode at 100kHz serial clock frequency. The program keeps reading input data from PCF8574 I/O port, its 8-bit content will show on PORTD of PIC16F887. 

  1. /*
  2.  * File: main.c
  3.  * Author: Admin
  4.  *
  5.  * Created on January 15, 2024, 8:17 PM
  6.  */
  7.  
  8.  
  9. #include <xc.h>
  10. #include "config.h"
  11. #include "i2c.h"
  12.  
  13. #define _XTAL_FREQ 8000000UL
  14. #define PCF8574_W 0x40
  15. #define PCF8574_R 0x41
  16.  
  17. void pcf8574Write(uint8_t data){
  18. i2c_start();
  19. i2c_write(PCF8574_W);
  20. i2c_write(0x20);
  21. i2c_write(data);
  22. i2c_stop();
  23. }
  24.  
  25. uint8_t pcf8574Read(){
  26. uint8_t data;
  27. pcf8574Write(0xFF);
  28.  
  29. i2c_start();
  30. i2c_write(PCF8574_R);
  31. data=i2c_read(0);
  32. i2c_stop();
  33. return data;
  34. }
  35. void main(void) {
  36. OSCCONbits.IRCF=7;
  37. i2c_init(100000);
  38. PORTD=0;
  39. TRISD=0;
  40. while(1){
  41. PORTD=pcf8574Read();
  42. __delay_ms(200);
  43. }
  44. return;
  45. }
  46.  

Since A2...A0 pins of PCF8574 are logic 0. So its device write address is 0x40, and 0x41 for device read address.

Click here to download its source file. See Also,

320x50

Search This Blog

Labels

25AA010A (1) 8051 (7) 93AA46B (1) ADC (30) Analog Comparator (1) Arduino (15) ARM (6) AT89C52 (7) ATMega32 (57) AVR (58) CCS PICC (28) DAC (1) DHT11 (2) Display (106) Distance Sensor (3) DS18B20 (3) dsPIC (3) dsPIC30F1010 (3) dsPIC30F2010 (1) EEPROM (5) Environment Sensor (4) esp8266 (1) I2C (29) Input/Output (68) Interrupt (19) Keil (5) Keypad (10) LCD (48) Master/Slave (1) MAX7221 (1) MCP23017 (5) MCP23S17 (4) Meter (3) MikroC (2) Motor (15) MPLABX (73) Nokia 5110 LCD (3) OLED (2) One-Wire (6) Oscillator (8) PCB (10) PCD8544 (3) PCF8574 (5) PIC (108) PIC12F (3) 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) PWM (11) RTC (9) Sensor (11) SH1106 (1) Shift Register (11) Shift Registers (3) SPI (24) STM32 (6) STM32 Blue Pill (6) STM32CubeIDE (6) STM32F103C8T6 (6) SysTick (3) temperature sensor (11) Thermometer (21) Timer/Counter (31) TM1637 (2) UART (7) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (96)

tyro-728x90