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

共2条 1/1 1 跳转至页

【let's_do|2026年第3期】加速度计

高工
2026-10-05 18:14:39     打赏

【let's do|2026年第3期】加速度计


本文介绍了 Let's Do|2026年第3期 活动,使用 NUCLEO-C562RE 开发板驱动 LIS3DH 加速度传感器并 OLED 显示的项目设计,包括硬件连接、环境搭建、工程测试等流程。


项目介绍

NUCLEO-C562RE 开发板通过 IIC 通信协议读取 LIS3DH 传感器数据的项目设计。

  • 传感器介绍、硬件连接;

  • 传感器驱动:工程创建、参数配置、IDE 导入、代码、编译运行等;

  • OLED驱动:头文件、源文件、显示测试;

  • 角度显示:关键代码、加速度数据的 OLED 显示;

lis3dh_oled_cover.jpg

LIS3DH

Grove - 三轴数字加速度计 (LIS3DHTR) 是一款低成本的三轴加速度计,属于 Grove 产品系列。

基于 LIS3DHTR 芯片,提供多种量程和接口选择。体积小巧,支持 I2C、SPI 和 ADC GPIO 接口。

这款加速度计可监测环境温度,以校正由温度引起的误差。

lis3dhtr_module.jpg


特性

  • 测量范围:±2g、±4g、±8g、±16g,多种量程选择。

  • 多种接口选项:Grove I2C 接口、SPI 接口、ADC 接口。

  • 温度可调:能够调整和校正由温度引起的误差。

  • 3/5V 电源供电。

规格


项目参数
电源供电3/5V
接口I2C/SPI/GPIO ADC
I2C 地址默认 0x19,当 SDO 引脚连接到 GND 时可更改为 0x18
ADC GPIO 电源输入0-3.3V
中断预留一个中断引脚
SPI 模式设置将 CS 引脚连接到 GND

原理图

SCH_LIS3DH.jpg


详见:LIS3DH | Seeed Studio Wiki .



传感器驱动

通过硬件 I2C 驱动 LIS3DH 模块,串口打印三轴加速度与俯仰角度数据。


硬件连接

由原理图可知,将模块的 IIC 引脚与 STM32C562RET6 的 PB6 (SCL)、PB7 (SDA) 相连;

为了使用杜邦线连接开发板引脚和 LIS3DH 模块,设计 Grove 扩展板

grove_i2c_expander.jpg

详见:Grove IIC 扩展板 - 立创开源硬件平台 .

接线方式如下


STM32C562RET6LIS3DHTR
Digital Pin 15 (PB6) SCLSCL
Digital Pin 14 (PB7) SDASDA
GNDGND
3V3VCC


实物图

connect_lis3dh.jpg

工程创建

  • 打开 STM32CubeMX2 软件,从开发板新建工程;

  • 点击左侧工具栏 Open Peripherals 按钮,展开 Connectivity ,使能 USART2 并配置为异步通信;

  • 展开 System - GPIO ,将 USART2 对应引脚配置为 PA2 和 PA3,并使能全局中断;

  • 进入 Peripherials 标签页,展开 Connectivity,使能 I2C1,标准速率 100kHz,7 位地址 0x19,

  • cubemx2_i2c_hex.jpg

  • SCL 和 SDA 引脚分别配置为 PB6、PB7 均设置为上拉输出模式;

  • mx2_i2c_gpio_config.jpg

  • 保存配置,生成 CMake工程;

详见:【let's_do|2026年第3期】介绍、环境搭建、工程测试 .


导入 IDE (VSCode)

  • 打开 STM32CubeIDE 软件,依次选择 File - Import ,选择 STM32 CMake Project ,选择目标工程文件所在路径;

  • 配置工具链,选择主控芯片型号 STM32C562RETx ;

  • 待导入完成,点击工具栏 小锤子 按钮,编译工程,无报错。

在 IDE 项目中新建 LIS3DH 传感器驱动的头文件 lis3dh_reg.h 和源文件 lis3dh_reg.c 。


