0

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;  //Rien de 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.

I'm completely stuck. I've went through the MSSP datasheet 5 to 6 times without finding any issue. Can you guys help?

And here's my logic analyzer preview (removing the while inside vReadAck() )

Jean-francois
  • 316
  • 1
  • 9
  • Your question suggests that you think that master device should be ACK'ing each byte it sends to the slave. In fact it's the receiver of the byte, in this case the slave, who's ACKs each packet. From your logic analyzer screen shot it appears that your slave device is NAK – Ross Ridge Aug 18 '14 at 23:33
  • I totally know that it's the salve who's ACK'ing the Data the master send to it. The problem is the master has to change it's pin to an input state to actually "read" the ACK the slave sends. That's why I poll SSPCON2.ACKSTAT, but the pic seems to never get the ACK. It should work, the adress is the right one, 0xA0. – Jean-francois Aug 18 '14 at 23:59

2 Answers2

0

Well it looks like I've found the answer to my question. What I was doing was the exact way of doing this. The problem seemed to be the Bus Free Time delay required for the slave to respond. At 16Mhz, my I2C was probably too fast for the EEPROM memory. So I've added a small Delay function right after the stop operation, so the write sequences are delayed and BAM, worked.

Bus free time: Time the bus must be free before a new transmission can start.

Jean-francois
  • 316
  • 1
  • 9
0

Despite the fact you "totally know" know "PIC won't ACK the data I send to the I2C EEPROM" because it's not supposed to, you still seem to misunderstand how I2C acknowledgements are supposed to work. They're called acknowledgements because they can be both positively (ACK) and negatively (NAK) acknowledged. If you look at the the analyzer screen shot you posted you'll find that its quite clearly labelled each byte being sent as having been NAK'ed by the transmitter.

To properly check for I2C ACKs you should be polling the trailing edge of the ACKTIM bit, and then checking the ACKSTAT bit to find out whether the slave transmitted an ACK or a NAK bit. Something like this:

int
vReadACK() {
    while(!SSPCON3.ACKTIM);
    while(SSPCON3.ACKTIM);
    return SSPCON2.ACKSTAT;
}

As for why your slaved device is apparently NAKing each byte it isn't clear from the code you've posted, but there's a couple of notable omissions from your code. You need to generate start and stop conditions but you've shown no code to do this.

Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
  • I did not post this code because these part do work efficiently. I think it's simply about the way I've written my question. Yes, the pic is the master, but it's the slave (in my case the 24LC32A) which is sending an ACK (if the adress/data timing is matching) or a NACK (if the adress &| data is NOT matching). As said, I've always used bit banging I2C functions that I wrote, so I do know the ACK and NACK issue. Looking again at my question, I think it was wrongly spelled. – Jean-francois Aug 19 '14 at 01:02