提交完整工程

This commit is contained in:
2026-02-05 13:22:38 +08:00
commit 729514af5d
1033 changed files with 626323 additions and 0 deletions

View File

@@ -0,0 +1,210 @@
/**
* ==================================================
* @file imu_lis3dhtr.c
* @brief TODO 描述该文件的功能
* @author wangb
* @date 2026-01-27 12:21
* @version 1.0
*
* @details 本文件包含...
*
* @copyright Copyright (c) 2026 wangb. All Rights Reserved.
*
* @license 不开源
* ==================================================
*/
#include "mems_lis3dhtr.h"
#include "cmsis_os2.h"
#include "elog.h"
#include "i2c.h"
volatile uint8_t lis3dh_int_flag = 0;
static uint8_t last_int_src = 0; // 记录上一次中断源
/* ================= 内部 I2C 读写 ================= */
void lis3dh_read(uint8_t reg, uint8_t *data, uint16_t len)
{
/* 多字节读必须置位 bit7 */
if (len > 1)
reg |= 0x80;
HAL_I2C_Mem_Read(&hi2c1,
LIS3DHTR_I2C_ADDR,
reg,
I2C_MEMADD_SIZE_8BIT,
data,
len,
1000);
}
void lis3dh_write(uint8_t reg, uint8_t data)
{
HAL_I2C_Mem_Write(&hi2c1,
LIS3DHTR_I2C_ADDR,
reg,
I2C_MEMADD_SIZE_8BIT,
&data,
1,
1000);
}
/* ================= 清除所有中断标志 ================= */
void lis3dh_clear_all_int_flags(void) {
uint8_t dummy;
// 读取INT1_SRC清除中断锁存关键
lis3dh_read(LIS3DH_REG_INT1_SRC, &dummy, 1);
// 读取状态寄存器确保数据就绪标志清除
lis3dh_read(LIS3DH_REG_STATUS, &dummy, 1);
// 读取REFERENCE寄存器重置高通滤波器
lis3dh_read(LIS3DH_REG_REFERENCE, &dummy, 1);
last_int_src = 0;
}
/* ================= LIS3DH 中断初始化 ================= */
static void lis3dh_int1_fall_init(void) {
uint8_t val;
/* 第一步:禁用所有中断并清除标志 */
lis3dh_write(LIS3DH_REG_CTRL3, 0x00);
lis3dh_write(LIS3DH_REG_INT1_CFG, 0x00);
osDelay(10);
/* 第二步:清除所有可能的中断标志 */
lis3dh_clear_all_int_flags();
osDelay(10);
/* 第三步配置CTRL2 - 高通滤波器 */
// 0x11 = 100Hz截止频率HP使能
lis3dh_write(LIS3DH_REG_CTRL2, 0x11);
/* 第四步配置CTRL3 - INT1引脚输出AOI1中断 */
val = 0x40; // I1_AOI1 = 1
lis3dh_write(LIS3DH_REG_CTRL3, val);
/* 第五步INT1_CFG - 配置检测逻辑 */
// 0x2A = 0010 1010只检测Z轴高阈值和低阈值
// 0x3F = 0011 1111检测所有轴根据你的日志0x25/0x65包含多个轴
val = 0x2A; // 先用Z轴测试
lis3dh_write(LIS3DH_REG_INT1_CFG, val);
/* 第六步INT1_THS - 阈值设置 */
val = 15; // 15 * 16mg = 240mg ≈ 0.24g(自由落体阈值)
lis3dh_write(LIS3DH_REG_INT1_THS, val);
/* 第七步INT1_DUR - 持续时间(去抖动) */
val = 2; // 2 * 1/ODR = 20ms @ 100Hz
lis3dh_write(LIS3DH_REG_INT1_DUR, val);
/* 第八步配置CTRL5 - 锁存中断 */
// 0x0A = 0000 1010LIR_INT1=1锁存INT1高阈值使能
lis3dh_write(LIS3DH_REG_CTRL5, 0x0A);
/* 第九步:再次清除所有标志 */
lis3dh_clear_all_int_flags();
elog_info("MEMS", "INT1 fall detect configured (Latch Mode)");
}
/* ================= LIS3DH 初始化 ================= */
uint8_t imu_lis3dhtr_init(void) {
uint8_t whoami = 0;
lis3dh_read(LIS3DH_REG_WHOAMI, &whoami, 1);
elog_info("MEMS", "LIS3DHTR WHO_AM_I = 0x%02X", whoami);
if (whoami != 0x33)
return 0;
/* CTRL_REG1: 100Hz ODR, XYZ 使能 */
lis3dh_write(LIS3DH_REG_CTRL1, 0x57);
/* CTRL_REG4: BDU=1, HR=1, FS=±2g */
lis3dh_write(LIS3DH_REG_CTRL4, 0xA0);
/* 初始化 INT1 跌落检测 */
lis3dh_int1_fall_init();
/* 读回验证 */
uint8_t c1, c2, c3, c4, c5, cfg;
lis3dh_read(LIS3DH_REG_CTRL1, &c1, 1);
lis3dh_read(LIS3DH_REG_CTRL2, &c2, 1);
lis3dh_read(LIS3DH_REG_CTRL3, &c3, 1);
lis3dh_read(LIS3DH_REG_CTRL4, &c4, 1);
lis3dh_read(LIS3DH_REG_CTRL5, &c5, 1);
lis3dh_read(LIS3DH_REG_INT1_CFG, &cfg, 1);
elog_info("MEMS", "CTRL1=0x%02X CTRL2=0x%02X CTRL3=0x%02X", c1, c2, c3);
elog_info("MEMS", "CTRL4=0x%02X CTRL5=0x%02X INT1_CFG=0x%02X", c4, c5, cfg);
return 1;
}
/* ================= 读取加速度 ================= */
uint8_t imu_lis3dhtr_read_accel(lis3dh_accel_t *accel)
{
uint8_t status;
lis3dh_read(LIS3DH_REG_STATUS, &status, 1);
if ((status & 0x08) == 0)
return 0; // 新数据未准备好
uint8_t buf[6];
lis3dh_read(LIS3DH_REG_OUT_X_L, buf, 6);
int16_t raw_x = ((int16_t)buf[1] << 8 | buf[0]) >> 4;
int16_t raw_y = ((int16_t)buf[3] << 8 | buf[2]) >> 4;
int16_t raw_z = ((int16_t)buf[5] << 8 | buf[4]) >> 4;
accel->x_g = raw_x * 0.001f; // ±2g HR模式1LSB≈1mg
accel->y_g = raw_y * 0.001f;
accel->z_g = raw_z * 0.001f;
return 1;
}
/* ================= 外部中断回调 ================= */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if (GPIO_Pin == lis3dhtr_Pin) {
uint8_t src;
// 1. 读取中断源(这会清除锁存中断)
lis3dh_read(LIS3DH_REG_INT1_SRC, &src, 1);
// 2. 有效性检查:源寄存器必须有中断标志
if (src == 0x00) {
// 可能是假中断,额外操作确保清除
uint8_t dummy;
lis3dh_read(LIS3DH_REG_INT1_SRC, &dummy, 1);
return;
}
// 3. 去重:避免相同中断源连续触发
if (src == last_int_src) {
// 相同中断,可能是未及时处理,强制清除
elog_debug("MEMS", "Duplicate INT1 SRC = 0x%02X", src);
return;
}
// 4. 记录并处理
last_int_src = src;
elog_warn("MEMS", "INT1 SRC = 0x%02X", src);
// 5. 解析中断类型(用于调试和高级处理)
if (src & 0x40) elog_debug("MEMS", "Z high triggered");
if (src & 0x20) elog_debug("MEMS", "Z low triggered");
if (src & 0x10) elog_debug("MEMS", "Y high triggered");
if (src & 0x08) elog_debug("MEMS", "Y low triggered");
if (src & 0x04) elog_debug("MEMS", "X high triggered");
if (src & 0x02) elog_debug("MEMS", "X low triggered");
// 6. 设置处理标志
lis3dh_int_flag = 1;
}
}