Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 

    SPI problem with BMI160

    SPI problem with BMI160

    SaberKazemi1992
    Established Member

    I am trying to have SPI connectio as interface protocol between BMI160 shuttle board/MSP432P401R. What I need is the accel/gyroscope data continuously.  The main functions I am using is from BMI160 drivers found on github:

    https://github.com/BoschSensortec/BMI160_driver 

    I have defined the user_spi_read/user_spi_write as below:

    int8_t user_spi_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
    {
    int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
    SPI_BMI160_BEGIN;
    /* send register address byte */
    SPI_BMI160_TX(reg_addr);
    /* Storing chip status */
    // SPI_BMI160_RX(rslt);
    for (i = 0; i < len; i++)
    {
    SPI_BMI160_TX(*reg_data);
    reg_data++;
    }
    return (rslt);

    }

    And

    int8_t user_spi_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
    {
    int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
    int i;
    /* Pull CS_N low*/
    SPI_BMI160_BEGIN;
    /* send register address byte */
    SPI_BMI160_TX(reg_addr);
    /* Storing chip status */
    //SPI_BMI160_RX(rslt);/////////////////?????
    /* Communicate len number of bytes: if RX - the procedure sends 0x00 to push bytes from slave*/
    for (i = 0; i < len; i++)
    {
    SPI_BMI160_TX(0); /* Possible to combining read and write as one access type */
    // SPI_WAIT_DONE();
    SPI_BMI160_RX(*reg_data); /* Store pData from last pData RX */
    reg_data++;
    }
    //}
    /* Pull CS_N low*/
    SPI_BMI160_END;
    /* return the status byte value */
    return(rslt);
    }

    The functions for SPI (in MSP432p401R) abbreviated as below:

    #define SPI_BMI160_BEGIN              P6OUT &= ~BIT2;
    #define SPI_BMI160_TX(x)                do{while(!(UCTXIFG & UCB1IFG));UCB1TXBUF= (x);}while(1==-1)
    #define SPI_BMI160_RX(x)                do{while(!(UCRXIFG & UCB1IFG));(x)=UCB1RXBUF;}while(1==-1)
    #define SPI_BMI160_END                   P6OUT |= BIT2;

    Is this correct form for SPI wirte/read functions? Seems SPI is not working.

    Thanks

    Saber

    5 REPLIES 5

    shellywang
    Occasional Contributor

    It is recommended to observe the waveform using a logic analyzer or oscilloscope.

    Here are some suggestions in terms of the code:

    1. After power-on reset, the BMI160 is in I2C state by default. Therefore, a dummy read of register 0x00 is required to switch to SPI bus.
    2. For write operations, reg_address should be ANDed with 0x7f and then sent out. For example, to write the address 0x40, 0x40 is ANDed with 0x7f, i.e.  0x40 & 0x7f, and the result 0x40 is sent out.
    3. For read operations, reg_address should be ORed with 0x80 and then sent out. For example, to read the address 0x40, 0x40 is ORed with 0x80, i.e. 0x40 | 0x80, and the result 0xC0 is sent out.

    Thanks for your previous reply. 

    On 2 and 3, you mentioned that for read/write operations, the registers need to be ORed/ANDed with 0x7F/0x40 respectively. Does it apply to I2C as well?

     

    Thanks

    Saber

    No. Only for SPI.

    Background: In i2c the R/W bit is part of the address byte. In SPI, there is no address byte and the R/W bit is part of the command byte.

    o_o

    Hello

    Thanks for your previous answer. Maybe a trivial question 🙂:

    In #1, you mentioned to switch to SPI, a dummy read of 0x00 should be done. Can you please explain how I can do it?

    The SPI write and read instances are like below:

     

    int8_t user_spi_write(int8_t dev_id, int8_t reg_addr, int8_t *reg_data, int8_tlength)
    {
    int8_t rslt = BMI160_OK; /* Return 0 for Success, non-zero for failure */
    SPI_BMI160_BEGIN;
    SPI_BMI160_TX(reg_addr & 0x7F);
    __delay_cycles(200);

    for (i = 0; i < length; i++)
    {
    SPI_BMI160_TX(*reg_data);
    reg_data++;
    }
    SPI_BMI160_END;

    return rslt;
    }

    int8_t user_spi_read(int8_t dev_id, int8_t reg_addr, int8_t *reg_data, int8_tlength)

    {

    int8_t rslt = BMI160_OK; /* Return 0 for Success, non-zero for failure */

    SPI_BMI160_BEGIN;

    SPI_BMI160_TX(reg_addr | 0x80);
    __delay_cycles(200);

    for (i = 0; i < length; i++)
    {
    SPI_BMI160_TX(0); 
    SPI_BMI160_RX(*reg_data); /* Store pData from last pData RX */
    reg_data++;
    }
    SPI_BMI160_END;

    return rslt;

    }

     

    Thanks

    Saber

    Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist