Need help interfacing i2c PCF8575 with 8051 microcontroller - Page 1
Forum section: electronics / general

author: chiart_nor
author_rank: Newbie
timestamp: November 25, 2013, 03:42:32 pm
content: Hi All,I tried to use IO expansion chip that can controls up to 16 output by just using 2 wires (SDA and SCL). I'm using PCF8575 and interface with 8051 microcontroller (P89C51RD2HBA). I've connected 16 LED at the output side to see the result for the testing purpose. However, I'm stuck in the writing to the slave process, where i need to send 3 bytes of data to the slave.Based on my findings :1. We need to send 3 bytes of data : First is to determine slave address. In this case (0x40) as slave address based on PCF8575 datasheets.2. Second byte is the data P0-P7 . (0xAA)3. Third byte is the data P10-P17 . (0xF0)4. The LED should turn ON at P0-P7 (10101010) and at P10-P17 (11110000)But, the LED did not turn ON at all. The voltage at the output pin was around (1.1-1.3) which were not sufficient to turn on the LED.Below, i attached the sourcecode, and appreciate any help to see which part i go wrong.#include <REG51F.H>#include <stdio.h>#include <INPUT_OUTPUT.h>#include <delay1.h>// Function declarationsvoid initRS();void initPort();void I2C_Init();void I2C_Start();void I2C_Restart();void I2C_Stop();void I2C_SendAck();void I2C_SendNack();unsigned char I2C_Write(unsigned char Data);unsigned char I2C_Read();#define SDA p1_0#define SCL p1_1//Main functionvoid main(){initRS();initPort();I2C_Init();//unsigned char RxByte = 0;I2C_Start();I2C_Write(0x40);I2C_Write(0xAA);I2C_Write(0xF0);I2C_Read();I2C_SendAck();I2C_Stop();}//Function : I2C Write Byte transfer 3 bytesunsigned char I2C_Write(unsigned char Data){unsigned char i; // Variable to be used in for loopfor(i=0;i<8;i++) // Repeat for every bit{SCL = 0; // Make SCL pin lowdelay1(); // Data pin should change it's value,// when it is confirm that SCL is lowif ((Data & 0x40) == 0) //SDA = 1;elseSDA = 0;delay1();SCL = 1;Data<<=1;}//Get ACK from slaveSCL = 0;SDA = 1;delay1();SCL = 1;SCL = 0;return SDA;//for(i=0;i<8;i++) // Repeat for every bit{SCL = 0; // Make SCL pin lowdelay1(); // Data pin should change it's value,// when it is confirm that SCL is lowif ((Data & 0xAA) == 0) //10101010SDA = 1;elseSDA = 0;delay1();SCL = 1;Data<<=1;}//Get ACK from slaveSCL = 0;SDA = 1;delay1();SCL = 1;SCL = 0;return SDA;//for(i=0;i<8;i++) // Repeat for every bit{SCL = 0; // Make SCL pin lowdelay1(); // Data pin should change it's value,// when it is confirm that SCL is lowif ((Data & 0xF0) == 0) //11110000SDA = 1;elseSDA = 0;delay1();SCL = 1;Data<<=1;}//Get ACK from slaveSCL = 0;SDA = 1;delay1();SCL = 1;SCL = 0;return SDA ;}// Function : I2C Read Byteunsigned char I2C_Read(){unsigned char i, Data=0;for(i=0;i<8;i++){SCL = 0;SCL = 1;delay1();if(SDA)Data |=1;if(i<7)Data<<=1;}SCL = 0;SDA = 1;return Data;}// Function : To set initial values of SDA and SCLvoid I2C_Init(){SDA = 1; // Set SDA pin HIGHSCL = 1; // Set SCL pin LOW}// Function : Master sending START condition, HIGH to LOW transition on SDA while SCL keeping highvoid I2C_Start(){SCL = 1;SDA = 1;delay1();SDA = 0;SCL =1;delay1();}void I2C_Restart(){SDA = 1;SCL = 1;SDA = 0;}void I2C_Stop(){SDA = 0;SCL = 1;SDA = 1;}void I2C_Ack(){SDA = 0;SCL = 1;SCL = 0;}void I2C_Nack(){SDA = 1;SCL = 1;SCL = 0;}// Initialize serial portvoid initRS (){SCON = 0x50; // SCON: mode 1, 8-bit UART, enable rcvrTMOD = 0x20; // TMOD: timer 1, mode 2, 8-bit reloadTH1 = 253; // TH1: reload value for 9600 baud @ 11.0592MHz FDHTR1 = 1; // TR1: timer 1 runTI = 1; // TI: set TI to send first char of UART}//Initialize portvoid initPort(){P1 = 0xFF;P2 = 0x00;P0 = 0x00;}Any help highly appreciated.Thank you.

author: dannyf
author_rank: Super Contributor
timestamp: November 25, 2013, 04:19:23 pm
content: The first thing to do in those cases is to make sure that your low level routines work.

author: free_electron
author_rank: Super Contributor
timestamp: November 25, 2013, 04:25:00 pm
content: Wow. There is a ton of mistakes in that one...Quote from: chiart_nor on November 25, 2013, 03:42:32 pmDo you have any programming experience ? There are so many fundamental mistakes, not only against the protocol but also against basic programming.

author: chiart_nor
author_rank: Newbie
timestamp: November 26, 2013, 01:49:50 am
content: Hi,Thank you for the feedback and correcting my mistakes.Based on the codes below :I2C_Start();I2C_Write(0x40);I2C_Write(0xAA);I2C_Write(0xF0);I2C_Stop();}//Function : I2C Write Byte transfer 3 bytesunsigned char I2C_Write(unsigned char Data){unsigned char i; // Variable to be used in for loopfor(i=0;i<8;i++) // Repeat for every bit{SCL = 0; // Make SCL pin low // the start condition should have exited low !delay1(); // Data pin should change it's value,if ((Data & 0x80) == 0)// <<<<SDA = 0;elseSDA = 001;delay1();SCL = 1;Data<<=1;delay1();Scl=0; // all routines must exit with clock low, or bus clear !}From the highlighted code,if ((Data & 0x80) == 0) // Decimal = 128In the previous code, the address is if ((Data & 0x40) == 0), This is where i go wrong.I should define it as 0x80= 128 (8 bits) and to write the address to the slave, called the function I2C_Write.Correct me if I'm wrong.Thank you.Regards,