STM32 SPI驱动读取LSM6DSRTR

提示:通过SPI驱动读取传感器数据

文章目录

  • 前言
  • 一、LSM6DSRTR
  • 二、配置步骤
  • 1.配置SPI
  • 2.引入 LSM驱动库
  • 3.结果
  • 总结

  • 前言

    制作一个倾角传感器,通过SPI读取LSM6DSRTR的加速度数据转换为角度,不用IIC的原因是考虑IIC通讯的协议过于繁琐,且会影响后续的发包速率。


    一、LSM6DSRTR

    六轴传感器,最好用ST的芯片来读取,主要是ST在这块已经提供好驱动了,其它也行,都一样简单。其次就是,你需要配置好SPI,这个很重要,不然很容易读不出来。

    二、配置步骤

    1.配置SPI

    注意:通过STM32CUBEMX 来构建代码

    static void MX_SPI1_Init(void)
    {
      hspi1.Instance = SPI1;
      hspi1.Init.Mode = SPI_MODE_MASTER;
      hspi1.Init.Direction = SPI_DIRECTION_2LINES;
      hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
      hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
      hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
      hspi1.Init.NSS = SPI_NSS_SOFT;
      hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
      hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
      hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
      hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
      hspi1.Init.CRCPolynomial = 7;
      if (HAL_SPI_Init(&hspi1) != HAL_OK)
      {
        Error_Handler();
      }
      /* USER CODE BEGIN SPI1_Init 2 */
    
      /* USER CODE END SPI1_Init 2 */
    }
    

    2.引入 LSM驱动库


    案例代码

    #include <string.h>
    #include <stdio.h>
    #include "lsm6dsr_reg.h"
    #include "stm32l0xx_hal.h"
    #include "main.h"
    
    #define CS_Pin GPIO_PIN_4
    #define CS_GPIO_Port GPIOA
    #define LED_Pin GPIO_PIN_12
    #define LED_GPIO_Port GPIOA
    #define BOOT_TIME 10 // ms
    #define PI 3.1415926
    extern SPI_HandleTypeDef hspi1;
    
    extern UART_HandleTypeDef huart1;
    static stmdev_ctx_t dev_ctx;
    
    /* Private variables ---------------------------------------------------------*/
    static int16_t data_raw_acceleration[3];
    static int16_t data_raw_angular_rate[3];
    static int16_t data_raw_temperature;
    static float acceleration_mg[3];
    static float angular_rate_mdps[3];
    static uint8_t whoamI, rst;
    static uint8_t tx_buffer[1000];
    
    static int32_t platform_write(void *handle, uint8_t reg, const uint8_t *bufp,
                                  uint16_t len);
    static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp,
                                 uint16_t len);
    static void tx_com(uint8_t *tx_buffer, uint16_t len);
    static void platform_delay(uint32_t ms);
    
    /* Main Example --------------------------------------------------------------*/
    //在主函数里面调用这个接口就行
    void lsm6dsr_read_angle_data_polling(void)
    {
    
        uint8_t reg;
        /* Read output only if new xl value is available */
        lsm6dsr_xl_flag_data_ready_get(&dev_ctx, &reg);
    
        if (reg)
        {
            /* Read acceleration field data */
            memset(data_raw_acceleration, 0x00, 3 * sizeof(int16_t));
            lsm6dsr_acceleration_raw_get(&dev_ctx, data_raw_acceleration);
            acceleration_mg[0] =
                lsm6dsr_from_fs2g_to_mg(data_raw_acceleration[0]);
            acceleration_mg[1] =
                lsm6dsr_from_fs2g_to_mg(data_raw_acceleration[1]);
            acceleration_mg[2] =
                lsm6dsr_from_fs2g_to_mg(data_raw_acceleration[2]);
    
            /* 注意:atan算出来的是弧度值, 然后1弧度 = 180/Π */
            float angle_x = atan(acceleration_mg[0] / sqrt(acceleration_mg[2] * acceleration_mg[2] + acceleration_mg[1] * acceleration_mg[1])) * 180 / PI;
            float angle_y = atan(acceleration_mg[1] / sqrt(acceleration_mg[0] * acceleration_mg[0] + acceleration_mg[2] * acceleration_mg[2])) * 180 / PI;
            float angle_z = atan(acceleration_mg[2] / sqrt(acceleration_mg[0] * acceleration_mg[0] + acceleration_mg[1] * acceleration_mg[1])) * 180 / PI;
    
            sprintf((char *)tx_buffer,
                    "Acceleration [mg]:%4.2f\t%4.2f\t%4.2f\r\n",
                    acceleration_mg[0], acceleration_mg[1], acceleration_mg[2]);
            //这边是计算出来的角度值
            sprintf((char *)tx_buffer,
                    "Angle :x %4.2f\t y %4.2f\t z %4.2f\r\n",
                    angle_x, angle_y, angle_z);
            tx_com(tx_buffer, strlen((char const *)tx_buffer));
        }
    
        // lsm6dsr_gy_flag_data_ready_get(&dev_ctx, &reg);
    
        // if (reg)
        // {
        //     /* Read angular rate field data */
        //     memset(data_raw_angular_rate, 0x00, 3 * sizeof(int16_t));
        //     lsm6dsr_angular_rate_raw_get(&dev_ctx, data_raw_angular_rate);
        //     angular_rate_mdps[0] =
        //         lsm6dsr_from_fs2000dps_to_mdps(data_raw_angular_rate[0]);
        //     angular_rate_mdps[1] =
        //         lsm6dsr_from_fs2000dps_to_mdps(data_raw_angular_rate[1]);
        //     angular_rate_mdps[2] =
        //         lsm6dsr_from_fs2000dps_to_mdps(data_raw_angular_rate[2]);
        //     sprintf((char *)tx_buffer,
        //             "Angular rate [mdps]:%4.2f\t%4.2f\t%4.2f\r\n",
        //             angular_rate_mdps[0], angular_rate_mdps[1], angular_rate_mdps[2]);
        //     tx_com(tx_buffer, strlen((char const *)tx_buffer));
        // }
        platform_delay(1000);
    }
    
    /*
     * @brief  Write generic device register (platform dependent)
     *
     * @param  handle    customizable argument. In this examples is used in
     *                   order to select the correct sensor bus handler.
     * @param  reg       register to write
     * @param  bufp      pointer to data to write in register reg
     * @param  len       number of consecutive register to write
     *
     */
    static int32_t platform_write(void *handle, uint8_t reg, const uint8_t *bufp,
                                  uint16_t len)
    {
        HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);
        HAL_SPI_Transmit(handle, &reg, 1, 1000);
        HAL_SPI_Transmit(handle, (uint8_t *)bufp, len, 1000);
        HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);
    
        return 0;
    }
    
    /*
     * @brief  Read generic device register (platform dependent)
     *
     * @param  handle    customizable argument. In this examples is used in
     *                   order to select the correct sensor bus handler.
     * @param  reg       register to read
     * @param  bufp      pointer to buffer that store the data read
     * @param  len       number of consecutive register to read
     *
     */
    static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp,
                                 uint16_t len)
    {
        reg |= 0x80;
        HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);
        HAL_SPI_Transmit(handle, &reg, 1, 1000);
        HAL_SPI_Receive(handle, bufp, len, 1000);
        HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);
        return 0;
    }
    
    /*
     * @brief  Send buffer to console (platform dependent)
     *
     * @param  tx_buffer     buffer to transmit
     * @param  len           number of byte to send
     *
     */
    static void tx_com(uint8_t *tx_buffer, uint16_t len)
    {
        HAL_UART_Transmit(&huart1, tx_buffer, len, 1000);
    }
    
    /*
     * @brief  platform specific delay (platform dependent)
     *
     * @param  ms        delay in ms
     *
     */
    static void platform_delay(uint32_t ms)
    {
        HAL_Delay(ms);
    }
    
    /*
     * @brief  platform specific initialization (platform dependent)
     */
    void platform_init(void)
    {
        /* Initialize mems driver interface */
        dev_ctx.write_reg = platform_write;
        dev_ctx.read_reg = platform_read;
        dev_ctx.handle = &hspi1;
    
        /* Wait sensor boot time */
        platform_delay(BOOT_TIME);
        /* Check device ID */
        while (1)
        {
            // 考虑如何喂狗
            lsm6dsr_device_id_get(&dev_ctx, &whoamI);
            if (whoamI == LSM6DSR_ID)
            {
                sprintf((char *)tx_buffer,
                        "Read id :0x%2x\r\n",
                        whoamI);
                tx_com(tx_buffer, strlen((char const *)tx_buffer));
    
                break;
            }
            platform_delay(BOOT_TIME);
        }
        /* Restore default configuration */
        lsm6dsr_reset_set(&dev_ctx, PROPERTY_ENABLE);
        do
        {
            lsm6dsr_reset_get(&dev_ctx, &rst);
        } while (rst);
    
        /* Disable I3C interface */
        lsm6dsr_i3c_disable_set(&dev_ctx, LSM6DSR_I3C_DISABLE);
        /* Enable Block Data Update */
        lsm6dsr_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
        /* Set Output Data Rate */
        lsm6dsr_xl_data_rate_set(&dev_ctx, LSM6DSR_XL_ODR_12Hz5);
        lsm6dsr_gy_data_rate_set(&dev_ctx, LSM6DSR_GY_ODR_12Hz5);
        /* Set full scale */
        lsm6dsr_xl_full_scale_set(&dev_ctx, LSM6DSR_2g);
        lsm6dsr_gy_full_scale_set(&dev_ctx, LSM6DSR_2000dps);
        /* Configure filtering chain(No aux interface)
         * Accelerometer - LPF1 + LPF2 path
         */
        lsm6dsr_xl_hp_path_on_out_set(&dev_ctx, LSM6DSR_LP_ODR_DIV_100);
        lsm6dsr_xl_filter_lp2_set(&dev_ctx, PROPERTY_ENABLE);
    }
    
    

    3.结果


    总结

    有什么问题,可以评论区里面提一下,看到都会帮忙解决,这个案例只是简单应用,没有涉及复杂的使用过程。

    作者:&向上

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32 SPI驱动读取LSM6DSRTR

    发表回复