nRF SPI 与 TWI 操作相关 (BMI088 与 MLX90614 举例)

2023-05-16

SPI0 与 TWI0 的 ID相同,SPI0 与 TWI0 的 ID相同。编译时有报错

若要避免,有两个方法

1、使用不同ID外设

2、使用模拟SPI或模拟IIC

 

nRF SPI 初始化

sdk_config.h 中:

添加:

// <h> Application

//==========================================================
// <h> SPI_CONFIGURATION - Spi configuration

//==========================================================
// <o> SPI_BMI088_SCK_PIN - Pin number

// <0=> 0 (P0.0)
// <1=> 1 (P0.1)
// <2=> 2 (P0.2)
// <3=> 3 (P0.3)
// <4=> 4 (P0.4)
// <5=> 5 (P0.5)
// <6=> 6 (P0.6)
// <7=> 7 (P0.7)
// <8=> 8 (P0.8)
// <9=> 9 (P0.9)
// <10=> 10 (P0.10)
// <11=> 11 (P0.11)
// <12=> 12 (P0.12)
// <13=> 13 (P0.13)
// <14=> 14 (P0.14)
// <15=> 15 (P0.15)
// <16=> 16 (P0.16)
// <17=> 17 (P0.17)
// <18=> 18 (P0.18)
// <19=> 19 (P0.19)
// <20=> 20 (P0.20)
// <21=> 21 (P0.21)
// <22=> 22 (P0.22)
// <23=> 23 (P0.23)
// <24=> 24 (P0.24)
// <25=> 25 (P0.25)
// <26=> 26 (P0.26)
// <27=> 27 (P0.27)
// <28=> 28 (P0.28)
// <29=> 29 (P0.29)
// <30=> 30 (P0.30)
// <31=> 31 (P0.31)
// <32=> 32 (P1.0)
// <33=> 33 (P1.1)
// <34=> 34 (P1.2)
// <35=> 35 (P1.3)
// <36=> 36 (P1.4)
// <37=> 37 (P1.5)
// <38=> 38 (P1.6)
// <39=> 39 (P1.7)
// <40=> 40 (P1.8)
// <41=> 41 (P1.9)
// <42=> 42 (P1.10)
// <43=> 43 (P1.11)
// <44=> 44 (P1.12)
// <45=> 45 (P1.13)
// <46=> 46 (P1.14)
// <47=> 47 (P1.15)
// <4294967295=> Not connected

#ifndef SPI_BMI088_SCK_PIN
#define SPI_BMI088_SCK_PIN 45
#endif

// <o> SPI_BMI088_MISO_PIN - Pin number

// <0=> 0 (P0.0)
// <1=> 1 (P0.1)
// <2=> 2 (P0.2)
// <3=> 3 (P0.3)
// <4=> 4 (P0.4)
// <5=> 5 (P0.5)
// <6=> 6 (P0.6)
// <7=> 7 (P0.7)
// <8=> 8 (P0.8)
// <9=> 9 (P0.9)
// <10=> 10 (P0.10)
// <11=> 11 (P0.11)
// <12=> 12 (P0.12)
// <13=> 13 (P0.13)
// <14=> 14 (P0.14)
// <15=> 15 (P0.15)
// <16=> 16 (P0.16)
// <17=> 17 (P0.17)
// <18=> 18 (P0.18)
// <19=> 19 (P0.19)
// <20=> 20 (P0.20)
// <21=> 21 (P0.21)
// <22=> 22 (P0.22)
// <23=> 23 (P0.23)
// <24=> 24 (P0.24)
// <25=> 25 (P0.25)
// <26=> 26 (P0.26)
// <27=> 27 (P0.27)
// <28=> 28 (P0.28)
// <29=> 29 (P0.29)
// <30=> 30 (P0.30)
// <31=> 31 (P0.31)
// <32=> 32 (P1.0)
// <33=> 33 (P1.1)
// <34=> 34 (P1.2)
// <35=> 35 (P1.3)
// <36=> 36 (P1.4)
// <37=> 37 (P1.5)
// <38=> 38 (P1.6)
// <39=> 39 (P1.7)
// <40=> 40 (P1.8)
// <41=> 41 (P1.9)
// <42=> 42 (P1.10)
// <43=> 43 (P1.11)
// <44=> 44 (P1.12)
// <45=> 45 (P1.13)
// <46=> 46 (P1.14)
// <47=> 47 (P1.15)
// <4294967295=> Not connected

#ifndef SPI_BMI088_MISO_PIN
#define SPI_BMI088_MISO_PIN 47
#endif

// <o> SPI_BMI088_MOSI_PIN - Pin number

