提示:通过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, ®);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, ®);// 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, ®, 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, ®, 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.结果
总结
有什么问题,可以评论区里面提一下,看到都会帮忙解决,这个案例只是简单应用,没有涉及复杂的使用过程。