这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【let'sdo2026年第3期】任务2:加速度计数据采集

共1条 1/1 1 跳转至页

【let'sdo2026年第3期】任务2:加速度计数据采集

高工
2026-11-11 21:16:17     打赏

本次活动中使用Grove - 三轴数字加速度计 (LIS3DHTR)采集加速度信息,结合之前的工程在NUCLEO-C562RE开发板上实现串口打印,实现采集LIS3DHTR的加速度信息,

1、硬件配置

Grove - 三轴数字加速度计 (LIS3DHTR)的主要特性如下

  • 核心芯片:LIS3DHTR(ST 意法半导体),属于超低功耗“nano”系列。

  • 测量量程:可通过软件动态选择 ±2g、±4g、±8g、±16g。

  • 接口选项:模块原生支持 Grove I2C 接口

  • I2C 地址:默认为 0x19。如果模块上的 SDO 引脚接地,地址会变为 0x18,方便总线上挂载多个设备。

  • 供电与温度:支持 3.3V / 5V 供电,工作温度范围 -40°C 至 +85°C,并内置温度传感器可用于补偿。

连接开发板的Arduino转接口到Arduino Grove 转接板,三轴数字加速度计 (LIS3DHTR)连接到Arduino Grove转接板的I2C接口,实现开发板与三轴数字加速度计的连接。硬件连接图如下。

Sensor_Hardware.png

2、CubeMX2配置

查看NUCLEO-C562RE开发板的原理图,I2C接口的引脚为:SCL-PB6,SDA-PB7

Arduino_I2C.png

CubeMX2配置以上引脚为I2C功能

PinOut_I2C1.png

选择I2C1外设的工作模式为I2C

Select_I2C1_mode.png

设置I2C外设的通讯速率为100kHz,I2C1的首选外设地址为0x19

I2C1_Config1.png

设置I2C外设的引脚为上拉

I2C1_Config2.png

保存并生成工程代码。

3、LIS3DH 传感器驱动

ST官方提供该传感器的驱动,

https://github.com/STMicroelectronics/lis3dh-pid/

下载代码仓库将其中的lis3dh_reg.c/h文件添加到工程中。STM32 VSCode工程是由CMake管理的,在顶层的CMakeList.txt文件中添加lis3dh_reg.c/h的信息

 # Stubs to be able to add compiler flag overrides, e.g. -Os    
 target_sources(${CMAKE_PROJECT_NAME} PRIVATE    
   # Add additional source files here    
   lis3dh_reg.c    
 )   
 # 添加浮点打印配置  
 target_link_options(${CMAKE_PROJECT_NAME} PUBLIC  
   # Add additional linker flags here  
   -u _printf_float  
 )

Cmake_add_info.png

main.c中添加驱动相关的头文件

#include <math.h>  
#include "lis3dh_reg.h"

定义LIS3DH 三轴数字加速度计相关的宏定义、变量以及函数声明,用于读取传感器的数据

#define LIS3DH_I2C_ADDR    (LIS3DH_I2C_ADD_H & 0xFEU)  
static stmdev_ctx_t lis3dh_ctx;  

uint8_t whoami = 0;  
int16_t acc_raw[3];  
float_t acc_mg[3];  
float_t acc_g[3];  
float_t pitch_deg;  
float_t roll_deg;  

static int32_t platform_write(void *handle, uint8_t reg, const uint8_t *buf, uint16_t len);  
static int32_t platform_read(void *handle, uint8_t reg, uint8_t *buf, uint16_t len);  
static void platform_delay(uint32_t millisec);

传感器读懂的写数据的的回调函数定义如下

 /** 
   * @brief  I2C 写回调(适配 STM32C5 的 HAL_I2C_MASTER_MemWrite) 
   */  
 static int32_t platform_write(void *handle, uint8_t reg, const uint8_t *buf, uint16_t len)  
 {  
     hal_i2c_handle_t *hi2c = (hal_i2c_handle_t *)handle;  
     reg |= 0x80;   /* LIS3DH auto-increment 标志,多字节写使能 */  

     if (HAL_I2C_MASTER_MemWrite(hi2c, LIS3DH_I2C_ADDR, reg,  
                                 HAL_I2C_MEM_ADDR_8BIT, (uint8_t *)buf, len, 1000) != HAL_OK)  
     {  
         return -1;  
     }  

     return 0;  
 }