// <0=> 0 (P0.0)
// <1=> 1 (P0.1)
// <2=> 2 (P0.2)
// <3=> 3 (P0.3)
// <4=> 4 (P0.4)
// <5=> 5 (P0.5)
// <6=> 6 (P0.6)
// <7=> 7 (P0.7)
// <8=> 8 (P0.8)
// <9=> 9 (P0.9)
// <10=> 10 (P0.10)
// <11=> 11 (P0.11)
// <12=> 12 (P0.12)
// <13=> 13 (P0.13)
// <14=> 14 (P0.14)
// <15=> 15 (P0.15)
// <16=> 16 (P0.16)
// <17=> 17 (P0.17)
// <18=> 18 (P0.18)
// <19=> 19 (P0.19)
// <20=> 20 (P0.20)
// <21=> 21 (P0.21)
// <22=> 22 (P0.22)
// <23=> 23 (P0.23)
// <24=> 24 (P0.24)
// <25=> 25 (P0.25)
// <26=> 26 (P0.26)
// <27=> 27 (P0.27)
// <28=> 28 (P0.28)
// <29=> 29 (P0.29)
// <30=> 30 (P0.30)
// <31=> 31 (P0.31)
// <32=> 32 (P1.0)
// <33=> 33 (P1.1)
// <34=> 34 (P1.2)
// <35=> 35 (P1.3)
// <36=> 36 (P1.4)
// <37=> 37 (P1.5)
// <38=> 38 (P1.6)
// <39=> 39 (P1.7)
// <40=> 40 (P1.8)
// <41=> 41 (P1.9)
// <42=> 42 (P1.10)
// <43=> 43 (P1.11)
// <44=> 44 (P1.12)
// <45=> 45 (P1.13)
// <46=> 46 (P1.14)
// <47=> 47 (P1.15)
// <4294967295=> Not connected

#ifndef SPI_BMI088_MOSI_PIN
#define SPI_BMI088_MOSI_PIN 46
#endif


// <o> SPI_BMI088_SS_PIN - Pin number

// <0=> 0 (P0.0)
// <1=> 1 (P0.1)
// <2=> 2 (P0.2)
// <3=> 3 (P0.3)
// <4=> 4 (P0.4)
// <5=> 5 (P0.5)
// <6=> 6 (P0.6)
// <7=> 7 (P0.7)
// <8=> 8 (P0.8)
// <9=> 9 (P0.9)
// <10=> 10 (P0.10)
// <11=> 11 (P0.11)
// <12=> 12 (P0.12)
// <13=> 13 (P0.13)
// <14=> 14 (P0.14)
// <15=> 15 (P0.15)
// <16=> 16 (P0.16)
// <17=> 17 (P0.17)
// <18=> 18 (P0.18)
// <19=> 19 (P0.19)
// <20=> 20 (P0.20)
// <21=> 21 (P0.21)
// <22=> 22 (P0.22)
// <23=> 23 (P0.23)
// <24=> 24 (P0.24)
// <25=> 25 (P0.25)
// <26=> 26 (P0.26)
// <27=> 27 (P0.27)
// <28=> 28 (P0.28)
// <29=> 29 (P0.29)
// <30=> 30 (P0.30)
// <31=> 31 (P0.31)
// <32=> 32 (P1.0)
// <33=> 33 (P1.1)
// <34=> 34 (P1.2)
// <35=> 35 (P1.3)
// <36=> 36 (P1.4)
// <37=> 37 (P1.5)
// <38=> 38 (P1.6)
// <39=> 39 (P1.7)
// <40=> 40 (P1.8)
// <41=> 41 (P1.9)
// <42=> 42 (P1.10)
// <43=> 43 (P1.11)
// <44=> 44 (P1.12)
// <45=> 45 (P1.13)
// <46=> 46 (P1.14)
// <47=> 47 (P1.15)
// <4294967295=> Not connected

#ifndef SPI_BMI088_SS_PIN
#define SPI_BMI088_SS_PIN 8
#endif


// <o> SPI_IRQ_PRIORITY - Interrupt priority

// <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
// <0=> 0 (highest)
// <1=> 1
// <2=> 2
// <3=> 3
// <4=> 4
// <5=> 5
// <6=> 6
// <7=> 7

#ifndef SPI_IRQ_PRIORITY
#define SPI_IRQ_PRIORITY 2
#endif

// </h>
//==========================================================

 

勾选:

nRF_Drivers --> NRFX_SPIM_ENABLED

nRF_Drivers --> NRFX_SPI_ENABLED

nRF_Drivers --> SPI_ENABLED

nRF_Drivers --> SPI_ENABLED --> SPI0_ENABLED

nRF_Drivers --> SPI_ENABLED --> SPI0_ENABLED --> SPI0_USE_EASY_DMA

 

注:

记得打开 SPI0_USE_EASY_DMA,SPI 读写不占用MCU资源,大大提高效率,

 

nrf_drv_spi.h 中:

