• AVR Freaks

Helpful ReplyXC32 I2C Peripheral Library

Author
ProfECE341
New Member
  • Total Posts : 23
  • Reward points : 0
  • Joined: 2011/07/06 10:21:54
  • Location: 0
  • Status: offline
2014/01/30 14:52:55 (permalink)

XC32 I2C Peripheral Library

As far as I can determine, the I2CAcknowledgeByte peripheral library function doe not actually generate either and ACK or NACK.  The I2C example provided with the XC32 ver 1.31 compiler correctly writes and reads single bytes with the 24LC256 EEPROM as written. HOWEVER, the example code doe not use the I2CAcknowledgeByte function when reading a single byte. Instead, the example code simply calls the function StopTransfer which sends a stop sequence  to terminate the read operation. Since the example code does not cause the master (PIC32) to generate the 9th clock pulse, the example code cannot be used to read multiple bytes from the EEPROM. I would like to hear what other XC32 users are experiencing in regards to the I2C peripheral library. 
#1
ProfECE341
New Member
  • Total Posts : 23
  • Reward points : 0
  • Joined: 2011/07/06 10:21:54
  • Location: 0
  • Status: offline
Re:XC32 I2C Peripheral Library 2014/01/30 16:04:31 (permalink) ☄ Helpfulby vksingh 2015/10/02 09:18:55
I do believe I've answered my own question. The following example for the "ReceiveOneByte" function that correctly sets the ACK bit. The last argument, "ack" indicates if the ACK or NAK bit is to be set by the master. Some I2C devices do not reset properly if the NAK is missing at the end of the read data transfer. So this function would need to be called multiple times after the device ID is written by the master (with the R/!W) bit set high to read multiple bytes from the EEPROM. This function can be used for any I2C port by changing the "i2c_port" argument.
 

 I2C_RESULT ReceiveOneByte( I2C_MODULE i2c_port, BYTE *data, BOOL ack ) 
{
  I2C_RESULT i2c_result = I2C_SUCCESS;
  if(I2CReceiverEnable(i2c_port, TRUE) == I2C_RECEIVE_OVERFLOW)
    {   printf("Error: I2C Receive Overflow\n");
        i2c_result =  I2C_RECEIVE_OVERFLOW;
    }
    else
    {        while(!I2CReceivedDataIsAvailable(i2c_port));
        I2CAcknowledgeByte(i2c_port, ack);
        while(!I2CAcknowledgeHasCompleted(i2c_port));
        *data = I2CGetByte(i2c_port);
    }   
return i2c_result; 
}

 
#2
pchidley
Super Member
  • Total Posts : 117
  • Reward points : 0
  • Joined: 2009/11/24 13:23:55
  • Location: Calgary, Alberta, Canada
  • Status: offline
Re:XC32 I2C Peripheral Library 2014/09/18 14:57:50 (permalink)
Hi Prof,
 
THANKS for posting your own answer.  Very annoying when people post questions here and no resolution is ever posted by anyone.  Even when they figure it out themselves or with a support ticket.
Kind of defeats the purpose of the forum.
As for your post.  
1. Yes, the MCHP example is TERRIBLE.  
2. Not only does it not handle the Ack correctly choosing as you say to simple Stop the transfer, but it gives you no idea how to read multiple bytes.  And the language is very misleading.  Why would you set up the Acknowledge then wait for it to complete then Get the Byte.  
Because I2CAcknowledgeByte should be called "clock in a byte followed by an Ack or Nak".
Then we wait for the "clock in a byte" to finish.
Then we transfer the data from the receive buffer.
 
I've been fighting this for a couple of hours and the bulb turned on when I saw you post your own answer.
 
Thanks, again.  Paul C.
post edited by pchidley - 2014/09/18 19:48:26
#3
JSC
New Member
  • Total Posts : 5
  • Reward points : 0
  • Joined: 2014/04/05 12:17:35
  • Location: Québec, Canada
  • Status: offline
Re:XC32 I2C Peripheral Library 2014/10/28 07:41:02 (permalink)
Bonjour,
 
Thanks for the solution, it works for me.
 
JS
#4
vksingh
New Member
  • Total Posts : 14
  • Reward points : 0
  • Joined: 2014/10/01 21:36:20
  • Location: 0
  • Status: offline
Re:XC32 I2C Peripheral Library 2015/10/02 09:59:49 (permalink)
Thanks ProfECE341, for the education.  I also got stuck when trying to sequentially read multiple bytes from the eeprom.
 
Apparently I2CReceiverEnable(i2c_port, TRUE) function is the key here.  It sets RCEN bit -
i2cRegisters->I2CxCONbits.RCEN = enable;
The RCEN bit  "Enables Receive mode for I 2 C, automatically cleared by module at end of 8-bit receive data byte". 
 
Thus counter-intuitively  I2CReceiverEnable() must be called to receive each byte and  I2CGetByte() does only this -     return(i2cRegisters->I2CxRCV);
 
#5
Jump to:
© 2019 APG vNext Commercial Version 4.5