这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 加速度计数据串口发送接收

共1条 1/1 1 跳转至页

加速度计数据串口发送接收

菜鸟
2026-10-19 22:48:26     打赏

很荣幸能够有资格参加 Let's do 2026 年第 3 期活动。我通过主控 NUCLEO-C562RE 开发板实现 LIS3DHTR数据串口发送的项目设计。

image.png

效果预览image.png第一步:使用STM32CubeMX2来生成一个项目。image.png

LIS3DHTR传感器使用I2C总线读取。所以要开启I2C支持。此外我初始化了USART2来发送采集到的数据到上位机VOFA+。

第二步:参考论坛里面老师的操作方法,使用VS code,结合STM32Cube相关插件来对项目进行开发image.png

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stepmotor.h"
#include "lis3dh_reg.h"
#include <stdio.h>
#include <math.h>

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* LIS3DH detected by the I2C1 bus scan at 0x32/0x33 (8-bit format),
   i.e. 7-bit address 0x19 -> SA0 is tied HIGH on this module.
   The HAL I2C API takes the 8-bit form (7-bit address << 1), so clear the
   R/W bit of the ST driver constant (LIS3DH_I2C_ADD_H = 0x33 -> 0x32). */
#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);

/**
  * brief:  Retarget printf to USART2 (called by newlib _write()).
  */
int __io_putchar(int ch)
{
  hal_uart_handle_t *huart = mx_usart2_uart_gethandle();
  uint8_t data = (uint8_t)ch;

  (void)HAL_UART_Transmit(huart, &data, 1U, 100U);

  return ch;
}

/**
  * brief:  I2C write callback for the LIS3DH driver.
  */
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 |= 0x80U; /* LIS3DH auto-increment flag (needed for multi-byte transfer) */

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

  return 0;
}

/**
  * brief:  I2C read callback for the LIS3DH driver.
  */
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 |= 0x80U; /* Multi-byte read with address auto-increment (needed for 6-byte accel read) */

  status = HAL_I2C_MASTER_MemRead(hi2c, LIS3DH_I2C_ADDR, reg, HAL_I2C_MEM_ADDR_8BIT,
                                  buf, len, 1000U);
  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:  Delay callback for the LIS3DH driver.
  */
static void platform_delay(uint32_t millisec)
{
  HAL_Delay(millisec);
}


/**
  * brief:  The application entry point.
  * retval: none but we specify int to comply with C99 standard
  */
int main(void)
{
  uint8_t whoami = 0U;
  uint8_t lis3dh_ready = 0U;
  int16_t acc_raw[3];
  float acc_mg[3];
  float acc_g[3];
  float pitch_deg;
  float roll_deg;

  /** System Init: this code placed in targets folder initializes your system.
    * It calls the initialization (and sets the initial configuration) of the peripherals.
    * You can use STM32CubeMX to generate and call this code or not in this project.
    * It also contains the HAL initialization and the initial clock configuration.
    */
  if (mx_system_init() != SYSTEM_OK)
  {
    return (-1);
  }
  else
  {
    /* 初始化步进电机 */
    stepper_init();

    /* 填充 LIS3DH 驱动上下文,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();

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

      if (whoami != LIS3DH_ID)
      {
        printf("LIS3DH ID mismatch!\r\n");
      }
      else
      {
        /* 配置 LIS3DH */
        (void)lis3dh_block_data_update_set(&lis3dh_ctx, PROPERTY_ENABLE); /* BDU */
        (void)lis3dh_full_scale_set(&lis3dh_ctx, LIS3DH_2g);              /* ±2g */
        (void)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");
        }
        else
        {
          printf("LIS3DH initialized OK!\r\n");
          lis3dh_ready = 1U;
        }
      }
    }

    while (1)
    {
      if (lis3dh_ready != 0U)
      {
        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("%.3f,%.3f,%.3f,%.2f,%.2f\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(10);   /* 10ms -> ~100Hz,与 LIS3DH ODR 匹配 */
    }
  }
} /* end main */

可以让AI辅助编写驱动,自己修改主函数中的调用,然后就可以在上位机读取到三轴的加速度信息了。




共1条 1/1 1 跳转至页

回复

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