#define NRF_DRV_SPI_DEFAULT_CONFIG \
{ \
    .sck_pin = NRF_DRV_SPI_PIN_NOT_USED, \
    .mosi_pin = NRF_DRV_SPI_PIN_NOT_USED, \
    .miso_pin = NRF_DRV_SPI_PIN_NOT_USED, \
    .ss_pin = NRF_DRV_SPI_PIN_NOT_USED, \
    .irq_priority = SPI_DEFAULT_CONFIG_IRQ_PRIORITY, \
    .orc = 0xFF, \
    .frequency = NRF_DRV_SPI_FREQ_8M, \
    .mode = NRF_DRV_SPI_MODE_0, \
    .bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST, \
}

注:

1、设定的 spi 模式,要与传感器对应

2、设定的 spi 的频率要在传感器支持的频率范围内

3、设定的 bit_order 要与传感器的数据排序一致,MSB_FIRST or LSB_FIRST

 

main.c 中:

#define SPI_INSTANCE_0                  0                                           /**< SPI instance index. */

static const nrf_drv_spi_t spi_0_bmi088 = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE_0);            /**< SPI instance. */

static void spi_bmi088_event_handler(nrf_drv_spi_evt_t const * p_event,
                              					void *                    p_context)
{
    spi_bmi088_xfer_done = true;
//    NRF_LOG_INFO("Spi bmi088 transfer completed.");
}

static void spi_bmi088_init(void)
{
    nrf_drv_spi_config_t spi_bmi088_config = NRF_DRV_SPI_DEFAULT_CONFIG;
    spi_bmi088_config.ss_pin   = NRF_DRV_SPI_PIN_NOT_USED;
    spi_bmi088_config.miso_pin = SPI_BMI088_MISO_PIN;
    spi_bmi088_config.mosi_pin = SPI_BMI088_MOSI_PIN;
    spi_bmi088_config.sck_pin  = SPI_BMI088_SCK_PIN;
    APP_ERROR_CHECK(nrf_drv_spi_init(&spi_0_bmi088, &spi_bmi088_config, spi_bmi088_event_handler, NULL));
}

注:

1、若 cs 片选引脚信号为高使能,或需要操控多个 cs 片选脚时,需在设置时将 .ss_pin 参数留空,另外将其设为输出脚并将其拉高(拉低),在发送或接收时拉低(拉高)。(因为nRF SPI 底层驱动库仅支持 cs 片选引脚低使能)

///< Slave Select pin number (optional).

/**< Set to @ref NRF_DRV_SPI_PIN_NOT_USED

* if this signal is not needed. The driver

* supports only active low for this signal.

* If the signal should be active high,

* it must be controlled externally. */

 

2、nrf_drv_spi_init 初始化参数中,若回调函数留空则将以阻塞模式执行传输。 Event handler provided by the user. If NULL, transfers will be performed in blocking mode.

 

nRF 的 SPI 发送与接收做成了一体,收发都需要调用 nrf_drv_spi_transfer:

1、做发送时

nrf_drv_spi_transfer(&spi_0_bmi088, m_tx_buf, m_tx_length, NULL, 0)

发送的数据 m_tx_buf 内容为 :

m_tx_buf[0] = reg_addr

memcpy(&m_tx_buf[1], data, len);

首字节为寄存器地址,(注:需要做偏移,例如,最高位读写位为0时为写,则需 & 0x7F

从第二个字节开始为要写入的数据)

发送的数据长度 m_tx_length

必须是写入数据的长度 + 1(寄存器地址)

接收BUF及接收数据长度留空

 

2、做接收时

nrf_drv_spi_transfer(&spi_0_bmi088, m_tx_buf, m_tx_length, data, m_rx_length)

发送的数据 m_tx_buf 内容为 :

uint8_t m_tx_buf[1] = {reg_addr};

首字节为寄存器地址,(注:需要做偏移,例如,最高位读写位为1时为读,则需 | 0x80

从第二个字节开始为要写入的数据)

发送的数据长度 m_tx_length = 1;

接收数据长度根据数据而定

 

注:特别注意冗余数据处理,(具体参考2_Vibration_measurer-Github 项目)=

例:

/*!
 *  @brief Function for reading the sensor's registers through SPI bus.
 *
 *  @param[in] cs_pin   : Chip selection pin.
 *  @param[in] reg_addr : Register address.
 *  @param[in] data     : Pointer to the data buffer to store the read data.
 *  @param[in] len      : No of bytes to read.
 *
 *  @return Status of execution
 *  @retval 0 -> Success
 *  @retval >0 -> Failure Info
 *
 */
