/* * This program reads the accelerometer on the Digilent Orbit BoosterPack * and display the bits 7-4 of X axis on the LEDs. * The LEDs are connected to the MCU as: * LD1 PC6 * LD2 PC7 * LD3 PD6 * LD4 PB5 * The accelerometer is Analog Devices ADXL345 on I2C. */ #include "TM4C123GH6PM.h" void delayMs(int n); void I2C0_init(void); int I2C0_read(int slaveAddr, int memAddr, int byteCount, unsigned char* data); int I2C0_byteWrite(int slaveAddr, int memAddr, const unsigned char data); #define SLAVE_ADDR 0x1D /* 1001 111. Microchip TCN75A */ int main(void) { unsigned char data[6]; short x, y, z; volatile int rv; SYSCTL->RCGCGPIO |= 0x0E; // enable clock to GPIOB, GPIOC, GPIOD I2C0_init(); // initialize I2C0 I2C0_byteWrite(SLAVE_ADDR, 0x2D, 0x08); // start // configure output pins GPIOC->DIR |= 0xC0; // set PORTC 7, 6 as output pins GPIOC->DEN |= 0xC0; // set PORTC 7, 6 as digital pins GPIOD->DIR |= 0x40; // set PORTD 6 as output pins GPIOD->DEN |= 0x40; // set PORTD 6 as digital pins GPIOB->DIR |= 0x20; // set PORTB 5 as output pins GPIOB->DEN |= 0x20; // set PORTB 5 as digital pins while(1) { rv = I2C0_read(SLAVE_ADDR, 0x32, 6, data); // read six bytes of three axes x = data[1] << 8 | data[0]; // convert from two 8-bit data to one 16-bit data y = data[3] << 8 | data[2]; z = data[5] << 8 | data[4]; if (x < 0) // get absolute value of x x = -x; if(x & 0x10) // use bit 8 of conversion result to set LD1 GPIOC->DATA |= 0x40; else GPIOC->DATA &= ~0x40; if(x & 0x20) // use bit 9 of conversion result to set LD2 GPIOC->DATA |= 0x80; else GPIOC->DATA &= ~0x80; if(x & 0x40) // use bit 10 of conversion result to set LD3 GPIOD->DATA |= 0x40; else GPIOD->DATA &= ~0x40; if(x & 0x80) // use bit 11 of conversion result to set LD4 GPIOB->DATA |= 0x20; else GPIOB->DATA &= ~0x20; delayMs(100); } } // 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 } // Write one byte with register address write first int I2C0_byteWrite(int slaveAddr, int memAddr, const unsigned char data) { int error; // write: S-(addr+w)-ACK-addr-ACK-data-ACK-data-ACK- ... -data-ACK-P I2C0->MSA = slaveAddr << 1; I2C0->MDR = memAddr; I2C0->MCS = 3; // S-(addr+w)-ACK-addr-ACK error = I2C_wait_till_done(); // wait until write is complete if (error) return error; I2C0->MDR = 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; return 0; } // Read consecutive bytes with register address write first int I2C0_read(int slaveAddr, int memAddr, int byteCount, unsigned char* data) { int error; // read: S-(addr+w)-ACK-addr-ACK-S-(addr+r)-ACK-data-ACK-data-ACK- ... -data-NACK-P I2C0->MSA = slaveAddr << 1; I2C0->MDR = memAddr; I2C0->MCS = 3; // S-(addr+w)-ACK-addr-ACK error = I2C_wait_till_done(); if (error) return error; I2C0->MSA = (slaveAddr << 1) + 1; // restart if (byteCount == 1) // if last byte, don't ack I2C0->MCS = 7; // -S-(addr+r)-NACK-P else // else ack I2C0->MCS = 0xB; // -S-(addr+r)-ACK-data-ACK- error = I2C_wait_till_done(); if (error) return error; *data++ = I2C0->MDR; if (--byteCount == 0) { while(I2C0->MCS & 0x40); // wait until bus is not busy return error; } while (byteCount > 1) { I2C0->MCS = 9; // -data-ACK- error = I2C_wait_till_done(); if (error) return error; byteCount--; *data++ = I2C0->MDR; } I2C0->MCS = 5; // -data-NACK-P error = I2C_wait_till_done(); *data = I2C0->MDR; while(I2C0->MCS & 0x40); // wait until bus is not busy return 0; } // 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 } // 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; }