Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PIC16F1459 I2C Master Ack receivement issue

Status
Not open for further replies.
I'm facing a weird issue. I've always used bit bangin I2C functions on my PIC16F1459, but now I want to use the MSSP (SPI,I2C Master Slave Peripheral). So I've started writing the functions according to the datasheet, Start, Stop, etc. The problem I have is my PIC won't ACK the data I send to the I2C EEPROM. It clearly says in the datasheet that the ACK status can be found at SSPCON2.ACKSTAT. So my guess was to poll this bit until the slave responds to my data, but the program hangs in the while Loop.

void vReadACK (void)
{
while(SSPCON2.ACKSTAT !=0);
}
And here's my write function, my I2CCheck function and I2C Master Initialization function

void vI2CEcrireOctet (UC ucData, UC ucRW)
{
vI2CCheck();
switch(ucRW)
{
case READ:
SSPBUF = ucData +1;
break;
case WRITE:
SSPBUF = ucData +0;
break;
}
vReadACK();
}

void vI2CCheck (void)
{
while(SSPCON2.ACKEN);//ACKEN not cleared, wait
while(SSPCON2.RCEN);//RCEN not cleared, wait
while(SSPCON2.PEN);//STOP not cleared, wait
while(SSPCON2.SEN);//Start not cleared, wait
while(SSPCON2.RSEN);//Rep start not cleared, wait
while(SSP1STAT.R_NOT_W);//TX not done wait
}

void vInitI2CMaster (void)
{
TRISB4_bit =1;//SDA IN
TRISB6_bit =1;//SCL IN
SSP1STAT.SMP =1;//No slew rate
SSP1STAT.CKE =0;//Disable SMBus inputs
SSPADD =0x27;//100 KHz
SSPCON1 =0b00101000;//I2C Master mode
SSPCON3 =0b00000000;//Nothing slave
}​

Just so you know, 24LC32A WriteProtect tied to VSS, A2-A1-A0 tied to GND, so adress 0xA0. 4k7 pull-ups are on I2C line. PIC16F1459 at 16MHz INTOSC. Writing a byte works, same for start and stop.

I'm completely stuck. I've went through the MSSP datasheet 5 to 6 times without finding any issue. Can you guys help?
 
I2C is more complicated than this. You need to follow the sequence - create a start condition, then send a slave address etc. Your code dosn't show anything of that.

You should read the datasheet. Do not confuse I2C with SPI - it's completely different.
 
I know I2C is complicated. I'm using MSSP module from PIC16F1459 which creates the "Start" and "Stop" condition. I'm using Saleae logic analyzer with I2C protocol, and it clearly shows Start, Adress OxAO, 1 byte of data, then stop. God please, I've read this datasheet 10 times, I'm an advanced PIC user and it's last try hope to get help that I've posted my question here. You should read the datasheet before posting this kind of answer.

For your interest, complete code :

Code:
#include "I2CMS.h"

void vInitI2CMaster (void)
{
   TRISB4_bit = 1;        //SDA IN
   TRISB6_bit = 1;        //SCL IN
   SSP1STAT.SMP = 1;      //No slew rate
   SSP1STAT.CKE = 0;      //Disable SMBus inputs
   SSPADD = 0x27;         //100 KHz
   SSPCON1 = 0b00101000;  //I2C Master mode
   SSPCON3 = 0b00000000;  //Rien de slave
}
void vInitI2CSlave (void)
{
   TRISB4_bit = 1;        //SDA IN
   TRISB6_bit = 1;        //SCL IN
   SSP1STAT.SMP = 1;      //No slew rate
   SSP1STAT.CKE = 0;      //Disable SMBus inputs
   SSPADD = 0b00110000;   //Adresse SLAVE 0x30
   SSPCON1 = 0b00110110;  //slave I2C start
   PIE1.SSP1IE = 1;       //Enable interruptions slave
}

void vI2CCheck (void)
{
   while (SSPCON2.ACKEN);     //ACKEN not cleared, wait
   while (SSPCON2.RCEN);      //RCEN not cleared, wait
   while (SSPCON2.PEN);       //STOP not cleared, wait
   while (SSPCON2.SEN);       //Start not cleared, wait
   while (SSPCON2.RSEN);      //Rep start not cleared, wait
   while (SSP1STAT.R_NOT_W);  //TX not done wait
}
void vI2CStart (void)
{
   vI2CCheck();          //Check bus is clear
   SSPCON2.SEN = 1;      //Start condition
}

void vI2CStop (void)
{
   vI2CCheck();          //Check bus is clear
   SSPCON2.PEN = 1;      //Stop condition
}

void vI2CReStart (void)
{
   vI2CCheck();          //Check bus is clear
   SSPCON2.RSEN = 1;     //Repeated start condition
}

void vReadACK (void)
{
   while (SSPCON2.ACKSTAT != 0);
}

void vSendACK (UC ucAck)
{
   vI2CCheck();
   SSPCON2.ACKDT = ucAck;
   SSPCON2.ACKEN = 1;
}
void vI2CEcrireOctet (UC ucData, UC ucRW)
{
   vI2CCheck();
   switch (ucRW)
    {
      case READ:
        SSPBUF = ucData + 1;
      break;
      case WRITE:
        SSPBUF = ucData + 0;
      break;
    }
   //vReadACK();
}

UC ucI2CLireOctet (UC ucAck)
{
   vI2CCheck();
   SSPCON2.RCEN = 1;
   while (SSPCON2.RCEN != 0);
   vSendACK (ucAck);
   return (SSPBUF);
}
 
You should also see one more SCL cycle. MSSP is supposed to insert it automatically. If you don't see it, something is wrong with it. During this extra SCL cycle, the memory IC is supposed to recognize the address and pull SDA low.

Do you see the IC pulling SDA low to ack after you transmit the address?
 
I've found the answer to this redundant problem. My I2C functions we're perfect. The problem is the slave. It needs a "Bus Free Time" between each write sequences. I've simply added a simple delay function of about 10ms and worked right away.
 
I used the exact same memory IC and it worked ok without waiting between writes. You probably need much less than 10ms.
 
Well it depends on the I2C clock, a function of the PIC clock. I've did several test, and 400uS worked, a little more than needed by the 24LC32A to free it's bus. Thanks.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top