lis3dh_reg.h

 #ifndef LIS3DH_REGS_H
 #define LIS3DH_REGS_H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /* Includes ------------------------------------------------------------------*/
 #include <stdint.h>
 #include <stddef.h>
 #include <math.h>
 
 #ifndef DRV_BYTE_ORDER
 #ifndef __BYTE_ORDER__
 
 #define DRV_LITTLE_ENDIAN 1234
 #define DRV_BIG_ENDIAN    4321
 
 #define DRV_BYTE_ORDER    DRV_LITTLE_ENDIAN
 
 #else /* defined __BYTE_ORDER__ */
 
 #define DRV_LITTLE_ENDIAN  __ORDER_LITTLE_ENDIAN__
 #define DRV_BIG_ENDIAN     __ORDER_BIG_ENDIAN__
 #define DRV_BYTE_ORDER     __BYTE_ORDER__
 
 #endif /* __BYTE_ORDER__*/
 #endif /* DRV_BYTE_ORDER */
 
 
 /** I2C Device Address 8 bit format if SA0=0 -> 31 if SA0=1 -> 33 **/
 #define LIS3DH_I2C_ADD_L   0x31U
 #define LIS3DH_I2C_ADD_H   0x33U
 
 /** Device Identification (Who am I) **/
 #define LIS3DH_ID          0x33U
 
 typedef union
 {
   lis3dh_status_reg_aux_t status_reg_aux;
   lis3dh_ctrl_reg0_t      ctrl_reg0;
   lis3dh_temp_cfg_reg_t   temp_cfg_reg;
   lis3dh_ctrl_reg1_t      ctrl_reg1;
   lis3dh_ctrl_reg2_t      ctrl_reg2;
   lis3dh_time_limit_t     time_limit;
   lis3dh_time_latency_t   time_latency;
   lis3dh_time_window_t    time_window;
   lis3dh_act_ths_t        act_ths;
   lis3dh_act_dur_t        act_dur;
   bitwise_t                 bitwise;
   uint8_t                   byte;
 } lis3dh_reg_t;
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif /* LIS3DH_REGS_H */

保存代码。

lis3dh_reg.c

 #include "lis3dh_reg.h"
 
 int32_t lis3dh_temp_status_reg_get(const stmdev_ctx_t *ctx, uint8_t *buff)
 {
   int32_t ret;
 
   ret = lis3dh_read_reg(ctx, LIS3DH_STATUS_REG_AUX, buff, 1);
 
   return ret;
 }
 
 int32_t lis3dh_temperature_raw_get(const stmdev_ctx_t *ctx, int16_t *val)
 {
   uint8_t buff[2];
   int32_t ret;
 
   ret = lis3dh_read_reg(ctx, LIS3DH_OUT_ADC3_L, buff, 2);
 
   if (ret != 0) { return ret; }
 
   *val = (int16_t)(buff[0] | ((uint16_t)buff[1] << 8));
 
   return ret;
 }
 
 int32_t lis3dh_adc_raw_get(const stmdev_ctx_t *ctx, int16_t *val)
 {
   uint8_t buff[6];
   int32_t ret;
 
   ret = lis3dh_read_reg(ctx, LIS3DH_OUT_ADC1_L, buff, 6);
 
   if (ret != 0) { return ret; }
 
   val[0] = (int16_t)(buff[0] | ((uint16_t)buff[1] << 8));
   val[1] = (int16_t)(buff[2] | ((uint16_t)buff[3] << 8));
   val[2] = (int16_t)(buff[4] | ((uint16_t)buff[5] << 8));
 
   return ret;
 }

保存代码。

详见:STMicroelectronics/lis3dh-pid .

CMake

打开项目的 CMakeLists.txt 文件,将新增的驱动文件 lis3dh_reg.c 添加至编译路径;

 # 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
 )

保存文件。

main.c

修改 main.c 文件,添加如下代码

 #include "main.h"
 #include <stdio.h>
 #include <string.h>
 #include <math.h>
 #include "lis3dh_reg.h"
 /* Private typedef -----------------------------------------------------------*/
 /* Private define ------------------------------------------------------------*/
 #define LIS3DH_I2C_ADDR    (LIS3DH_I2C_ADD_H & 0xFEU)
 /* Private macro -------------------------------------------------------------*/
 /* Private variables ---------------------------------------------------------*/
 static stmdev_ctx_t lis3dh_ctx;
 
 /* Private functions prototype -----------------------------------------------*/
 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);
 
 int _write(int file, char *ptr, int len)
 {
     hal_uart_handle_t *huart2 = mx_usart2_uart_gethandle();
 
     if (huart2 != NULL)
     {
         HAL_UART_Transmit(huart2, ptr, len, 1000);
     }
 
     return len;
 }
 
 /**
   * @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);
 }
 
 /**
   * brief:  The application entry point.
   */
 int main(void)
 {
  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;
   /** 
   System Init
     */
   if (mx_system_init() != SYSTEM_OK)
   {
     return (-1);
   }
   else
   {
      /* 填充驱动上下文,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");
 
  /* 主循环:读取并打印 */
     while (1) {
         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);
     }
   }
 } /* end main */