int8_t user_bmi088_spi_write(uint8_t cs_pin, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
    if (cs_pin == MCU_GPIO_BMI088_CSB1)
    {
        nrf_gpio_pin_set(MCU_GPIO_BMI088_CSB2);
        nrf_gpio_pin_clear(MCU_GPIO_BMI088_CSB1);
    }
    else if (cs_pin == MCU_GPIO_BMI088_CSB2)
    {
        nrf_gpio_pin_set(MCU_GPIO_BMI088_CSB1);
        nrf_gpio_pin_clear(MCU_GPIO_BMI088_CSB2);
    }
    else
    {
        return -2;
    }

    nrf_delay_us(1);

    if (len <= 32)
    {
        uint8_t m_tx_buf[33] = {0};
        m_tx_buf[0] = reg_addr;
        uint8_t m_tx_length = ((uint8_t)len) + 1;
        memcpy(&m_tx_buf[1], data, len);

        spi_bmi088_xfer_done = false;
        APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi_0_bmi088, m_tx_buf, m_tx_length, NULL, 0));
        while(spi_bmi088_xfer_done == false)
        {
            __WFE();
        }
    }
    else
    {
        NRF_LOG_INFO("Spi write over length.");
    }

    nrf_delay_us(1);
    nrf_gpio_pin_set(MCU_GPIO_BMI088_CSB1);
    nrf_gpio_pin_set(MCU_GPIO_BMI088_CSB2);

    return 0;
}


/*!
 *  @brief Function for writing the sensor's registers through SPI bus.
 *
 *  @param[in] cs_pin   : Chip selection pin.
 *  @param[in] reg_addr : Register address.
 *  @param[out]data     : Pointer to the data buffer whose value is to be written.
 *  @param[in] len      : No of bytes to write.
 *
 *  @return Status of execution
 *  @retval 0 -> Success
 *  @retval >0 -> Failure Info
 *
 */
int8_t user_bmi088_spi_read(uint8_t cs_pin, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
    if (cs_pin == MCU_GPIO_BMI088_CSB1)
    {
        nrf_gpio_pin_set(MCU_GPIO_BMI088_CSB2);
        nrf_gpio_pin_clear(MCU_GPIO_BMI088_CSB1);
    }
    else if (cs_pin == MCU_GPIO_BMI088_CSB2)
    {
        nrf_gpio_pin_set(MCU_GPIO_BMI088_CSB1);
        nrf_gpio_pin_clear(MCU_GPIO_BMI088_CSB2);
    }
    else
    {
        return -2;
    }

    nrf_delay_us(1);

    if (len <= 32)
    {
        uint8_t m_tx_buf[1] = {reg_addr};
        uint8_t m_tx_length = 1;
        uint8_t m_rx_length = (uint8_t)len + 1; // Add the byte sent
        uint8_t m_rx_buf[33] = {0};

        spi_bmi088_xfer_done = false;
        APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi_0_bmi088, m_tx_buf, m_tx_length, m_rx_buf, m_rx_length));
        while(spi_bmi088_xfer_done == false)
        {
            __WFE();
        }

        memcpy(data, &m_rx_buf[1], (m_rx_length - 1));
    }
    else
    {
        NRF_LOG_INFO("Spi read over length.");
    }

    nrf_delay_us(1);
    nrf_gpio_pin_set(MCU_GPIO_BMI088_CSB1);
    nrf_gpio_pin_set(MCU_GPIO_BMI088_CSB2);

    return 0;
}

 

nRF TWI 初始化

sdk_config.h 中:

勾选:

NRFX_TWIM_ENABLED --> NRFX_TWIM_ENABLED

NRFX_TWIM_ENABLED --> NRFX_TWI_ENABLED

NRFX_TWIM_ENABLED --> NRFX_TWI_ENABLED --> TWI1_ENABLED

NRFX_TWIM_ENABLED --> NRFX_TWI_ENABLED --> TWI1_ENABLED -->TWI1_USE_EASY_DMA

 

修改:

TWI_DEFAULT_CONFIG_FREQUENCY 26738688

TWI_DEFAULT_CONFIG_CLR_BUS_INIT 0

TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT 0

TWI_DEFAULT_CONFIG_IRQ_PRIORITY 2

 

nrf_drv_twi.h 中:

#define NRF_DRV_TWI_DEFAULT_CONFIG                                               \
{                                                                                \
    .frequency          = (nrf_drv_twi_frequency_t)TWI_DEFAULT_CONFIG_FREQUENCY, \
    .scl                = 0xFF,                                                  \
    .sda                = 0xFF,                                                  \
    .interrupt_priority = TWI_DEFAULT_CONFIG_IRQ_PRIORITY,                       \
    .clear_bus_init     = TWI_DEFAULT_CONFIG_CLR_BUS_INIT,                       \
    .hold_bus_uninit    = TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT,                    \
}

main.c 中:

