I build two functions for reading and writing a single byte using the eusci i2c interface.
I was not able to find any examples that did not use interrupts so I build my own.
I did a lot of debugging with a logic analyser, but they are working fine now.
oid i2c_init(){ P1SEL1 |= BIT6 | BIT7; // configure I2C pins P1SEL0 &= ~(BIT6 | BIT6); // configure I2C pins // I2C default uses SMCLK UCB0CTL1 |= UCSWRST; // put eUSCI_B in reset state UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC; // I2C, master, sync UCB0BRW = 0x000A; // baud rate = SMCLK / 10 = 100khz UCB0CTL1 &= ~UCSWRST; // eUSCI_B in operational state } void i2c_write(uint8_t slv_addr, uint8_t reg_addr, uint8_t data){ while(UCB0STAT & UCBBUSY); UCB0I2CSA = slv_addr; // set slave address UCB0CTLW0 |= UCTR | UCTXSTT; // transmitter mode and START condition. while (UCB0CTLW0 & UCTXSTT); UCB0TXBUF = reg_addr; while(!(UCB0IFG & UCTXIFG0)); UCB0TXBUF = data; while(!(UCB0IFG & UCTXIFG0)); UCB0CTLW0 |= UCTXSTP; while(UCB0CTLW0 & UCTXSTP); // wait for stop } uint8_t i2c_read(uint8_t slv_addr, uint8_t reg_addr){ uint8_t data = 0; while(UCB0STAT & UCBBUSY); UCB0I2CSA = slv_addr; // set slave address UCB0CTLW0 |= UCTR | UCTXSTT; // transmitter mode and START condition. while(UCB0CTLW0 & UCTXSTT); UCB0TXBUF = reg_addr; while(!(UCB0IFG & UCTXIFG0)); UCB0CTLW0 &= ~UCTR; // receiver mode UCB0CTLW0 |= UCTXSTT; // START condition while(UCB0CTLW0 & UCTXSTT); // make sure start has been cleared UCB0CTLW0 |= UCTXSTP; // STOP condition while(!(UCB0IFG & UCRXIFG0)); data = UCB0RXBUF; while(UCB0CTLW0 & UCTXSTP); return data; }
I found debugging the single read and write that all the "instructions" should be just in the right order for it to work stable.
However, some sensors require you to read multiple registers without a intermediate stop.
Because if you do try to read them byte by byte, after reading the first one, new data is stored in the registers.
To my understanding:
- Both a stop and repeated start automatically send a NACK instead of a ACK
- while(UCB0STAT & UCBBUSY); waits as long as the bus is busy. ( So this should not be checked with a repeated start? )
How should I modify my single read function, for it to be able to read multiple bytes?
I tried some things but when should I send a repeated start? in the same spot as stop?
Ideally I want to have a function as this:
uint8_t i2c_read_multi(uint8_t slv_addr, uint8_t reg_addr, uint8_t l, uint8_t arr*){}
l for the number of bytes to read and arr* a pointer to an array of size l