/* * This program reads/writes the EEPROM on the Digilent Orbit BoosterPack * The Orbit BoosterPack has a Microchip 24LC256 I2C EEPROM. */ #include "TM4C123GH6PM.h" void I2C0_init(void); int I2C0_byteRead(int slaveAddr, short memAddr, unsigned char* data); int I2C0_byteWrite(int slaveAddr, short memAddr, const unsigned char data); #define SLAVE_ADDR 0x54 /* 1010 100. Microchip 24LC256 */ int main(void) { volatile int error; unsigned char buffer[8]; short addr; I2C0_init(); addr = 0x34; error = I2C0_byteWrite(SLAVE_ADDR, addr, 'M'); error = I2C0_byteRead(SLAVE_ADDR, addr, buffer); while(1) { } } // Wait until I2C master is not busy and return error code. // Busy status bit has a latency. The function call overhead takes care of it. static int I2C_wait_till_done(void) { // wait until I2C master is not busy while(I2C0->MCS & 1); // return I2C error code return I2C0->MCS & 0xE; } void I2C0_init(void) { SYSCTL->RCGCGPIO |= 0x02; // enable clock to GPIOB SYSCTL->RCGCI2C |= 0x01; // enable clock to I2C0 // PORTB 2, 3 for I2C0 GPIOB->AFSEL |= 0x0C; // PORTB 2, 3 for I2C0 GPIOB->PCTL &= ~0x0000FF00; // PORTB 2, 3 for I2C0 GPIOB->PCTL |= 0x00003300; GPIOB->DEN |= 0x0C; // PORTB 2, 3 as digital pins GPIOB->ODR |= 0x08; // PORTB 2, 3 as open drain I2C0->MCR = 0x10; // master mode I2C0->MTPR = 6; // 100 kHz @ 16 MHz //I2C0->MTPR = 24; // 50 kHz @ 50 MHz } // Write one byte with two byte memory address write first int I2C0_byteWrite(int slaveAddr, short memAddr, const unsigned char data) { int error; // write: S-(addr+w)-ACK-addrH-ACK-addrL-ACK-data-ACK-P I2C0->MSA = slaveAddr << 1; I2C0->MDR = (memAddr >> 8) & 0xFF; // send high byte of memory address I2C0->MCS = 3; // S-(addr+w)-ACK-addrH-ACK error = I2C_wait_till_done(); // wait until write is complete if (error) return error; I2C0->MDR = memAddr & 0xFF; // send low byte of memory address I2C0->MCS = 1; // -addrL-ACK- error = I2C_wait_till_done(); // wait until write is complete if (error) return error; I2C0->MDR = data; // write the data I2C0->MCS = 5; // -data-ACK-P error = I2C_wait_till_done(); // wait until write is complete while(I2C0->MCS & 0x40); // wait until bus is not busy error = I2C0->MCS & 0xE; if (error) return error; // polling for programming complete (wait until an ack for address write) do { I2C0->MSA = slaveAddr << 1; I2C0->MDR = memAddr; I2C0->MCS = 7; // S-(addr+w)-ACK-addr-ACK=P error = I2C_wait_till_done(); // wait until write is complete while(I2C0->MCS & 0x40); // wait until bus is not busy } while(I2C0->MCS & 4); // repeat if address was not acked return 0; } // Read one byte with two byte memory address write first int I2C0_byteRead(int slaveAddr, short memAddr, unsigned char* data) { int error; // read: S-(addr+w)-ACK-addrH-ACK-addrL-ACK-S-(addr+r)-ACK-data-NACK-P I2C0->MSA = slaveAddr << 1; I2C0->MDR = (memAddr >> 8) & 0xFF; I2C0->MCS = 3; // S-(addr+w)-ACK-addrH-ACK error = I2C_wait_till_done(); if (error) return error; I2C0->MDR = memAddr & 0xFF; // send low byte of memory address I2C0->MCS = 0x1; // -addrL-ACK- error = I2C_wait_till_done(); if (error) return error; I2C0->MSA = (slaveAddr << 1) + 1; // restart and read I2C0->MCS = 0x7; // -S-(addr+r)-data-NACK-P error = I2C_wait_till_done(); *data = I2C0->MDR; // get the data read while(I2C0->MCS & 0x40); // wait until bus is not busy return 0; } // This function is called by the startup assembly // code to perform system specific initialization tasks. void SystemInit(void) { // Grant coprocessor access // This is required since TM4C123G has // a floating point coprocessor SCB->CPACR |= 0x00f00000; }