Quantcast
Channel: MSP low-power microcontroller forum - Recent Threads
Viewing all articles
Browse latest Browse all 22222

MSP430FR5969: Read multiple bytes of data i2c with repeated start and without interrupts

$
0
0

Part Number:MSP430FR5969

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


Viewing all articles
Browse latest Browse all 22222

Trending Articles