static void twi_mlx90614_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
    switch (p_event->type)
    {
        case NRF_DRV_TWI_EVT_DONE:
        {
            if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TX)
            {
                NRF_LOG_INFO("Twi mlx90614 tx evt done.");
            }
            else if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
            {
                NRF_LOG_INFO("Twi mlx90614 rx evt done.");
            }
            else if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TXRX)
            {
                NRF_LOG_INFO("Twi mlx90614 txrx evt done.");
            }
            else if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TXTX)
            {
                NRF_LOG_INFO("Twi mlx90614 txtx evt done.");
            }
            twi_mlx90614_xfer_done = true;
        } break;

        case NRF_DRV_TWI_EVT_ADDRESS_NACK:
            NRF_LOG_ERROR("Error event: NACK received after sending the address.");
            break;

        case NRF_DRV_TWI_EVT_DATA_NACK:
            NRF_LOG_ERROR("Error event: NACK received after sending a data byte.");
        break;

        default:
            break;
    }
}


static void twi_mlx90614_init(void)
{
    ret_code_t err_code;

    nrf_drv_twi_config_t twi_mlx90614_config = NRF_DRV_TWI_DEFAULT_CONFIG;
    twi_mlx90614_config.scl                  = TWI_MLX90614_SCL_PIN,
    twi_mlx90614_config.sda                  = TWI_MLX90614_SDA_PIN,

    err_code = nrf_drv_twi_init(&twi_1_mlx90614, &twi_mlx90614_config, twi_mlx90614_handler, NULL);
APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&twi_1_mlx90614);
}

nRF 的 TWI 发送调用 nrf_drv_twi_tx,接收调用 nrf_drv_twi_rx。具体时序依照传感器数据手册

例如 mlx90614:

uint8_t PEC_Calculation(uint8_t pec[])
{
    uint8_t crc[6];
    uint8_t BitPosition = 47;
    uint8_t shift;
    uint8_t i;
    uint8_t j;
    uint8_t temp;

    do
    {
        /*Load pattern value 0x000000000107*/
        crc[5] = 0;
        crc[4] = 0;
        crc[3] = 0;
        crc[2] = 0;
        crc[1] = 0x01;
        crc[0] = 0x07;

        /*Set maximum bit position at 47 ( six bytes byte5...byte0,MSbit=47)*/
        BitPosition = 47;

        /*Set shift position at 0*/
        shift = 0;

        /*Find first "1" in the transmited message beginning from the MSByte byte5*/
        i = 5;
        j = 0;
        while (((pec[i] & (0x80 >> j)) == 0) && (i > 0))
        {
            BitPosition--;
            if (j < 7)
            {
                j++;
            }
            else
            {
                j = 0x00;
                i--;
            }
        }/*End of while */

        /*Get shift value for pattern value*/
        shift = BitPosition - 8;

        /*Shift pattern value */
        while(shift)
        {
            for(i = 5; i < 0xFF; i--)
            {
                if((crc[i-1] & 0x80) && (i > 0))
                {
                    temp = 1;
                }
                else
                {
                    temp = 0;
                }
                crc[i] <<= 1;
                crc[i] += temp;
            }/*End of for*/
            shift--;
        }/*End of while*/

        /*Exclusive OR between pec and crc*/
        for(i = 0; i <= 5; i++)
        {
            pec[i] ^= crc[i];
        }/*End of for*/
    } while(BitPosition > 8); /*End of do-while*/

    return pec[0];
}


uint16_t SMBus_Read_Memory(uint8_t slave_Address, uint8_t command)
{
    ret_code_t err_code;
    uint16_t data;			// Data storage (DataH:DataL)
    uint8_t Pec;			// PEC byte storage
    uint8_t PecReg;			// Calculated PEC byte storage
    uint8_t arr[6];			// Buffer for the sent bytes
    uint8_t DataL = 0;			// Low data byte storage
    uint8_t DataH = 0;			// High data byte storage
    uint8_t Error_Counter;              // Defines the number of the attempts for communication with MLX90614
    uint8_t rx_data[3] = {0};           // Data received from twi
    uint8_t tx_data[1] = {command};     // Data sent from twi
    
    Error_Counter = 0x00;               // Initialising of Error_Counter
    slave_Address <<= 1;                // 2-7 bits indicate the slave address
	
    do
    {
        err_code = nrf_drv_twi_tx(&twi_1_mlx90614, slave_Address, tx_data, 1, true);
        APP_ERROR_CHECK(err_code);
        twi_mlx90614_xfer_done = false;
        while(twi_mlx90614_xfer_done == false);
        {
            __WFE();
        }

        err_code = nrf_drv_twi_rx(&twi_1_mlx90614, slave_Address, rx_data, 3);
        APP_ERROR_CHECK(err_code);
        twi_mlx90614_xfer_done = false;
        while(twi_mlx90614_xfer_done == false);
        {
            __WFE();
        }

        DataL = rx_data[0];
        DataH = rx_data[1];
        Pec = rx_data[2];

        arr[5] = slave_Address;
        arr[4] = command;
        arr[3] = slave_Address + 1;	
        arr[2] = DataL;
        arr[1] = DataH;
        arr[0] = 0;
        PecReg = PEC_Calculation(arr);  // Calculate CRC
    } while(PecReg != Pec);             // If received and calculated CRC are equal go out from do-while{}

    data = (DataH << 8) | DataL;        // data = DataH:DataL

    return data;
}


