I2C EEPROM & PIC32
Few useful examples, how to force HW I2C module of PIC32MX to collaborate with I2C EEPROM chip, like Microchip’s 24LC1025.
I2C Module Initialization
void eepromInit(void) { I2CConfigure(EE_I2C, I2C_ENABLE_SLAVE_CLOCK_STRETCHING | I2C_ENABLE_HIGH_SPEED); I2CSetFrequency(EE_I2C, GetPeripheralClock(),400000); I2CEnable(EE_I2C, TRUE); }
For single master-slave enviroment, you can omit I2C_ENABLE_SLAVE_CLOCK_STRETCHING config word.
Reading from EEPROM.
void eepromRead(unsigned int ee_addr, unsigned char *buf, unsigned int len) { // Start StartI2C2(); IdleI2C2(); MasterWriteI2C2(EE_ADDR | 0); // Write control byte IdleI2C2(); if (I2C2STATbits.ACKSTAT) return; // NACK'ed by slave ? MasterWriteI2C2(ee_addr >> 8); // Address of operation IdleI2C2(); if (I2C2STATbits.ACKSTAT) return; // NACK'ed by slave ? MasterWriteI2C2(ee_addr); // Address of operation IdleI2C2(); if (I2C2STATbits.ACKSTAT) return; // NACK'ed by slave ? RestartI2C2(); IdleI2C2(); MasterWriteI2C2(EE_ADDR | 1); // Read command IdleI2C2(); if (I2C2STATbits.ACKSTAT) return; // NACK'ed by slave ? while (len) { I2C2CONbits.RCEN = 1; while(!DataRdyI2C2()); *buf = I2C2RCV; buf++; len--; if (len) { // ACK the slave I2C2CONbits.ACKDT = 0; I2C2CONbits.ACKEN = 1; } else { // NACK the slave I2C2CONbits.ACKDT = 1; I2C2CONbits.ACKEN = 1; } while(I2C2CONbits.ACKEN == 1); /* Wait till ACK/NACK sequence is over */ } StopI2C2(); IdleI2C2(); }
where EE_ADDR is #defined as 0xA0 , corresponding to EEPROM’s control word.
This function has limited functionality – it can only read first 0xFFFF bytes of data from EEPROM – no code provided to set B0 bit in config word (see datasheet).
Writing to EEPROM.
void eepromWritePage(unsigned int ee_addr, unsigned char *buf, unsigned int len) { // Start StartI2C2(); IdleI2C2(); MasterWriteI2C2(EE_ADDR | 0); // Write control byte IdleI2C2(); if (I2C2STATbits.ACKSTAT) return; // NACK'ed by slave ? MasterWriteI2C2(ee_addr >> 8); // Address of operation IdleI2C2(); if (I2C2STATbits.ACKSTAT) return; // NACK'ed by slave ? MasterWriteI2C2(ee_addr); // Address of operation IdleI2C2(); if (I2C2STATbits.ACKSTAT) return; // NACK'ed by slave ? while (len) { MasterWriteI2C2(*buf++); IdleI2C2(); if (I2C2STATbits.ACKSTAT) return; // NACK'ed by slave ? len--; } StopI2C2(); IdleI2C2(); // Do acknowledge poll (indicating, that eeprom has completed flashing our bytes while(1) { StartI2C2(); IdleI2C2(); MasterWriteI2C2(EE_ADDR | 0); // Call the eeprom IdleI2C2(); if (I2C2STATbits.ACKSTAT==0) break; StopI2C2(); IdleI2C2(); } StopI2C2(); IdleI2C2(); } void eepromWrite(unsigned int ee_addr, unsigned char *buf, unsigned int len) { int bytes_to_write; while (len) { bytes_to_write = 0x80; // default xx1025 pagesize if (len<bytes_to_write) bytes_to_write = len; eepromWritePage(ee_addr, buf, bytes_to_write); len-=bytes_to_write; buf+=bytes_to_write; ee_addr+=bytes_to_write; } }
because of limited amount of data for single write command (page size of this eeprom is 128 bytes), you should call eepromWrite(…) function, which can handle writes in 0x0000-0xffff addresses in eeprom space. (the same limitation with B0 bit as for eepromRead() func).
Have fun.