保存代码,编译并上传固件。

复位开发板,运行程序;


效果

重新编译工程、点击工具栏 Run 按钮,配置调试器为 ST-LINK ,运行程序;

运行串口调试软件,配置波特率等参数,打开串口;

连续接收开发板输出的字符串;

lis3dh_print2.jpg

  • 使用绘图软件显示 X、Y、Z 三轴加速度数值,以及翻滚角度的变化

lis3dh_plot.gif

OLED 驱动

使用 OLED 显示 LIS3DH 传感器数据,包括硬件连接、工程配置、驱动代码、显示测试。


硬件连接

根据原理图,选择 PA11 和 PA12 作为 I2C2 的通信引脚。

oled_pindef.jpg

接线方式如下


STM32C562RET6OLED
PA11 (SCL)SCL
PA12 (SDA)SDA
GNDGND
3V3VCC

实物图

connect_oled_lis3dh_text.jpg

工程配置

  • 打开 STM32CubeMX2 软件,从开发板新建工程;

  • 点击左侧工具栏 Open Peripherals 按钮,展开 Connectivity ,使能 I2C2,标准速率 100kHz,7 位地址 0x3c ;

  • SCL 和 SDA 引脚分别配置为 PA11、PA12 均设置为上拉输出模式;

  • 保存配置,生成 CMake工程;

ssd1306.h

新建 OLED 驱动头文件,添加如下代码

 #ifndef __SSD1306_H
 #define __SSD1306_H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #include <stdint.h>
 
 void WriteCmd(void);
 void SSD1306_WR_CMD(uint8_t cmd);
 void SSD1306_WR_DATA(uint8_t data);
 void SSD1306_Init(void);
 void SSD1306_Clear(void);
 void SSD1306_Display_On(void);
 void SSD1306_Display_Off(void);
 void SSD1306_Set_Pos(uint8_t x, uint8_t y);
 void SSD1306_On(void);
 void SSD1306_ShowNum(uint8_t x,uint8_t y,unsigned int num,uint8_t len,uint8_t size2, uint8_t Color_Turn);
 void SSD1306_ShowDecimal(uint8_t x,uint8_t y,float num,uint8_t z_len,uint8_t f_len,uint8_t size2, uint8_t Color_Turn);
 void SSD1306_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size, uint8_t Color_Turn);
 void SSD1306_ShowString(uint8_t x,uint8_t y,const char *chr,uint8_t Char_Size, uint8_t Color_Turn);
 void SSD1306_ShowCHinese(uint8_t x,uint8_t y,uint8_t no, uint8_t Color_Turn);
 void SSD1306_DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t *  BMP,uint8_t Color_Turn);
 void SSD1306_DrawGIF(uint8_t x0, uint8_t  y0, uint8_t  x1, uint8_t y1, uint8_t  k, int m, unsigned char GIF[][m]);
 void SSD1306_HorizontalShift(uint8_t direction);
 void SSD1306_Some_HorizontalShift(uint8_t direction,uint8_t start,uint8_t end);
 void SSD1306_VerticalAndHorizontalShift(uint8_t direction);
 void SSD1306_DisplayMode(uint8_t mode);
 void SSD1306_IntensityControl(uint8_t intensity);
 void SSD1306_ClearLinePart(uint8_t line, uint8_t start, uint8_t end);
 #ifdef __cplusplus
 }
 #endif
 
 #endif /* __SSD1306_H */

保存代码。

ssd1306.c

