金牌会员
 
- 积分
- 2099
- 金钱
- 2099
- 注册时间
- 2017-2-11
- 在线时间
- 306 小时
|
本帖最后由 jiangyy 于 2021-3-25 13:28 编辑
STMicro 的 LSM6DSL 和 LSM6DSM 采用创新型电源管理技术、增强型陀螺仪设计,且具有高效的数据批处理能力。相比目前最新的 LSM6DS3 和 LSM6DS3H 器件,这些器件的功耗减少多达 50%。 符合最常见的创新型操作系统要求,可帮助开发人员实现常见移动平台的个性化和省电功能的价值最大化。 这些运动检测器件已获得 Google Daydream 和 Tango 认证,并支持 android 移动产品上身临其境的虚拟和增强现实技术。
此外,最新型传感器通过提高升压陀螺仪精度来支持增强型用户体验,如光学防抖 (OIS)、视觉定位检测和手势识别,而且还集成了加速计驱动型步伐检测、步伐计数和计步器,以及倾斜和大幅度运动检测,从而减轻手持式设备和应用开发人员的工作。
在这两个模块中,LSM6DSM 针对摄像头 OIS 采用了专门的附加处理和串行端口。 陀螺仪的噪声降低了 40% 并采用了可配置率滤波器,这两个特性使现有器件 (LSM6DS3H).的摄像头 OIS 性能得以提升。 相比使用分立式 OIS 传感器的解决方案,LSM6DSM 不仅元件少,占据板空间小,而且功耗不到替代性设计的 1/6。
特性
- 3 轴加速计:具有 ±2 g、±4 g、±8 g、±16g 满量程范围
- 3 轴 MEMS 陀螺仪:±125 dps、±245 dps、±500 dps、±1000dps 和 ±2000 dps
- 工作电流:0.4 mA(正常组合模式):0.65 mA(高性能组合模式)
- 封装:2.5 mm x 3.0 mm x 0.83 mm、LGA-14
- 模拟电源电压范围:1.71 V 至 3.6 V
- 具有批采集功能的智能化 FIFO,可达 4 KB
- 地磁传感器用于外部磁传感器纠正的软、硬熨平
基于STM32CUBEIDE,开发此陀螺仪,基本已调试完成,分享代码如下:
一、IIC底层驱动
1.头文件
- /*
- * bsp_i2c4.h
- *
- * Created on: Dec 13, 2020
- * Author: jiangyuanyuan
- */
- #ifndef INC_BSP_I2C4_H_
- #define INC_BSP_I2C4_H_
- #include "gpio.h"
- #include "bsp_delay.h"
- //IO方向设置
- #define I2C_4_SDA_IN() {GPIOD->MODER&=~(3<<(13*2));GPIOD->MODER|=0<<13*2;} //PD13输入模式
- #define I2C_4_SDA_OUT() {GPIOD->MODER&=~(3<<(13*2));GPIOD->MODER|=1<<13*2;} //PD13输出模式
- //IO操作
- #define I2C_4_SCL(n) (n?HAL_GPIO_WritePin(GPIOD,GPIO_PIN_12,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOD,GPIO_PIN_12,GPIO_PIN_RESET))//SCL
- #define I2C_4_SDA(n) (n?HAL_GPIO_WritePin(GPIOD,GPIO_PIN_13,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOD,GPIO_PIN_13,GPIO_PIN_RESET))//SDA
- #define I2C_4_READ_SDA HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_13)//输入SDA
- //I2C_4所有操作函数
- void I2C_4_Init(void); //初始化IIC的IO口
- void I2C_4_Start(void); //发送IIC开始信号
- void I2C_4_Stop(void); //发送IIC停止信号
- void I2C_4_Send_Byte(uint8_t txd); //IIC发送一个字节
- uint8_t I2C_4_Read_Byte(uint8_t ack); //IIC读取一个字节
- uint8_t I2C_4_Wait_Ack(void); //IIC等待ACK信号
- void I2C_4_Ack(void); //IIC发送ACK信号
- void I2C_4_NAck(void); //IIC不发送ACK信号
- void I2C_4_Write_One_Byte(uint8_t daddr,uint8_t addr,uint8_t data);
- uint8_t I2C_4_Read_One_Byte(uint8_t daddr,uint8_t addr);
- #endif /* INC_BSP_I2C4_H_ */
复制代码 2.C文件
二、ISM6DSL应用层
1.头文件
- /*
- * bsp_lsm6dsl.h
- *
- * Created on: Dec 13, 2020
- * Author: jiangyuanyuan
- */
- #ifndef INC_BSP_LSM6DSL_H_
- #define INC_BSP_LSM6DSL_H_
- #include "stdio.h"
- #include "bsp_i2c4.h"
- #include "bsp_lcd.h"
- #define SENSITIVITY_LIS3MDL_16Ga 1711.0 //LSB/Ga
- /* I2C Addresses */
- #define ACC_GYRO_ADDRESS 0xD6
- /* sensor output data */
- #define LSM6DSL_OUTX_L_G 0X22
- #define LSM6DSL_OUTX_H_G 0X23
- #define LSM6DSL_OUTY_L_G 0X24
- #define LSM6DSL_OUTY_H_G 0X25
- #define LSM6DSL_OUTZ_L_G 0X26
- #define LSM6DSL_OUTZ_H_G 0X27
- #define LSM6DSL_OUTX_L_XL 0X28
- #define LSM6DSL_OUTX_H_XL 0X29
- #define LSM6DSL_OUTY_L_XL 0X2A
- #define LSM6DSL_OUTY_H_XL 0X2B
- #define LSM6DSL_OUTZ_L_XL 0X2C
- #define LSM6DSL_OUTZ_H_XL 0X2D
- /* sensor control reg */
- #define LSM6DSL_CTRL1_XL 0X10
- #define LSM6DSL_CTRL2_G 0X11
- #define LSM6DSL_CTRL3_C 0X12
- #define LSM6DSL_CTRL4_C 0X13
- #define LSM6DSL_CTRL5_C 0X14
- #define LSM6DSL_CTRL6_G 0X15
- #define LSM6DSL_CTRL7_G 0X16
- #define LSM6DSL_CTRL8_XL 0X17
- #define LSM6DSL_CTRL9_XL 0X18
- #define LSM6DSL_CTRL10_C 0X19
- #define LSM6DSL_INT1_CTRL 0X0D
- #define LSM6DSL_INT2_CTRL 0X0E
- #define LSM6DSL_WHO_AM_I 0x0F //get id
- #define LSM6DSL_SENSORHUB1_REG 0X2E
- #define LSM6DSL_SENSORHUB2_REG 0X2F
- #define LSM6DSL_SENSORHUB3_REG 0X30
- #define LSM6DSL_SENSORHUB4_REG 0X31
- #define LSM6DSL_SENSORHUB5_REG 0X32
- #define LSM6DSL_SENSORHUB6_REG 0X33
- #define LSM6DSL_SENSORHUB7_REG 0X34
- #define LSM6DSL_SENSORHUB8_REG 0X35
- #define LSM6DSL_SENSORHUB9_REG 0X36
- #define LSM6DSL_SENSORHUB10_REG 0X37
- #define LSM6DSL_SENSORHUB11_REG 0X38
- #define LSM6DSL_SENSORHUB12_REG 0X39
- #define LSM6DSL_FIFO_STATUS1 0X3A
- #define LSM6DSL_FIFO_STATUS2 0X3B
- #define LSM6DSL_FIFO_STATUS3 0X3C
- #define LSM6DSL_FIFO_STATUS4 0X3D
- #define LSM6DSL_FIFO_DATA_OUT_L 0X3E
- #define LSM6DSL_FIFO_DATA_OUT_H 0X3F
- #define LSM6DSL_TIMESTAMP0_REG 0X40
- #define LSM6DSL_TIMESTAMP1_REG 0X41
- #define LSM6DSL_TIMESTAMP2_REG 0X42
- #define LSM6DSL_STEP_TIMESTAMP_L 0X49
- #define LSM6DSL_STEP_TIMESTAMP_H 0X4A
- #define LSM6DSL_STEP_COUNTER_L 0X4B
- #define LSM6DSL_STEP_COUNTER_H 0X4C
- #define LSM6DSL_SENSORHUB13_REG 0X4D
- #define LSM6DSL_SENSORHUB14_REG 0X4E
- #define LSM6DSL_SENSORHUB15_REG 0X4F
- #define LSM6DSL_SENSORHUB16_REG 0X50
- #define LSM6DSL_SENSORHUB17_REG 0X51
- #define LSM6DSL_SENSORHUB18_REG 0X52
- #define LSM6DSL_FUNC_SRC1 0X53
- #define LSM6DSL_FUNC_SRC2 0X54
- #define LSM6DSL_TAP_CFG 0X58
- #define LSM6DSL_TAP_THS_6D 0X59
- #define LSM6DSL_INT_DUR2 0X5A
- #define LSM6DSL_WAKE_UP_THS 0X5B
- #define LSM6DSL_WAKE_UP_DUR 0X5C
- #define LSM6DSL_FREE_FALL 0X5D
- #define LSM6DSL_MD1_CFG 0X5E
- #define LSM6DSL_MD2_CFG 0X5F
- /************** Access Device RAM *******************/
- #define LSM6DSL_MASTER_CMD_CODE 0X60
- #define LSM6DSL_SENS_SYNC_SPI_ERROR_CODE 0X61
- /************** Embedded functions register mapping *******************/
- #define LSM6DSL_OUT_MAG_RAW_X_L 0x66
- #define LSM6DSL_OUT_MAG_RAW_X_H 0x67
- #define LSM6DSL_OUT_MAG_RAW_Y_L 0x68
- #define LSM6DSL_OUT_MAG_RAW_Y_H 0x69
- #define LSM6DSL_OUT_MAG_RAW_Z_L 0x6A
- #define LSM6DSL_OUT_MAG_RAW_Z_H 0x6B
- #define LSM6DSL_X_OFS_USR 0x73
- #define LSM6DSL_Y_OFS_USR 0x74
- #define LSM6DSL_Z_OFS_USR 0x75
- #define LSM6DSL_STATUS_REG 0x1E
- /*******************************************************************************
- * Register : CTRL1_XL
- * Address : 0X10
- * Bit Group Name: FS_XL
- * Permission : RW
- *******************************************************************************/
- typedef enum {
- LSM6DSL_FS_XL_2g = 0x00,
- LSM6DSL_FS_XL_16g = 0x04,
- LSM6DSL_FS_XL_4g = 0x08,
- LSM6DSL_FS_XL_8g = 0x0C,
- } LSM6DSL_FS_XL_t;
- /*******************************************************************************
- * Register : CTRL1_XL
- * Address : 0X10
- * Bit Group Name: ODR_XL
- * Permission : RW
- *******************************************************************************/
- typedef enum {
- LSM6DSL_ODR_XL_POWER_DOWN = 0x00,
- LSM6DSL_ODR_XL_13Hz = 0x10,
- LSM6DSL_ODR_XL_26Hz = 0x20,
- LSM6DSL_ODR_XL_52Hz = 0x30,
- LSM6DSL_ODR_XL_104Hz = 0x40,
- LSM6DSL_ODR_XL_208Hz = 0x50,
- LSM6DSL_ODR_XL_416Hz = 0x60,
- LSM6DSL_ODR_XL_833Hz = 0x70,
- LSM6DSL_ODR_XL_1660Hz = 0x80,
- LSM6DSL_ODR_XL_3330Hz = 0x90,
- LSM6DSL_ODR_XL_6660Hz = 0xA0,
- LSM6DSL_ODR_XL_13330Hz = 0xB0,
- } LSM6DSL_ODR_XL_t;
- /*select io device*/
- typedef enum
- {
- USE_SPI = 0,
- USE_I2C = 1
- }io_device;
- void Lsm_Init_iic(void);
- void Lsm_Get_Rawacc(void);
- void Lsm_Get_Rawgryo(void);
- #endif /* INC_BSP_LSM6DSL_H_ */
复制代码
2.C文件
- /*
- * bsp_lsm6dsl.c
- *
- * Created on: Dec 13, 2020
- * Author: jiangyuanyuan
- */
- #include "bsp_lsm6dsl.h"
- void LSM_WriteOneByte(uint8_t Add,uint8_t WriteAddr,uint8_t DataToWrite) //I2C_4从指定地址写入一个字节
- {
- I2C_4_Start();
- I2C_4_Send_Byte(Add); //发送I2C_4地址
- I2C_4_Wait_Ack();
- I2C_4_Send_Byte(WriteAddr); //发送地址
- I2C_4_Wait_Ack();
- I2C_4_Send_Byte(DataToWrite); //发送字节
- I2C_4_Wait_Ack();
- I2C_4_Stop(); //产生一个停止条件
- }
- uint8_t LSM_ReadOneByte(uint8_t Add,uint8_t ReadAddr) //I2C_4从指定地址读取一个字节
- {
- uint8_t temp=0;
- I2C_4_Start();
- I2C_4_Send_Byte(Add); //发送I2C_4地址
- I2C_4_Wait_Ack();
- I2C_4_Send_Byte(ReadAddr); //发送地址
- I2C_4_Wait_Ack();
- I2C_4_Start();
- I2C_4_Send_Byte(Add+1); //进入接收模式
- I2C_4_Wait_Ack();
- temp=I2C_4_Read_Byte(0);
- I2C_4_Stop(); //产生一个停止条件
- return temp;
- }
- uint8_t LSM_Write(uint8_t Add,uint8_t WriteAddr,uint8_t *pBuffer,uint8_t NumToWrite)//在指定的地址里面写入LSM的指定个数据
- {
- uint8_t i;
- I2C_4_Start();
- I2C_4_Send_Byte(Add<<1); //发送I2C_4地址
- I2C_4_Wait_Ack();
- I2C_4_Send_Byte(WriteAddr); //发送地址
- I2C_4_Wait_Ack();
- for(i=0;i<NumToWrite;i++)
- {
- I2C_4_Send_Byte(*(pBuffer+1));
- if(I2C_4_Wait_Ack()==0)
- {
- I2C_4_Stop();
- return 0;
- }
- }
- I2C_4_Stop();
- return 1;
- }
- void LSM_Read(uint8_t Add,uint8_t ReadAddr,uint8_t *pBuffer,uint8_t NumToRead) //在LSM里面的指定地址开始读出指定个数的数据
- {
- uint8_t i;
- I2C_4_Start();
- I2C_4_Send_Byte(Add<<1); //发送I2C_4地址
- I2C_4_Wait_Ack();
- I2C_4_Send_Byte(ReadAddr); //发送地址
- I2C_4_Wait_Ack();
- I2C_4_Start();
- I2C_4_Send_Byte((Add<<1)+1); //发送I2C_4地址
- I2C_4_Wait_Ack();
- for(i=0;i<NumToRead-1;i++)
- {
- pBuffer[i]=I2C_4_Read_Byte(1); //不发送应答
- }
- pBuffer[i]=I2C_4_Read_Byte(0); //发送应答
- }
- float calcAccel(int16_t input)
- {
- uint16_t accelRange = 2;
- float output = (float)input * 0.061 * (accelRange >> 1) / 1000;
- return output;
- }
- /***************************************USE IIC MODEL************************************/
- void Lsm_Init_iic(void) //IIC协议
- {
- // while(LSM_ReadOneByte(ACC_GYRO_ADDRESS,LSM6DSL_WHO_AM_I)!=0x6A); //检查ID是否存在
- LSM_WriteOneByte(ACC_GYRO_ADDRESS,LSM6DSL_CTRL2_G,0X1C); //陀螺仪12.5hz,2000dps
- LSM_WriteOneByte(ACC_GYRO_ADDRESS,LSM6DSL_CTRL10_C,0x38); //使能陀螺仪X,Y,Z轴
- //唤醒中断寄存器配置
- LSM_WriteOneByte(ACC_GYRO_ADDRESS,LSM6DSL_CTRL1_XL,0x60);
- LSM_WriteOneByte(ACC_GYRO_ADDRESS,LSM6DSL_TAP_CFG,0x90);
- LSM_WriteOneByte(ACC_GYRO_ADDRESS,LSM6DSL_WAKE_UP_DUR,0x00);
- LSM_WriteOneByte(ACC_GYRO_ADDRESS,LSM6DSL_WAKE_UP_THS,0x02);
- LSM_WriteOneByte(ACC_GYRO_ADDRESS,LSM6DSL_MD1_CFG,0x20);
- //6D Orientation Configuration 根据需求自行添加 (正反面值有差异)
- LSM_WriteOneByte(ACC_GYRO_ADDRESS,LSM6DSL_TAP_THS_6D,0x40);
- LSM_WriteOneByte(ACC_GYRO_ADDRESS,LSM6DSL_CTRL8_XL,0x01);
- }
- short ax,ay,az;
- float Ax,Ay,Az;
- //获取加速度值
- void Lsm_Get_Rawacc(void)
- {
- char ucBuff[20] = {'\0'};
- // short ax,ay,az;
- uint8_t buf[6];
- if((LSM_ReadOneByte(ACC_GYRO_ADDRESS,LSM6DSL_STATUS_REG)&0x01)!=0) //有数据生成
- {
- buf[0]= LSM_ReadOneByte(ACC_GYRO_ADDRESS,LSM6DSL_OUTX_H_XL);
- buf[1]= LSM_ReadOneByte(ACC_GYRO_ADDRESS,LSM6DSL_OUTX_L_XL);
- buf[2]= LSM_ReadOneByte(ACC_GYRO_ADDRESS,LSM6DSL_OUTY_H_XL);
- buf[3]= LSM_ReadOneByte(ACC_GYRO_ADDRESS,LSM6DSL_OUTY_L_XL);
- buf[4]= LSM_ReadOneByte(ACC_GYRO_ADDRESS,LSM6DSL_OUTZ_H_XL);
- buf[5]= LSM_ReadOneByte(ACC_GYRO_ADDRESS,LSM6DSL_OUTZ_L_XL);
- ax=(buf[0]<<8)|buf[1];
- ay=(buf[2]<<8)|buf[3];
- az=(buf[4]<<8)|buf[5];
- delay_ms(20);
- }
- Ax = ax/SENSITIVITY_LIS3MDL_16Ga;
- memset(ucBuff, '\0', sizeof(ucBuff));
- sprintf(ucBuff,"Ax:%.2f",Ax);
- LCD_ShowString(0, 130, 240, 12, 12, ucBuff);
- memset(ucBuff, '\0', sizeof(ucBuff));
- Ay = ay/SENSITIVITY_LIS3MDL_16Ga;
- sprintf(ucBuff,"Ay:%.2f",Ay);
- LCD_ShowString(0, 142, 240, 12, 12, ucBuff);
- memset(ucBuff, '\0', sizeof(ucBuff));
- Az = az/SENSITIVITY_LIS3MDL_16Ga;
- sprintf(ucBuff,"Az:%.2f",Az);
- LCD_ShowString(0, 154, 240, 12, 12, ucBuff);
- }
- short gx,gy,gz;
- //获取陀螺仪值
- void Lsm_Get_Rawgryo(void)
- {
- char ucBuff[20] = {'\0'};
- // short gx,gy,gz;
- uint8_t buf[6];
- if((LSM_ReadOneByte(ACC_GYRO_ADDRESS,LSM6DSL_STATUS_REG)&0x02)!=0) //有数据生成
- {
- buf[0]= LSM_ReadOneByte(ACC_GYRO_ADDRESS,LSM6DSL_OUTX_H_G);
- buf[1]= LSM_ReadOneByte(ACC_GYRO_ADDRESS,LSM6DSL_OUTX_L_G);
- buf[2]= LSM_ReadOneByte(ACC_GYRO_ADDRESS,LSM6DSL_OUTY_H_G);
- buf[3]= LSM_ReadOneByte(ACC_GYRO_ADDRESS,LSM6DSL_OUTY_L_G);
- buf[4]= LSM_ReadOneByte(ACC_GYRO_ADDRESS,LSM6DSL_OUTZ_H_G);
- buf[5]= LSM_ReadOneByte(ACC_GYRO_ADDRESS,LSM6DSL_OUTZ_L_G);
- gx=(buf[0]<<8)|buf[1];
- gy=(buf[2]<<8)|buf[3];
- gz=(buf[4]<<8)|buf[5];
- delay_ms(20);
- }
- memset(ucBuff, '\0', sizeof(ucBuff));
- sprintf(ucBuff,"gx:%10d",gx);
- LCD_ShowString(0, 166, 240, 12, 12, ucBuff);
- memset(ucBuff, '\0', sizeof(ucBuff));
- sprintf(ucBuff,"gy:%10d",gy);
- LCD_ShowString(0, 178, 240, 12, 12, ucBuff);
- memset(ucBuff, '\0', sizeof(ucBuff));
- sprintf(ucBuff,"gz:%10d",gz);
- LCD_ShowString(0, 190, 240, 12, 12, ucBuff);
- }
复制代码 3.main.c文件
- int main(void)
- {
- /* USER CODE BEGIN 1 */
- /* USER CODE END 1 */
- /* MCU Configuration--------------------------------------------------------*/
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
- HAL_Init();
- /* USER CODE BEGIN Init */
- /* USER CODE END Init */
- /* Configure the system clock */
- SystemClock_Config();
- /* USER CODE BEGIN SysInit */
- delay_init();
- /* USER CODE END SysInit */
- /* Initialize all configured peripherals */
- MX_GPIO_Init();
- MX_RTC_Init();
- MX_SDMMC1_SD_Init();
- MX_FATFS_Init();
- MX_TIM2_Init();
- MX_SPI1_Init();
- MX_RNG_Init();
- /* USER CODE BEGIN 2 */
- HAL_TIM_Base_Start_IT(&htim2);
- /* USER CODE END 2 */
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- LCD_Init();
- SD_Auto_NewFolder();
- Lsm_Init_iic();
- LCD_Clear(GREEN);
- POINT_COLOR = RED;
- BACK_COLOR = GREEN;
- LCD_ShowString(0, 0, 240, 32, 32, "Jaymie");
- LCD_ShowString(0, 40, 240, 24, 24, "Welcome to MAX");
- while (1)
- {
- /* USER CODE END WHILE */
- /* USER CODE BEGIN 3 */
- Display_Date_Time();
- MRTC_Get();
- Lsm_Get_Rawacc();
- Lsm_Get_Rawgryo();
- }
- /* USER CODE END 3 */
- }
复制代码
三、仿真结果
四、实物图显示
另外,有点小问题,就是精度的问题,后期有哪位小伙伴,可以参照我的代码优化一下,分享在这里。喜欢的朋友,点个赞。
|
|