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 举例) 的相关文章

  • SPI通信方式总结

    SPI xff08 Serial Peripheral interface xff09 是一种同步串行传输规范 xff0c 也是单片机外设芯片串行外设扩展接口 xff0c 该接口是一种高速 xff0c 全双工 xff0c 同步的通信总线 x
  • 使用DMA+SPI驱动Aliyun Things 上的ST7789H2 LCD屏幕

    目录 前言硬件CUBEMX时钟树GPIOSPI 代码部分LCD驱动中断服务函数测试代码现象 前言 1 xff1a 驱动程序参考自https blog csdn net BearPi article details 104311705 2 x
  • pixhawk px4 spi设备驱动

    此篇blog是以nuttx官网介绍为出发点 xff0c 先分析如何初始化的 xff0c 再分析如何读取传感器数据的 xff0c 最后对比了字符型设备操作和spi驱动的实现方式的差别 如有错误还请指正 6 字符型设备 所有的结构体和API都在
  • ((硬件spi+dma)+模拟spi)驱动LCD5110

    span class hljs preprocessor ifndef spi dma h span span class hljs preprocessor define spi dma h span span class hljs pr
  • 【STM32】基于SPI的OLED显示屏与DHT20温湿度采集显示数据

    STM32 基于SPI总线的OLED显示屏与DHT20温湿度采集显示数据 一 SPI通讯协议二 关于0 96英寸OLED模块三 硬件连接四 示例代码五 代码修改与撰写六 屏幕歌词滚动1 滚屏设置2 代码撰写 七 展示八 DHT20温湿度采集
  • UART、RS232、RS485、I2C和SPI的介绍

    基本知识 串行通信 xff1a 多个数据通过一条数据线 xff0c 依次传输并行通信 xff1a 多个数据通过多条数据线 xff0c 一次性传输单工通信 xff1a 只能接收数据或者发送数据 xff08 遥控器 收音机 xff09 半双工通
  • 老猿学5G扫盲贴:NEF、NRF、AF、UPF以及DN的功能

    专栏 xff1a Python基础教程目录 专栏 xff1a 使用PyQt开发图形界面Python应用 专栏 xff1a PyQt入门学习 老猿Python博文目录 NEF xff1a Network Exposure Function x
  • nRF SPI 与 TWI 操作相关 (BMI088 与 MLX90614 举例)

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

    文章目录 目的 基础说明 使用演示 其它补充 总结 目的 SPI是单片机中比较常用的一个功能 这篇文章将对CH32V307中相关内容进行说明 本文使用沁恒官方的开发板 CH32V307 EVT R1沁恒RISC V模块MCU赤兔评估板 进行
  • Raspberry Pi 与Arduino SPI通信

    本教程介绍了使用SPI 串行外围设备接口总线 进行Raspberry Pi与Arduino通讯和控制的基本框架 SPI代表了一种非常完善的芯片间通信方法 该方法在两种设备的硬件中均实现 在这里 我们将详细探讨SPI 讨论硬件和软件注意事项
  • FPGA驱动0.96oled显示屏 (4线 SPI) verilog语言

    之前也陆陆续续看了很多博客 也都能在自己的屏幕上显示出来 但是问题就是不知道怎么修改代码显示自己希望显示的东西 而且由于没注释原因看不太懂 最终的实现效果最终实现效果视频 b站视频链接1 评论区有人给了源码的百度网盘链接 csdn博客链接1
  • 各种通信接口的简单对比

    对比表 同步方式与异步方式的主要区别在于 是否传输时钟信号 只要是通訊前雙方需要設定相同波特率的 都是異步傳輸方式 异步传输 Asynchronous Transmission 每次异步传输的信息都以一个起始位开头 它通知接收方数据已经到达
  • Linux SPI 总线 和设备驱动架构之三:SPI控制器驱动

    通过第一篇文章 我们已经知道 整个SPI驱动架构可以分为协议驱动 通用接口层和控制器驱动三大部分 其中 控制器驱动负责最底层的数据收发工作 为了完成数据收发工作 控制器驱动需要完成以下这些功能 1 申请必要的硬件资源 例如中断 DMA通道
  • Java SPI机制

    一 SPI机制简介 SPI的全名为Service Provider Interface java spi机制的思想 系统里抽象的各个模块 往往有很多不同的实现方案 在面向的对象的设计里 一般推荐模块之间基于接口编程 模块之间不对实现类进行硬
  • SPI总线verilog hdl实现(1)SPI通信

    SPI总线传输只需要4根线就能完成 这四根线的作用分别如下 SCK Serial Clock SCK是串行时钟线 作用是Master向Slave传输时钟信号 控制数据交换的时机和速率 MOSI Master Out Slave in 在SP
  • STM32实现MLX90614非接触测温串口显示(标准库与HAL库实现)

    目录 模块选择 编程环境 MLX90614基本原理 通信协议 SMBus通信 类IIC通信 代码实现 STM32与模块之间接线表 1 标准库实现温度采集 2 HAL库实现温度采集 模块选择 STM32F103C8T6 MLX90614 非接
  • 谁在驱动程序代码中调用“probe”函数?

    我试图理解thisomap2 panda 板的 mcspi 驱动程序代码 我不明白谁打电话probe函数以及调用链是什么this驱动代码 设备连接时如何通知驱动程序 探针函数由spi omap2 mcspi c保存在static struc
  • SPI 电子墨水显示屏与 PIC 18F46K22 连接时出现问题

    我正在使用一个图18F46K22 https ww1 microchip com downloads en DeviceDoc 40001412G pdf在 SPI 主模式下与Waveshare 1 54 电子纸模组 https www w
  • 是什么让 SPI 比 I2C 协议更快 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我了解 I2C 和 SPI 通信的基础知识 因为两者都是同步协议 我想知道是什么让 SPI 比 I2C 更快 如果我没记错的话 使用 I2
  • STM32 传输结束时,循环 DMA 外设到存储器的行为如何?

    我想问一下 在以下情况下 STM32 中的 DMA SPI rx 会如何表现 我有一个指定的 例如 96 字节数组 名为 A 用于存储从 SPI 接收到的数据 我打开循环 SPI DMA 它对每个字节进行操作 配置为 96 字节 是否有可能

随机推荐

  • 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