新建 OLED 驱动源文件,添加如下代码

 #include "ssd1306.h"
 #include "main.h"
 #include "mx_i2c2.h"
 #include "oledfont.h"
 
 void WriteCmd(void)
 {
  uint8_t i = 0;
  for(i=0; i<27; i++)
  {
   HAL_I2C_MASTER_MemWrite(mx_i2c2_i2c_gethandle(), 0x78, 0x00,
                           HAL_I2C_MEM_ADDR_8BIT, CMD_Data + i, 1, 100);
  }
 }
 
 /**
  * @function: void SSD1306_WR_CMD(uint8_t cmd)
  * @description: 向设备写控制命令
  * @param {uint8_t} cmd 芯片手册规定的命令
  * @return {*}
  */
 void SSD1306_WR_CMD(uint8_t cmd)
 {
  HAL_I2C_MASTER_MemWrite(mx_i2c2_i2c_gethandle(), 0x78, 0x00,
                          HAL_I2C_MEM_ADDR_8BIT, &cmd, 1, 100);
 }
 
 /**
  * @function: void SSD1306_WR_DATA(uint8_t data)
  * @description: 向设备写控制数据
  * @param {uint8_t} data 数据
  * @return {*}
  */
 void SSD1306_WR_DATA(uint8_t data)
 {
  HAL_I2C_MASTER_MemWrite(mx_i2c2_i2c_gethandle(), 0x78, 0x40,
                          HAL_I2C_MEM_ADDR_8BIT, &data, 1, 100);
 }

具体函数定义详见:【功率监测与控制系统DIY活动过程贴】OLED显示 .

oledfont.h

新建 OLED 驱动的字体头文件,添加如下代码

 #ifndef __OLEDFONT_H
 #define __OLEDFONT_H
 
 #include <stdint.h>
 
 //8*6 ASCII字符集点阵  static const uint8_t Font6x8[][6] = {};
 const unsigned char F6x8[][6] =  
 {  
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// sp  
  0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,// !  
  0x00, 0x00, 0x07, 0x00, 0x07, 0x00,// "  
 // …… ……
  0x00, 0x44, 0x64, 0x54, 0x4C, 0x44,// z  
  0x14, 0x14, 0x14, 0x14, 0x14, 0x14,// horiz lines  
 };
 
 //16*8 ASCII字符集点阵  static const uint8_t Font8x16[][16]={};
 const unsigned char Font8x16[]=  
 {
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//sp /0  
  0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//!  /1   
 // …… ……
  0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 
  0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x00,0x00,0x01,0x00,0x00,0x01,0x01,0x00,0x00  // ~ /94
 };
 
 const unsigned char Hzk[][32]=
 {
 // 加(0) 速(1) 度(2) 计(3) 俯(4) 仰(5) 翻(6) 横(7) 滚(8) 偏(9) 航(10) 向(11) 角(12)
 
 {0x10,0x10,0x10,0xFF,0x10,0x10,0xF0,0x00,0x00,0xF8,0x08,0x08,0x08,0xF8,0x00,0x00},
 {0x80,0x40,0x30,0x0F,0x40,0x80,0x7F,0x00,0x00,0x7F,0x20,0x20,0x20,0x7F,0x00,0x00},/*"加",0*/
 
 {0x40,0x40,0x42,0xCC,0x00,0x04,0xF4,0x94,0x94,0xFF,0x94,0x94,0xF4,0x04,0x00,0x00},
 {0x00,0x40,0x20,0x1F,0x20,0x48,0x44,0x42,0x41,0x5F,0x41,0x42,0x44,0x48,0x40,0x00},/*"速",1*/
 /* (16 X 16 , 宋体 )*/
 };
 #endif

取模方式详见:【功率监测与控制系统DIY活动过程贴】OLED显示 .

字符在线取模:在线文字取模工具 .

bmp.h

新建 OLED 驱动的图片头文件,添加如下代码

 #ifndef BMP_H_
 #define BMP_H_
 
 const unsigned char BMP1[] =
 {
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 // …… ……
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 };
 
 #endif /* BMP_H_ */

保存代码。

main.c