static float SMBus_Read_Ambient_Temp(void)
{   
    return SMBus_Read_Memory(SA, (RAM_ACCESS | RAM_TA)) * 0.02 - 273.15;
}


static float SMBus_Read_Object_Temp(void)
{   
    return SMBus_Read_Memory(SA, (RAM_ACCESS | RAM_TOBJ1)) * 0.02 - 273.15;
}

 

注:

1、nrf_drv_twi_tx 第五个参数是 是否不发送停止位

2、如果需要访问EEPROM中的地址,则实际的地址值是需要访问的地址值与 Opcode 的组合

如EEPROM的0x0E地址,实际中输入的应该是0x2E

3、写的数据末尾一个字节要加上PEC

 

4、如果是写数据,先要把寄存器数据清零。比如命令为0x24,也就是修改发射频率,第一次先对高低八位分别写一遍0x00,第二次再重新用这个命令写入你要改的数据。

 

参考 2_Vibration_measurer-Github 项目

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

nRF SPI 与 TWI 操作相关 (BMI088 与 MLX90614 举例) 的相关文章

  • 使用DMA+SPI驱动Aliyun Things 上的ST7789H2 LCD屏幕

    目录 前言硬件CUBEMX时钟树GPIOSPI 代码部分LCD驱动中断服务函数测试代码现象 前言 1 xff1a 驱动程序参考自https blog csdn net BearPi article details 104311705 2 x
  • 调试笔记2:SPI+DMA

    一 内容简介 说明 xff1a 关于DMA xff0c SPI的基本知识这里不做介绍 本文只讲述SPI 43 DMA的实现 这里仅实现从外设到内存 从内存到外设也可以参考修改 目的 xff1a 使用STM32作为SPI从机接收数据 xff0
  • STM32 SPI 收发数据 ---规则 + 问题解析

    规则 xff1a 1 xff09 高速同步串行口 3 xff5e 4线接口 xff08 CS xff0c CLK xff0c MOSI xff0c MISO xff09 xff0c 收发独立 可同步进行 2 xff09 SPI分为主从模式
  • UART、RS232、RS485、I2C和SPI的介绍

    基本知识 串行通信 xff1a 多个数据通过一条数据线 xff0c 依次传输并行通信 xff1a 多个数据通过多条数据线 xff0c 一次性传输单工通信 xff1a 只能接收数据或者发送数据 xff08 遥控器 收音机 xff09 半双工通
  • STM32F4 使用SPI读取气压计MS5611的数据并转化为大气压强

    ms5611是同时支持I2C和SPI通信协议的气压计芯片 已经很普遍的被用在飞行器控制板上作为高度传感器 开发过stm32的朋友都知道它的硬件I2C是由bug的 xff0c 一般使用的都是自己编写的软件I2C通信协议 但是其硬件SPI通信却
  • 基于I2C/SPI的温湿度采集与OLED显示

    基于I2C SPI的温湿度采集与OLED显示 一 AHT20温湿度采集1 I2C2 温湿度采集代码效果 二 OLED显示1 显示学号姓名2 诗句显示 三 总结四 参考 一 AHT20温湿度采集 1 I2C 解释什么是 软件I2C 和 硬件I
  • 老猿学5G扫盲贴:NEF、NRF、AF、UPF以及DN的功能

    专栏 xff1a Python基础教程目录 专栏 xff1a 使用PyQt开发图形界面Python应用 专栏 xff1a PyQt入门学习 老猿Python博文目录 NEF xff1a Network Exposure Function x
  • Jlink使用技巧之烧写SPI Flash存储芯片

    文章目录 前言 准备 硬件连接 1 打开 2 连接SPI Flash芯片 3 打开程序文件 4 下载 5 程序文件的读取 6 程序文件的保存 7 命令行工具的使用 支持的芯片列表 速度说明 参考资料 JLink软件的下载 前言 大多数玩单片
  • RT-Thread记录(十六、SFUD组件 — SPI Flash的读写)

    从本文开始 测试学习一些 RT Thread 常用的组件与软件包 先从刚学完的 SPI 设备开始 目录 前言 一 SFUD 组件简介 1 1 基本简介 1 2 SFUD 对 Flash 的管理 二 SFUD 组件操作函数 2 1 初始化相关
  • 沁恒CH32V307使用记录:SPI基础使用

    文章目录 目的 基础说明 使用演示 其它补充 总结 目的 SPI是单片机中比较常用的一个功能 这篇文章将对CH32V307中相关内容进行说明 本文使用沁恒官方的开发板 CH32V307 EVT R1沁恒RISC V模块MCU赤兔评估板 进行
  • 用STM32F030F4的SPI总线获取BMP280的气压和温度

    1 用STM32Cube MX生成SPI总线的初始化函数 static void BMP280 SPI Init void LL SPI InitTypeDef SPI InitStruct 0 LL GPIO InitTypeDef GP
  • 使用Linux内核里的spi屏驱动-fbtft

    Linux内核里已经提供spi接口小屏的设备驱动 在内核的配置选项 make menuconfig ARCH arm CROSS COMPILE arm linux gnueabihf Device Drivers gt Graphics
  • 外设驱动库开发笔记22:ADXL345三轴数字加速度计驱动

    移动设备的广泛应用增加对移动过程中各种参数的检测需求 ADXL345三轴数字加速度计可以用来检测加速度 进而测量倾斜角度等 在这一篇中 我们将讨论ADXL345三轴数字加速度计驱动程序的设计与实现 1 功能概述 ADXL345是一款小而薄的
  • SPI总线verilog hdl实现(1)SPI通信

    SPI总线传输只需要4根线就能完成 这四根线的作用分别如下 SCK Serial Clock SCK是串行时钟线 作用是Master向Slave传输时钟信号 控制数据交换的时机和速率 MOSI Master Out Slave in 在SP
  • Linux内核自带SPI设备驱动测试程序分析:spidev_test.c

    在Linux系统中 SPI 的用户模式设备接口的驱动源码位于 drivers spi spidev c 在应用层生成 dev spidev 的节点 可以通过 read write 达到与硬件设备的 SPI 通信 下面介绍spidev驱动移植
  • CH347读写SPI Flash

    前面耽搁了几天 今天终于把CH347 SPI接口调试好了 CH347动态库中SPI接口函数如下 typedef struct SPI CONFIG UCHAR iMode 0 3 SPI Mode0 1 2 3 UCHAR iClock 0
  • SD卡系列之---SD初始化(SPI)

    SD卡分为SDIO模式与SPI模式 SDIO模式使用SD总线协议 使用4根数据线进行数据传输 SPI使用1收1发2根数据线数据传输 理论上SDIO模式会比SPI模式速度快4倍 但SDIO模式还牵扯到CRC校验位的计算 所以 如果使用CPU有
  • 谁在驱动程序代码中调用“probe”函数?

    我试图理解thisomap2 panda 板的 mcspi 驱动程序代码 我不明白谁打电话probe函数以及调用链是什么this驱动代码 设备连接时如何通知驱动程序 探针函数由spi omap2 mcspi c保存在static struc
  • Spidev 不使用 ioctl 同时写入/读取

    我希望找到一些帮助 即使这个问题可能更多地与硬件相关而不是与软件相关 我们将会看到 我正在开发基于 Freescales P1021 处理器 ppc e500v2 内核 的定制板 将连接外部 PCB 并可通过 SPI 进行配置 该外部 PC
  • 是什么让 SPI 比 I2C 协议更快 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我了解 I2C 和 SPI 通信的基础知识 因为两者都是同步协议 我想知道是什么让 SPI 比 I2C 更快 如果我没记错的话 使用 I2

