#include "I2C.h" #include "msp430x21x2.h" unsigned char data[2]; volatile unsigned int i; /////////////////////////////////////////////////////////////////////////////////////////////////// //Brief Initialisierung USCI B0 als I²C Bus mit SMCLK 4MHz /////////////////////////////////////////////////////////////////////////////////////////////////// void init_I2C (void) { UCB0CTL1 |= UCSWRST; // Enable SW Reset UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, I2C, Synchronous mode UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset UCB0BR0 = 40; // fSCL = SMCLK/40 = ~100kHz UCB0BR1 = 0; UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation } /////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////// //Brief Adresse auf ACK testen (IC Antwortet) /////////////////////////////////////////////////////////////////////////////////////////////////// unsigned char check_ack (unsigned char addr) { UCB0I2CSA = addr; UCB0CTL1 |= UCTR + UCTXSTT + UCTXSTP; // I2C TX, Start/Stop senden while (I2C_START); // Warten bis Start und Adresse gesendet while (I2C_STOP); // Warten bis Stop gesendet return (!I2C_NACK); // ACK/NACK? } /////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////// //Brief Ein einzelnes Byte schreiben /////////////////////////////////////////////////////////////////////////////////////////////////// unsigned char i2c_write_byte (unsigned int addr, unsigned char data) { UCB0STAT &=~UCNACKIFG; if (I2C_BUSY) return FALSE; if (I2C_SCLLOW) return FALSE; UCB0I2CSA = addr; // Slave Adresse setzen UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, Start senden UCB0TXBUF = data; while(I2C_START && !I2C_NACK); // Warten bis Start und Adresse gesendet if (I2C_NACK) return FALSE; // Bei NACK sofort raus UCB0CTL1 |= UCTXSTP; // Stop senden while(I2C_STOP && !I2C_NACK); // Warten bis Stop gesendet if (I2C_NACK) return FALSE; // Bei NACK sofort raus return TRUE; } /////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////// //Brief Mehrere Bytes schreiben /////////////////////////////////////////////////////////////////////////////////////////////////// unsigned char i2c_write_bytes (unsigned int addr, unsigned char data_cnt, unsigned char *data) { unsigned int i; UCB0STAT &=~UCNACKIFG; if (I2C_BUSY) return FALSE; if (I2C_SCLLOW) return FALSE; UCB0I2CSA = addr; // Slave Adresse setzen UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, Start senden UCB0TXBUF = data[0]; while(I2C_START && !I2C_NACK); // Warten bis Start und Adresse gesendet if (I2C_NACK) return FALSE; // Bei NACK sofort raus for(i = 1; i < data_cnt; i++) { while (!(IFG2 & UCB0TXIFG) && !I2C_NACK); if (I2C_NACK) return FALSE; // Bei NACK sofort raus UCB0TXBUF = data[i]; } while (!(IFG2 & UCB0TXIFG) && !I2C_NACK); if (I2C_NACK) return FALSE; // Bei NACK sofort raus UCB0CTL1 |= UCTXSTP; // Stop senden while(I2C_STOP && !I2C_NACK); // Warten bis Stop gesendet if (I2C_NACK) return FALSE; // Bei NACK sofort raus return TRUE; } /////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////// //Brief Ein einzelnes Byte lesen /////////////////////////////////////////////////////////////////////////////////////////////////// unsigned char i2c_read_byte (unsigned int addr, unsigned char *data) { UCB0STAT &=~UCNACKIFG; if (I2C_BUSY) return FALSE; if (I2C_SCLLOW) return FALSE; UCB0I2CSA = addr; // Slave Adresse setzen UCB0CTL1 &=~UCTR; // I2C RX UCB0CTL1 |= UCTXSTT; // Start senden while(I2C_START && !I2C_NACK); // Warten bis Start und Adresse gesendet if (I2C_NACK) return FALSE; // Bei NACK sofort raus UCB0CTL1 |= UCTXSTP; // Stop senden while (!(IFG2 & UCB0RXIFG)); // Buffer bereit? *data = UCB0RXBUF; while(I2C_STOP); // Warten bis Stop gesendet return TRUE; } /////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////// //Brief Mehrere Bytes lesen /////////////////////////////////////////////////////////////////////////////////////////////////// unsigned char i2c_read_bytes (unsigned int addr, unsigned char data_cnt, unsigned char *data) { unsigned int i; UCB0STAT &=~UCNACKIFG; if (I2C_BUSY) return FALSE; if (I2C_SCLLOW) return FALSE; UCB0I2CSA = addr; // Slave Adresse setzen UCB0CTL1 &=~UCTR; // I2C RX UCB0CTL1 |= UCTXSTT; // Start senden while(I2C_START && !I2C_NACK); // Warten bis Start und Adresse gesendet if (I2C_NACK) return FALSE; // Bei NACK sofort raus for(i = 0; i < data_cnt; i++) { if (data_cnt == i + 1) // Letztes Byte? UCB0CTL1 |= UCTXSTP; // Stop senden // while (!(IFG2 & UCB0RXIFG)); // Buffer bereit? data[i] = UCB0RXBUF; } while(I2C_STOP); // Warten bis Stop gesendet return TRUE; } /////////////////////////////////////////////////////////////////////////////////////////////////// void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT P1DIR |= 0x01; // P1.0 output P3SEL |= 0x06; // Assign I2C pins to USCI_B0 init_I2C(); i2c_write_byte(0x48, 0x00); // Temp Register adressieren i2c_read_bytes(0x48, 2, &data[0]); // 2 Byte lesen if (data[0] < 0xBD0) // >33C? P1OUT &= ~0x01; // No, P1.0 = 0 else P1OUT |= 0x01; // Yes, P1.0 = 1 for (;;) { i = 5000; do (i--); while (i != 0); } }