I am writing code for a PIC32MX250F128B to interface with the Microchip 24LC02B EEPROM with I2C interface. I have followed the datasheet of the EEPROM, the PIC32 and section 24 of the PIC32 family reference manual very closely and attempted to write code to interface with the EEPROM. I do not get any "hang" on any of the tests for the bits that need to be cleared/set after eg. an ACK is received - the code executes completely. However, when I check the value of the data variable right at the end of the readEeprom function, I just get a Null-character (after writing an 'H' in the EEPROM memory address specified, in byte write mode (page write code is commented out with #if)). This indicates that either the write did not occur properly, or the read did not occur properly.
I do not have access to an oscilloscope or logic analyzer to check what exactly happens on the SDA and SCL lines.
The PIC32 oscillator is set to 8 MHz and I intended to use a 100 kHz baud rate for communication with the EEPROM. So therefore, using the equation I2CBRG = (PBCLK/(2*FSCK))-2, as found in section 24 of the PIC32 family reference documents, I use 0x26 for theI2CBRG value.
Perhaps someone could spot if something is wrong in my code? I have tried to find the problem over a day now, but have not succeeded.
Here is my code:
I would greatly appreciate any help that anyone can offer. Thanks in advance.
I do not have access to an oscilloscope or logic analyzer to check what exactly happens on the SDA and SCL lines.
The PIC32 oscillator is set to 8 MHz and I intended to use a 100 kHz baud rate for communication with the EEPROM. So therefore, using the equation I2CBRG = (PBCLK/(2*FSCK))-2, as found in section 24 of the PIC32 family reference documents, I use 0x26 for theI2CBRG value.
Perhaps someone could spot if something is wrong in my code? I have tried to find the problem over a day now, but have not succeeded.
Here is my code:
Code:
/* Interface test for I2C EEPROM with PIC32
*/
#include <plib.h>
#include <p32xxxx.h>
/* Pin outline:
* SCL1 - pin 17 - (EEPROM pin 6)
* SDA1 - pin 18 - (EEPROM pin 5)
* WP - pin 16 (RB7) (EEPROM pin 7) - Currently connected to GND
*/
//configuration bits
// DEVCFG3
//#pragma config PMDL1WAY = OFF // Peripheral Module Disable Configuration (Allow multiple reconfigurations)
//#pragma config IOL1WAY = OFF // Peripheral Pin Select Configuration (Allow multiple reconfigurations)
//#pragma config FUSBIDIO = OFF // USB USID Selection (Controlled by the USB Module)
//#pragma config FVBUSONIO = OFF // USB VBUS ON Selection (Controlled by USB Module)
// DEVCFG2
#pragma config FPLLIDIV = DIV_1 // PLL Input Divider (12x Divider)
#pragma config FPLLMUL = MUL_24 // PLL Multiplier (24x Multiplier)
//#pragma config UPLLIDIV = DIV_1 // USB PLL Input Divider (12x Divider)
//#pragma config UPLLEN = OFF // USB PLL Enable (Disabled and Bypassed)
#pragma config FPLLODIV = DIV_1 // System PLL Output Clock Divider (PLL Divide by 256)
// DEVCFG1
#pragma config FNOSC = FRC // Oscillator Selection Bits (Fast RC Osc (FRC))
#pragma config FSOSCEN = OFF // Secondary Oscillator Disnable (Disabled)
#pragma config IESO = ON // Internal/External Switch Over (Enabled)
#pragma config POSCMOD = OFF // Primary Oscillator Configuration (Primary osc disabled)
#pragma config OSCIOFNC = OFF // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_1 // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/1)
#pragma config FCKSM = CSECMD // Clock Switching and Monitor Selection (Clock Switch Disable, FSCM Disabled)
#pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1:1048576)
//#pragma config WINDIS = OFF // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode)
#pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
//#pragma config FWDTWINSZ = WISZ_25 // Watchdog Timer Window Size (Window Size is 25%)
// DEVCFG0
//#pragma config JTAGEN = OFF // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2)
#pragma config PWP = OFF // Program Flash Write Protect (Disable)
#pragma config BWP = OFF // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF // Code Protect (Protection Disabled)
//////////////////////////////////////////
#define EEPROM_WP PORTBbits.RB7
#define CLOCK 8000000
#define HIGH 1 //logic values declaration
#define LOW 0 //logic values declaration
char data[10];
void init(void);
void readEeprom(void);
void writeEeprom(void);
int main (void)
{
init();
writeEeprom();
readEeprom();
} /*main*/
void init(void)
{
SYSTEMConfigPerformance(CLOCK);
TRISBbits.TRISB7 = 0x01;
/*I2C peripheral overrides states of respective interface pins - no need
to set state of SCLx and SDAx pins here*/
/*Initialize I2C Peripheral*/
I2C1CONbits.DISSLW = HIGH; /*disable slew rate for 100 kHz*/
I2C1BRG = 0x26; /*Set Baud Rate Generator*/
I2C1CONbits.ON = HIGH;
int i = 0;
for (i = 0; i < 10; i++)
{
data[i] = '0';
} /*for*/
} /*init*/
void writeEeprom(void)
{
/*Assert start condition*/
I2C1CONbits.SEN = HIGH; /*This bit is automatically cleared by MCU*/
/*Test if START condition is completed - test interrupt I2C1MIF in IFS1*/
while (I2C1CONbits.SEN == HIGH); /*wait until start condition finishes*/
/*Send device address and write indication - address = "1010xxx0"*/
I2C1TRN = 0b10100000;
/*Wait for transmit buffer empty - indicates that write is completed*/
while (I2C1STATbits.TBF == HIGH);
/*Wait for ACK signal from device - bit will clear when ACK is received*/
while (I2C1STATbits.ACKSTAT == HIGH);
/*Send address for read - first HIGH byte, then LOW byte*/
/*Begin with the very first address page*/
I2C1TRN = 0x00;
while (I2C1STATbits.ACKSTAT == HIGH); /*wait for ACK from device*/
I2C1TRN = 0x00;
while (I2C1STATbits.ACKSTAT == HIGH);
#if 0 /*Page write*/
int i;
/*24LC02 can only write up to 8 bytes at a time*/
for (i = 0; i < 7; i++)
{
I2C1TRN = i;
/*Wait for transmit buffer empty - indicates that write is completed*/
while (I2C1STATbits.TBF == HIGH);
/*Generate ACK event*/
I2C1CONbits.ACKEN;
} /*for*/
/*Send stop event*/
I2C1CONbits.PEN;
#endif
#if 1 /*Byte write*/
I2C1TRN = 'H';
/*Wait for transmit buffer empty - indicates that write is completed*/
while (I2C1STATbits.TBF == HIGH);
/*Generate ACK event*/
I2C1CONbits.ACKEN;
/*Send stop event*/
I2C1CONbits.PEN;
#endif
} /*writeEeprom*/
void readEeprom(void)
{
/*Assert start condition*/
I2C1CONbits.SEN = HIGH; /*This bit is automatically cleared by MCU*/
/*Test if START condition is completed - test interrupt I2C1MIF in IFS1*/
while (I2C1CONbits.SEN == HIGH); /*wait until start condition finishes*/
/*Send device address and write indication - address = "1010xxx0"*/
I2C1TRN = 0b10100000;
/*Wait for transmit buffer empty - indicates that write is completed*/
while (I2C1STATbits.TBF == HIGH);
/*Wait for ACK signal from device - bit will clear when ACK is received*/
while (I2C1STATbits.ACKSTAT == HIGH);
/*Send address for read - first HIGH byte, then LOW byte*/
I2C1TRN = 0x00; /*Upper 8 bits of address*/
while (I2C1STATbits.ACKSTAT == HIGH); /*wait for ACK from device*/
I2C1TRN = 0x00; /*Lower 8 bits of address*/
while (I2C1STATbits.ACKSTAT == HIGH);
/*Send Repeated start event again*/
I2C1CONbits.RSEN = HIGH;
/*Test if START condition is completed - test interrupt I2C1MIF in IFS1*/
while (I2C1CONbits.SEN == HIGH); /*wait until start condition finishes*/
/*Send device address and read indication*/
I2C1TRN = 0b10100001;
while (I2C1STATbits.ACKSTAT == HIGH);
int i = 0;
#if 0 /*Sequential read*/
for (i = 0; i < 10; i++)
{
/*Enable receive mode - RCEN cleared after 8th bit is received*/
I2C1CONbits.RCEN = HIGH;
while (I2C1STATbits.RBF == LOW); /*Wait for receive buffer full*/
data[i] = I2C1RCV; /*Store receive buffer value in dataByte*/
while (I2C1STATbits.RBF == HIGH); /*Wait for receive buffer to clear*/
/*Generate ACK event - do not send ACK for last sequential read*/
if (i < 9)
{
I2C1CONbits.ACKEN;
} /*if*/
} /*for*/
/*Send stop event*/
I2C1CONbits.PEN;
#endif
#if 1 /*Single read*/
/*Enable receive mode - RCEN cleared after 8th bit is received*/
I2C1CONbits.RCEN = HIGH;
//while (I2C1STATbits.RBF == LOW); /*Wait for receive buffer full*/
data[i] = I2C1RCV; /*Store receive buffer value in dataByte*/
while (I2C1STATbits.RBF == HIGH); /*Wait for receive buffer to clear*/
/*Send stop event - no ACK event must be sent*/
I2C1CONbits.PEN;
#endif
} /*readEeprom()*/
I would greatly appreciate any help that anyone can offer. Thanks in advance.