随机推荐

  • C语言Socket编程(TCP与UDP)

    C语言Socket编程 xff08 TCP与UDP xff09 UDP xff1a span class token comment udp server c span span class token macro property spa
  • ubuntu 换源深层次解析

    换源也是一个容易出错的问题 xff0c 本文以树莓派为例展开 xff0c x86也是一样的操作 那么假设成立的话 xff0c 就要记住我们是在树莓派 xff08 arm xff09 上安装的ubuntu xff0c 不是X86 xff0c
  • 1运动规划概述

    Motion planning autonomous robot 总结一下什么是自主机器人 xff1a 首先我们需要状态估计 xff08 定位 xff09 xff1b 基于此 xff0c 利用传感器融合人建立一个周围环境的三维地图 xff1
  • 5轨迹生成

    文章目录 Introduction全局与局部方法全局与局部对比 轨迹生成T xff08 what xff09 为什么需要平滑轨迹呢Y why W how 微分平坦 xff08 Differential Flatness xff09 TQua
  • java--通过JNI调用动态链接库(dll、so、dylib)

    公司项目需要用到第三方qt插件 xff0c 由于业务是偏底层的 xff0c 基本上用不到jar包 xff0c 因此只能通过jni的方式调用 没学过c 43 43 xff0c 十多天的摸爬滚打一路过来不容易啊 xff01 今天总算跑通了 网上
  • 在头文件实现函数的重定义问题

    例如一个头文件headfile h这样写 pragma once bool Func return true 在这个头文件被多个地方包含的时候就会出问题 xff0c 链接时报错 FuncB报重定义 fatal error LNK1169 找
  • 数字电路基础知识系列(六)之LC滤波器的基础知识

    针对设计过程的问题 xff0c 如有疑问 xff0c 欢迎留言讨论 xff01 点我返回目录 LC滤波器 xff0c 是指将电感 L 与电容器 进行组合设计构成的滤波电路 xff0c 可去除或通过特定频率的无源器件 电容器具有隔直流通交流
  • I-002 智能家居系列--ESP8266环境搭建

    智能家居系列 1 NodeMCU简介2 硬件介绍3 开发工具的选择3 1 软件介绍3 2 环境搭建 4 测试代码5 后续会更新这边文章 1 NodeMCU简介 NodeMCU简介 NodeMCU 是一个开源的 物联网 平台 它使用 Lua
  • I-000 智能家居系列--需求梳理

    智能家居系列 1 智能家居2 系统框架3 组成部分4 开发思路5 当前的进展 1 智能家居 智能家居的目的旨在提高人们的生活水平 xff0c 确保人们的生活更加舒适 2 系统框架 下图只是初版 xff0c 在具体的开发过程中 xff0c 会
  • Cartographer(二)使用思岚rplidar雷达进行cartographer建图

    一 修改launch文件和lua配置文件 xff08 1 xff09 修改revo lds lua 到目录下 xff0c 打开文件 home meng xx catographer ws src cartographer ros carto
  • 数字电路硬件设计系列(三)之缓启电路设计

    针对设计过程中的问题 xff0c 如有疑问 xff0c 欢迎留言评论 xff01 点我返回目录 1 简介 在一些大电压 大电流的产品中 xff0c 上电的瞬间通常会有较大的电流冲击 xff0c 下图是一款产品上电过程中波形 最大的电流达到1
  • 数字电路硬件设计系列(十)之RS485电路设计

    针对设计过程中的问题 xff0c 如有疑问 xff0c 欢迎留言评论 xff01 点我返回目录 1 简介 RS485通信属于串口通信中的半双工通信 xff0c RS485具有支持多节点 xff08 32个节点 xff09 传输距离远 xff
  • 数字电路硬件设计系列(五)之AT89C51/C52最小系统设计

    针对设计过程中的问题 xff0c 如有疑问 xff0c 欢迎留言评论 xff01 点我返回目录 1 简介 AT89C51 C52是指两个系列的产品 xff0c 具体包含AT89C51 AT89C52 xff0c 但是最小系统的组成基本上相差
  • 1.18 接地设计问题(非常实用)

    目录 1 简介 2 接地的分类 3 接地的目的 3 1 对地阻抗低 3 2 地平面稳定 3 3 对地均衡 4 共地耦合干扰 5 常用的基地方式 6 安全地 防雷击浪涌接地的接法 1 简介 在电路设计的过程中 xff0c 接地是一个老生常谈的
  • 1.0 硬件设计基础(面试题)

    1 滤波磁珠和滤波电感的区别 磁珠由导线穿过铁氧体组成 xff0c 直流电阻很小 xff0c 在低频时阻抗也很小 xff0c 对直流信号几乎没有影响 在高频 xff08 几十兆赫兹以上 xff09 时磁珠阻抗比较大 xff0c 高频电磁场在
  • 1.19 旁路电容与去耦电容

    1 简介 旁路电容和旁路电容是电路设计过程中十分常见 xff0c 但是很多应将工程师都没有真正区分这两者的功能 xff0c 我们先来看看这两个单词在英文中的意思 xff1a 电容英文中文解释旁路电容Bypass抄近道去耦电容couple是一
  • vins运行1

    vins fusion 运行笔记 安装code utils 1 fatal error elfutils libdw h 没有那个文件或目录 没有安装 sudo apt get install libdw dev 2 fatal error
  • 四旋翼无人机汇报

    我主要负责的是四旋翼无人机的组装和飞控参数的调试 遇到的问题 当初焊接时由于时间紧张用的是比较细的焊条 xff0c 虽然焊接成功 xff0c 但是导致了后续插拔导线时容易接触不良 xff0c 后来在焊点处重新焊接 由于未在地面站软件中修改无
  • 载波相位差分定位

    x1f30e 我接触差分定位是通过暑期在南京北斗一段时间的实习 x1f30e 我把 Lambda算法的zip和rar上传到了这里 x1f30e https wwi lanzoui com b01bp70yj x1f30e 再推荐一个gith
  • nRF SPI 与 TWI 操作相关 (BMI088 与 MLX90614 举例)

    SPI0 与 TWI0 的 ID相同 xff0c SPI0 与 TWI0 的 ID相同 编译时有报错 若要避免 xff0c 有两个方法 1 使用不同ID外设 2 使用模拟SPI或模拟IIC nRF SPI 初始化 sdk config h