/* * This program reads the temperature sensor on the Digilent Orbit BoosterPack * and display the least significant 4 bits on the LEDs. * The LEDs are connected to the MCU as: * LD1 PC6 * LD2 PC7 * LD3 PD6 * LD4 PB5 * The temperature sensor is Microchip TCN75A on I2C. */ #include "TM4C123GH6PM.h" void delayMs(int n); void I2C0_init(void); int I2C0_read(int slaveAddr, int byteCount, unsigned char* data); #define SLAVE_ADDR 0x4F /* 1001 111. Microchip TCN75A */ int main(void) { unsigned char data[2]; int temperature; volatile int rv; SYSCTL->RCGCGPIO |= 0x0E; // enable clock to GPIOB, GPIOC, GPIOD I2C0_init(); // initialize I2C0 // 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, 2, data); // read two bytes of temperature temperature = data[0] << 1; if(data[1] == 0x80) temperature += 1; if(temperature & 0x1) // use bit 8 of conversion result to set LD1 GPIOC->DATA |= 0x40; else GPIOC->DATA &= ~0x40; if(temperature & 0x2) // use bit 9 of conversion result to set LD2 GPIOC->DATA |= 0x80; else GPIOC->DATA &= ~0x80; if(temperature & 0x4) // use bit 10 of conversion result to set LD3 GPIOD->DATA |= 0x40; else GPIOD->DATA &= ~0x40; if(temperature & 0x8) // 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 //I2C0->MTPR = 24; // 50 kHz @ 50 MHz } // Read consecutive bytes int I2C0_read(int slaveAddr, int byteCount, unsigned char* data) { int error; // read: S-(addr+r)-ACK-data-ACK-data-ACK- ... -data-NACK-P I2C0->MSA = (slaveAddr << 1) + 1; 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; }