修改主函数文件,关键代码如下

 #include "main.h"
 #include "ssd1306.h"
 #include "bmp.h"
 
 int main(void)
 {
   if (mx_system_init() != SYSTEM_OK)
   {
     return (-1);
   }
   else
   {
     /* 初始化 OLED */
     SSD1306_Init();
 
     /* 清屏并显示 */
     SSD1306_Clear();
     SSD1306_ShowString(25, 0, "OLED TEST", 16, 1);
     SSD1306_ShowString(0, 2, "6x8 Font~", 12, 0);
     SSD1306_ShowString(0, 3, "8x16 Font~", 16, 0);
     SSD1306_ShowNum(0, 5, 1234567890, 10, 16, 0);
     HAL_Delay(1000);
     /* 图片显示 */
     SSD1306_DrawBMP(0, 0, 128, 8, BMP1, 0);
     HAL_Delay(1000);
     /* 显示汉字 */
     SSD1306_Clear();
     /* 1st row */
     SSD1306_ShowString(0,0,"DIY",16,1);
     SSD1306_ShowCHinese(24,0,0,1); // 加
     SSD1306_ShowCHinese(39,0,1,1); // 速
     SSD1306_ShowCHinese(54,0,2,1); // 度
     SSD1306_ShowCHinese(69,0,3,1); // 计
     /* 2nd row */
     SSD1306_ShowString(0,2,"X:",16,0);
     SSD1306_ShowString(44,2,"Y:",16,0);
     SSD1306_ShowString(88,2,"Z:",16,0);
     /* 3rd row */
     SSD1306_ShowCHinese(0,4,4,0); // 俯
     SSD1306_ShowCHinese(15,4,5,0); // 仰
     SSD1306_ShowChar(30,4,':',16,0); // : 
     /* 4th row */
     SSD1306_ShowCHinese(0,6,6,0); // 翻
     SSD1306_ShowCHinese(15,6,8,0); // 滚
     SSD1306_ShowChar(30,6,':',16,0); // : 
     HAL_Delay(1000);
     
     while (1) {}
   }
 } /* end main */

保存代码。

效果

编译固件,运行工程;

OLED 显示文字、数字、图片等;

oled_demo.gif

角度显示

进一步通过 OLED 实现倾斜角度和加速度的实时显示。


流程图

flowchart_lis3dh_oled.jpg


硬件连接

  • 将 LIS3DH 传感器模块与开发板 I2C1 引脚对应连接;

  • 将 OLED 模块与开发板的 I2C2 引脚对应连接。

connect_oled_lis3dh.jpg

代码

修改 main.c 代码如下

 #include "main.h"
 #include "ssd1306.h"
 #include "bmp.h"
 #include <stdio.h>
 #include <string.h>
 #include <math.h>
 #include "lis3dh_reg.h"
 
 int main(void){
  if (mx_system_init() != SYSTEM_OK){
   return (-1);
  }
  else{
     /* 初始化 OLED */
     SSD1306_Init();
     /* 显示文本 */
     SSD1306_Clear();
     /* 1st row */
     /* 2nd row */
     /* 3rd row */
     /* 4th row */
 
     /* 初始化 LIS3DH */
  printf("LIS3DH initialized OK!\r\n");
 
     while (1) {
         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);
         }
         SSD1306_ClearLinePart(2, 17, 43);
        SSD1306_ClearLinePart(2, 61, 87);
         SSD1306_ClearLinePart(2, 105, 127);
        SSD1306_ShowDecimal(17,2,fabsf(acc_g[0]),1,1,16,0);
         SSD1306_ShowDecimal(61,2,fabsf(acc_g[1]),1,1,16,0);
         SSD1306_ShowDecimal(105,2,fabsf(acc_g[2]),1,1,16,0);
 
        SSD1306_ClearLinePart(4, 47, 127);
         SSD1306_ClearLinePart(5, 47, 127);
        SSD1306_ShowDecimal(45,4,pitch_deg,2,2,16,0);
        SSD1306_ClearLinePart(6, 47, 127);
         SSD1306_ClearLinePart(7, 47, 127);
        SSD1306_ShowDecimal(45,6,roll_deg,2,2,16,0);
       HAL_Delay(100);
     }
   }
 } /* end main */

保存代码。

效果

  • 重新编译固件、运行程序;

  • OLED 显示实时三轴加速度数值;

lis3dh_oled_show.gif

同时串口打印加速度及俯仰倾斜角度。

总结

本文介绍了 Let's Do|2026年第3期 活动,使用 NUCLEO-C562RE 开发板驱动 LIS3DH 加速度传感器并 OLED 显示的项目设计,包括硬件连接、环境搭建、工程测试等流程,为后续项目的研究探索提供了参考。





关键词: lis3dh     传感器     驱动     oled     stm32         

院士
2026-10-06 17:21:16     打赏
2楼

谢谢分享详细的调试介绍,学习了。


共2条 1/1 1 跳转至页

回复

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