传感器驱动的读数据的回调函数实现如下

 /** 
   * @brief  I2C 读回调(适配 STM32C5 的 HAL_I2C_MASTER_MemRead) 
   */  
 static int32_t platform_read(void *handle, uint8_t reg, uint8_t *buf, uint16_t len)  
 {  
     hal_i2c_handle_t *hi2c = (hal_i2c_handle_t *)handle;  
   hal_status_t status;  
     reg |= 0x80;   /* 多字节读使能自动递增(读 6 字节加速度必须) */  

   status = HAL_I2C_MASTER_MemRead(hi2c, LIS3DH_I2C_ADDR, reg,  
                    HAL_I2C_MEM_ADDR_8BIT, buf, len, 1000);  
   if (status != HAL_OK)  
     {  
      printf("LIS3DH I2C read error: status=0x%08lX, error=0x%08lX, addr=0x%02X, reg=0x%02X\r\n",  
        (unsigned long)status, (unsigned long)hi2c->last_error_codes,  
          (unsigned int)LIS3DH_I2C_ADDR, (unsigned int)reg);  
         return -1;  
     }  

     return 0;  
 }

传感器驱动的延时回调函数如下

 /** 
   * @brief  延时回调 
   */  
 static void platform_delay(uint32_t millisec)  
 {  
     HAL_Delay(millisec);  
 }

main函数中注册上述回调函数到传感器的驱动接口中,通过获取传感器的ID验证通讯正常,配置传感器工作在±2g,100Hz的配置下。

    /* 填充驱动上下文,handle 直接指向 I2C1 */  
    lis3dh_ctx.write_reg = platform_write;  
    lis3dh_ctx.read_reg  = platform_read;  
    lis3dh_ctx.mdelay    = platform_delay;  
    lis3dh_ctx.handle    = mx_i2c1_i2c_gethandle();  /* 或 &hi2c1 */  

    /* 读取 WHO_AM_I,验证 I2C 通信 */  
    if (lis3dh_device_id_get(&lis3dh_ctx, &whoami) != 0)  
    {  
      printf("LIS3DH read WHO_AM_I failed!\r\n");  
      while (1);  
    }  

    printf("LIS3DH WHO_AM_I = 0x%02X\r\n", whoami);  
    if (whoami != LIS3DH_ID)  
    {  
      printf("LIS3DH ID mismatch!\r\n");  
      while (1);  
    }  

    /* 配置 LIS3DH */  
    lis3dh_block_data_update_set(&lis3dh_ctx, PROPERTY_ENABLE); /* BDU */  
    lis3dh_full_scale_set(&lis3dh_ctx, LIS3DH_2g);              /* ±2g */  
    lis3dh_data_rate_set(&lis3dh_ctx, LIS3DH_ODR_100Hz);        /* 100Hz */  
    if (lis3dh_operating_mode_set(&lis3dh_ctx, LIS3DH_HR_12bit) != 0)  
    {  
      printf("LIS3DH high-resolution mode configuration failed!\r\n");  
      while (1);  
    }  

    printf("LIS3DH initialized OK!\r\n");

main函数的主循环中添加以下代码实现循环读取传感器数据的功能。

        if (lis3dh_acceleration_raw_get(&lis3dh_ctx, acc_raw) == 0)  
        {  
          /* 配置为高分辨率(HR_12bit)模式,±2g 用 hr 换算 */  
          acc_mg[0] = lis3dh_from_fs2_hr_to_mg(acc_raw[0]);  
          acc_mg[1] = lis3dh_from_fs2_hr_to_mg(acc_raw[1]);  
          acc_mg[2] = lis3dh_from_fs2_hr_to_mg(acc_raw[2]);  

              acc_g[0] = acc_mg[0] / 1000.0f;  
              acc_g[1] = acc_mg[1] / 1000.0f;  
              acc_g[2] = acc_mg[2] / 1000.0f;  
              roll_deg = atan2f(acc_mg[1], acc_mg[2]) * 57.3f;  
              pitch_deg = atan2f(-acc_mg[0],  
                  sqrtf(acc_mg[1] * acc_mg[1] + acc_mg[2] * acc_mg[2])) * 57.3f;  

              printf("x=%.3f y=%.3f z=%.3f | pitch=%.2f roll=%.2f\r\n",  
                (double)acc_g[0], (double)acc_g[1], (double)acc_g[2],  
                (double)pitch_deg, (double)roll_deg);  
        }  
        else  
        {  
          printf("Read LIS3DH data failed!\r\n");  
        }  

        HAL_Delay(100);

编译并烧录程序到开发板,连接开发板到串口,获取到传感器数据如下

Sensor_Output.png





关键词: Let do 3         

共1条 1/1 1 跳转至页

回复

匿名不能发帖!请先 [ 登陆 注册 ]