/* * This program writes and reads an I2C device on the Wytec EduBase board. * * The Wytec EduBase board has a real-time clock device (BQ32000) with I2C * interface. This program writes a zero to the second register (address 0) * of the RTC and reads it back repetitively and display the second count * at the LEDs. Since the second register uses binary coded decimal format, * the LEDs will count up from 0 to 9 in binary and wrap around to 0. */ #include "TM4C123GH6PM.h" void delayMs(int n); void delayUs(int n); void I2C1_init(void); unsigned char I2C1_byteWrite(int slaveAddr, unsigned char memAddr, const unsigned char data); unsigned char I2C1_byteRead(int slaveAddr, unsigned char memAddr, unsigned char* data); #define SLAVE_ADDR 0x68 // 1101 000. int main(void) { unsigned char readback; unsigned char error; SYSCTL->RCGCGPIO |= 0x02; // enable clock to GPIOB readback = SYSCTL->RCGCGPIO; // enable PORTB 3-0 as output for LEDs GPIOB->DIR |= 0x0F; // set PORTB 3-0 as output pins GPIOB->DEN |= 0x0F; // set PORTB 3-0 as digital pins I2C1_init(); error = I2C1_byteWrite(SLAVE_ADDR, 0, 0); if (error) { GPIOB->DATA = error; while(1) ; // if I2C error, stop here } for (;;) { error = I2C1_byteRead(SLAVE_ADDR, 0, &readback); if (error) { GPIOB->DATA = error; while(1) ; // if I2C error, stop here } GPIOB->DATA = readback; delayMs(500); } } void I2C1_init(void) { SYSCTL->RCGCI2C |= 0x02; // enable clock to I2C1 SYSCTL->RCGCGPIO |= 0x01; // enable clock to GPIOA // PORTA 7, 6 for I2C1 GPIOA->AFSEL |= 0xC0; // PORTA 7, 6 for I2C1 GPIOA->PCTL &= ~0xFF000000; // PORTA 7, 6 for I2C1 GPIOA->PCTL |= 0x33000000; GPIOA->DEN |= 0xC0; // PORTA 7, 6 as digital pins GPIOA->ODR |= 0x80; // PORTA 7 as open drain I2C1->MCR = 0x10; // master mode I2C1->MTPR = 7; // 100 kHz @ 16 MHz } static int I2C1_wait_till_done(void) { while(I2C1->MCS & 1); // wait until I2C1 master is not busy return I2C1->MCS & 0xE; // return I2C1 error code } // Write one byte unsigned char I2C1_byteWrite(int slaveAddr, unsigned char memAddr, const unsigned char data) { unsigned char error; // write a byte: S-(addr+w)-ACK-memAddr-ACK-data-ACK-P I2C1->MSA = slaveAddr << 1; I2C1->MDR = memAddr; I2C1->MCS = 3; // S-(addr+w)-ACK-memAddr-ACK error = I2C1_wait_till_done(); // wait until write is complete if (error) return error; I2C1->MDR = data; I2C1->MCS = 5; // -data-ACK-P error = I2C1_wait_till_done(); // wait until write is complete while(I2C1->MCS & 0x40); // wait until bus is not busy error = I2C1->MCS & 0xE; return error; } // Read one byte unsigned char I2C1_byteRead(int slaveAddr, unsigned char memAddr, unsigned char* data) { unsigned char error; // read: S-(addr+w)-ACK-memAddr-ACK-R-(addr+r)-ACK-data-NACK-P I2C1->MSA = slaveAddr << 1; I2C1->MDR = memAddr; I2C1->MCS = 3; // S-(addr+w)-ACK-memAddr-ACK error = I2C1_wait_till_done(); if (error) return error; I2C1->MSA = (slaveAddr << 1) + 1; // restart: -R-(addr+r)-ACK I2C1->MCS = 7; // -S-(addr+r)-NACK-P error = I2C1_wait_till_done(); if (error) return error; *data = I2C1->MDR; while(I2C1->MCS & 0x40); // wait until bus is not busy error = I2C1->MCS & 0xE; return error; } // delay n milliseconds (16 MHz CPU clock) void delayMs(int n) { int i, j; for(i = 0 ; i < n; i++) for(j = 0; j < 3180; j++) {} // do nothing for 1 ms } // delay n microseconds (16 MHz CPU clock) void delayUs(int n) { int i, j; for(i = 0 ; i < n; i++) for(j = 0; j < 3; j++) {} // do nothing for 1 ms } // 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; }