STM32F103 驱动ADXL345三轴加速度传感器(软件I2C+OLED实时显示)
一、前言本文完整讲解基于 STM32F103C8T6 ADXL345 MEMS 三轴加速度传感器 0.96 寸 I2C OLED 的整套工程原理、硬件接线、寄存器配置、数据换算与现象分析采用软件模拟 I2C通信无需硬件 I2C 外设新手友好适合单片机课程教学、姿态检测入门实验。整套工程实现逻辑 模块姿态 / 振动 / 运动改变 → ADXL345 内部 MEMS 采集加速度 → 软件 I2C 读取三轴原始数据 → 转换为 mg 单位 → OLED 实时打印 X/Y/Z 三轴加速度数值视频讲解STM32F103 驱动ADXL345三轴加速度传感器(软件I2COLED实时显示)https://www.bilibili.com/video/BV1wjMd6EEDW/?share_sourcecopy_webvd_source91b967b41a17a5686913521545a8c3fb二、硬件接线说明2.1 器件引脚对应表ADXL345 模块引脚STM32F103 引脚功能说明SDAPA0软件 I2C 数据线SCK(SCL)PA1软件 I2C 时钟线SPI 标 SCKI2C 模式等效 SCLCS3.3V拉高切换至 I2C 通信模式SDO/ALT ADDRESSGNDI2C 从机地址 0x53VCC3.3V传感器供电严禁直连 5V无稳压模块仅支持 2~3.6VGNDGND单片机与传感器共地通信稳定前提OLED 屏幕引脚STM32F103 引脚功能说明SCLPB8OLED 软件 I2C 时钟SDAPB9OLED 软件 I2C 数据VCC3.3V屏幕供电GNDGND共地2.2 关键引脚补充说明CS 引脚拉高时 ADXL345 工作在 I2C 模式若拉低则切换 SPI 通信本工程全程使用 I2C必须接 3.3V。SDO 地址选择引脚接地7 位 I2C 地址0x53写地址0xA6读地址0xA7本工程使用接 3.3V7 位地址变为0x1D代码需要同步修改否则读不到数据I2C 上拉电阻I2C 为开漏总线标准需要 4.7kΩ 上拉至 3.3V市面上成品 ADXL345 模块大多自带板载上拉电阻若出现数据乱跳、通信失败自行增加上拉电阻排查。供电要求芯片额定电压 2.0~3.6V只有自带稳压、电平转换的 5V 兼容模块才能接 5V教学实验统一推荐 3.3V 供电避免烧坏传感器。三、ADXL345 核心工作原理ADXL345 是数字输出 MEMS 三轴加速度传感器核心是芯片内部微型机械质量块结构。3.1 信号转换流程姿态 / 晃动 / 振动 → 惯性使内部质量块产生微小位移 → 两侧差分电容容量发生变化 → 内部电路放大、滤波、ADC 模数转换 → 输出 X/Y/Z 三轴数字加速度值可检测两种加速度静态加速度重力传感器静止时仅受重力用于判断倾斜角度、设备姿态动态加速度晃动、撞击、运动产生可做振动检测、敲击识别。重点知识点传感器只采集加速度无法直接获取位移、速度仅单次读数不能推算移动距离。3.2 静止时数值规律地球恒定存在 1g 重力加速度1000mg设备平放静止时Z 轴垂直地面Z≈±1000mgX、Y 平行地面X、Y≈0mg 翻转传感器后坐标轴正负号反转任意倾斜状态下三轴矢量合加速度约等于 1000mg。自由落体特殊现象完全失重状态下 X/Y/Z 三轴读数全部趋近 0mg。四、软件 I2C 通信与三轴数据读取逻辑本工程不使用 STM32 硬件 I2C 外设将 PA0、PA1 配置为开漏输出通过翻转 GPIO 电平模拟标准 I2C 时序。4.1 I2C 基础通信时序单次寄存器读写完整流程 起始信号 → 从机地址 读写位 → 寄存器地址 → 读写数据 → 停止信号起始SCL 高电平SDA 由高拉低应答 ACK每传输 8bit 数据从机拉低 SDA 产生第 9 位应答停止SCL 高电平SDA 由低拉高寄存器读操作先发写指令指定寄存器重复起始信号后切换读模式接收数据。4.2 连续读取 6 字节数据原因ADXL345 三轴数据寄存器地址连续排布从0x32开始依次存储 X 低、X 高、Y 低、Y 高、Z 低、Z 高寄存器地址寄存器名存储内容0x32DATAX0X 轴低字节0x33DATAX1X 轴高字节0x34DATAY0Y 轴低字节0x35DATAY1Y 轴高字节0x36DATAZ0Z 轴低字节0x37DATAZ1Z 轴高字节一次性连续读取 6 字节保证 X/Y/Z 三轴数据来自同一采样周期分开单轴读取会存在采样时间差姿态数据失真。4.3 16 位有符号原始值合成规则数据存储格式低字节在前高字节在后采用二进制补码存储正负加速度C 语言处理代码s16 x (s16)((X高字节 8) | X低字节); s16 y (s16)((Y高字节 8) | Y低字节); s16 z (s16)((Z高字节 8) | Z低字节);五、寄存器初始化配置与单位换算5.1 关键寄存器配置表上电初始化严格按照下表配置开启测量模式后才能读取有效加速度寄存器名地址写入值功能作用DEVID0x00只读校验传感器 ID正确值 0xE5通信故障识别依据POWER_CTL0x2D0x00配置参数前进入待机模式DATA_FORMAT0x310x0B开启全分辨率量程 ±16gBW_RATE0x2C0x0A正常功耗传感器输出速率 100HzOFSX/OFSY/OFSZ0x1E~0x200x00三轴硬件偏移寄存器默认不校准INT_ENABLE0x2E0x00关闭所有中断采用轮询读取数据FIFO_CTL0x380x00不使用 FIFO 缓存POWER_CTL0x2D0x08MEASURE 位置 1传感器启动测量5.2 原始值转 mg 单位计算工程配置 ±16g 全分辨率模式分辨率参数1 LSB 3.9mg换算公式加速度(mg) 原始采样值 × 3.9单片机避免浮点运算使用整数等效计算int mg raw_value * 39 / 10;单位说明文中 mg 代表毫重力加速度和质量单位毫克无关换算关系1000mg 1g ≈ 9.8m/s²换算示例原始采样值计算后 mg 数值等效重力00mg0g128499mg0.5g256998mg1g-256-998mg-1g5.3 主程序整体运行流程系统延时初始化 OLED 屏幕初始化初始化 PA0/PA1 软件 I2C读取 DEVID 寄存器校验 IDID≠0xE5OLED 打印 Sensor error1s 后重新检测ID0xE5正常进入采样流程连续读取 6 字节三轴原始数据拼接 16 位有符号原始值换算 mgOLED 刷新三轴加速度数据延时 200ms循环采样。补充传感器内部数据刷新 100Hz10ms 更新一次程序 200ms 刷新屏幕显示速度满足实验观察需求。main.c代码/* * ADXL345 three-axis acceleration teaching demo * ADXL345 SDA - PA0, SCK/SCL - PA1 * OLED SCL - PB8, SDA - PB9 */ #include delay.h #include sys.h #include oled.h #include ADXL345.h #define ADXL345_REFRESH_MS 200U static void ADXL345_ShowData(const ADXL345_DataTypeDef *data); static void ADXL345_ShowError(u8 device_id); static void OLED_ShowSignedNum(u8 x, u8 y, s32 value, u8 digits, u8 size); static void OLED_ShowHexByte(u8 x, u8 y, u8 value, u8 size); int main(void) { ADXL345_DataTypeDef sensor_data; u8 sensor_ok; delay_init(); NVIC_Configuration(); OLED_Init(); OLED_ColorTurn(0); OLED_DisplayTurn(0); OLED_Clear(); OLED_ShowString(36, 0, (u8 *)ADXL345, 16); OLED_ShowString(16, 22, (u8 *)SDA PA0 SCK PA1, 12); OLED_ShowString(25, 42, (u8 *)Initializing, 12); OLED_Refresh(); sensor_ok ADXL345_Init(); while(1) { if((sensor_ok ! 0U) (ADXL345_ReadAcceleration(sensor_data) ! 0U)) { ADXL345_ShowData(sensor_data); delay_ms(ADXL345_REFRESH_MS); } else { ADXL345_ShowError(ADXL345_ReadDeviceID()); delay_ms(1000); sensor_ok ADXL345_Init(); } } } static void ADXL345_ShowData(const ADXL345_DataTypeDef *data) { OLED_Clear(); OLED_ShowString(16, 0, (u8 *)ADXL345 /-16g, 12); OLED_ShowString(0, 16, (u8 *)X:, 12); OLED_ShowSignedNum(18, 16, ADXL345_RawToMilliG(data-x), 5U, 12); OLED_ShowString(54, 16, (u8 *) mg, 12); OLED_ShowString(0, 32, (u8 *)Y:, 12); OLED_ShowSignedNum(18, 32, ADXL345_RawToMilliG(data-y), 5U, 12); OLED_ShowString(54, 32, (u8 *) mg, 12); OLED_ShowString(0, 48, (u8 *)Z:, 12); OLED_ShowSignedNum(18, 48, ADXL345_RawToMilliG(data-z), 5U, 12); OLED_ShowString(54, 48, (u8 *) mg, 12); OLED_Refresh(); } static void ADXL345_ShowError(u8 device_id) { OLED_Clear(); OLED_ShowString(36, 0, (u8 *)ADXL345, 16); OLED_ShowString(22, 20, (u8 *)Sensor error, 12); OLED_ShowString(10, 36, (u8 *)SDA PA0 SCK PA1, 12); OLED_ShowString(34, 50, (u8 *)ID:0x, 12); OLED_ShowHexByte(64, 50, device_id, 12); OLED_Refresh(); } static void OLED_ShowSignedNum(u8 x, u8 y, s32 value, u8 digits, u8 size) { u32 magnitude; if(value 0) { OLED_ShowChar(x, y, -, size); magnitude (u32)(-value); } else { OLED_ShowChar(x, y, , size); magnitude (u32)value; } OLED_ShowNum((u8)(x size / 2U), y, magnitude, digits, size); } static void OLED_ShowHexByte(u8 x, u8 y, u8 value, u8 size) { u8 high; u8 low; high (u8)((value 4) 0x0FU); low (u8)(value 0x0FU); OLED_ShowChar(x, y, (high 10U) ? (u8)(0 high) : (u8)(A high - 10U), size); OLED_ShowChar((u8)(x size / 2U), y, (low 10U) ? (u8)(0 low) : (u8)(A low - 10U), size); }ADXL345.c代码#include ADXL345.h #include delay.h /* * ADXL345 软件 I2C 驱动 * * 硬件连接 * ADXL345 SDA - STM32F103C8T6 PA0 * ADXL345 SCK/SCL - STM32F103C8T6 PA1 * * PA0 和 PA1 配置成开漏输出通过软件模拟 I2C 时序。 * CS 引脚必须接 3.3V 以选择 I2C 模式ALT ADDRESS/SDO 接地时 * ADXL345 的 7 位从机地址为 0x53对应写地址 0xA6、读地址 0xA7。 */ /* I2C 从机地址最低位由读写方向自动补充。 */ #define ADXL345_I2C_ADDRESS 0x53U #define ADXL345_WRITE_ADDRESS (ADXL345_I2C_ADDRESS 1) #define ADXL345_READ_ADDRESS ((ADXL345_I2C_ADDRESS 1) | 0x01U) /* 本驱动使用的 ADXL345 寄存器地址。 */ #define ADXL345_REG_DEVID 0x00U /* 器件标识寄存器固定值为 0xE5 */ #define ADXL345_REG_OFSX 0x1EU /* X 轴零偏校准寄存器 */ #define ADXL345_REG_OFSY 0x1FU /* Y 轴零偏校准寄存器 */ #define ADXL345_REG_OFSZ 0x20U /* Z 轴零偏校准寄存器 */ #define ADXL345_REG_BW_RATE 0x2CU /* 输出数据速率和低功耗控制寄存器 */ #define ADXL345_REG_POWER_CTL 0x2DU /* 电源模式和测量模式控制寄存器 */ #define ADXL345_REG_INT_ENABLE 0x2EU /* 中断使能寄存器 */ #define ADXL345_REG_DATA_FORMAT 0x31U /* 量程、全分辨率和数据格式寄存器 */ #define ADXL345_REG_DATAX0 0x32U /* 三轴数据起始地址DATAX0DATAZ1 */ #define ADXL345_REG_FIFO_CTL 0x38U /* FIFO 工作模式控制寄存器 */ /* 软件 I2C 引脚操作开漏输出写 1 表示释放总线写 0 表示拉低总线。 */ #define ADXL345_SDA_HIGH() GPIO_SetBits(GPIOA, GPIO_Pin_0) #define ADXL345_SDA_LOW() GPIO_ResetBits(GPIOA, GPIO_Pin_0) #define ADXL345_SCL_HIGH() GPIO_SetBits(GPIOA, GPIO_Pin_1) #define ADXL345_SCL_LOW() GPIO_ResetBits(GPIOA, GPIO_Pin_1) #define ADXL345_READ_SDA() GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) /* 软件 I2C 底层函数只在本文件内部使用。 */ static void ADXL345_I2C_Delay(void); static void ADXL345_I2C_Start(void); static void ADXL345_I2C_Stop(void); static void ADXL345_I2C_SendAck(u8 send_ack); static u8 ADXL345_I2C_SendByte(u8 data); static u8 ADXL345_I2C_ReadByte(void); static void ADXL345_I2C_BusRecovery(void); /* * I2C 时序延时。 * 5us 半周期对应的总线速度低于 100kHz适合教学和杜邦线连接环境。 */ static void ADXL345_I2C_Delay(void) { delay_us(5); } /* * 产生 I2C 起始信号 * SCL 为高电平时SDA 由高电平变为低电平。 */ static void ADXL345_I2C_Start(void) { ADXL345_SDA_HIGH(); ADXL345_SCL_HIGH(); ADXL345_I2C_Delay(); ADXL345_SDA_LOW(); ADXL345_I2C_Delay(); ADXL345_SCL_LOW(); ADXL345_I2C_Delay(); } /* * 产生 I2C 停止信号 * SCL 为高电平时SDA 由低电平变为高电平。 */ static void ADXL345_I2C_Stop(void) { ADXL345_SCL_LOW(); ADXL345_SDA_LOW(); ADXL345_I2C_Delay(); ADXL345_SCL_HIGH(); ADXL345_I2C_Delay(); ADXL345_SDA_HIGH(); ADXL345_I2C_Delay(); } /* * 从最高位开始向 I2C 总线发送一个字节并读取从机应答。 * 返回值1 表示收到 ACK0 表示收到 NACK。 */ static u8 ADXL345_I2C_SendByte(u8 data) { u8 i; u8 acknowledged; /* 依次发送 D7D0每个时钟周期发送一位。 */ for(i 0U; i 8U; i) { ADXL345_SCL_LOW(); if((data 0x80U) ! 0U) ADXL345_SDA_HIGH(); else ADXL345_SDA_LOW(); ADXL345_I2C_Delay(); ADXL345_SCL_HIGH(); ADXL345_I2C_Delay(); data 1; } /* * 第 9 个时钟用于读取应答先释放 SDA再由 ADXL345 拉低 SDA。 * SDA 为低表示 ACK说明从机已经正确接收当前字节。 */ ADXL345_SCL_LOW(); ADXL345_SDA_HIGH(); ADXL345_I2C_Delay(); ADXL345_SCL_HIGH(); ADXL345_I2C_Delay(); acknowledged (ADXL345_READ_SDA() Bit_RESET) ? 1U : 0U; ADXL345_SCL_LOW(); ADXL345_I2C_Delay(); return acknowledged; } /* * 从 I2C 总线读取一个字节按 D7D0 的顺序接收。 * 本函数只负责读取 8 位数据读完后的 ACK/NACK 由调用者发送。 */ static u8 ADXL345_I2C_ReadByte(void) { u8 i; u8 data; data 0U; ADXL345_SDA_HIGH(); for(i 0U; i 8U; i) { ADXL345_SCL_LOW(); ADXL345_I2C_Delay(); ADXL345_SCL_HIGH(); ADXL345_I2C_Delay(); data 1; if(ADXL345_READ_SDA() ! Bit_RESET) data | 0x01U; } ADXL345_SCL_LOW(); ADXL345_I2C_Delay(); return data; } /* * 主机向从机发送应答位。 * send_ack 1发送 ACK表示还要继续读取后续字节 * send_ack 0发送 NACK表示当前字节是最后一个字节。 */ static void ADXL345_I2C_SendAck(u8 send_ack) { ADXL345_SCL_LOW(); if(send_ack ! 0U) ADXL345_SDA_LOW(); else ADXL345_SDA_HIGH(); ADXL345_I2C_Delay(); ADXL345_SCL_HIGH(); ADXL345_I2C_Delay(); ADXL345_SCL_LOW(); ADXL345_SDA_HIGH(); ADXL345_I2C_Delay(); } /* * I2C 总线恢复释放 SDA 后输出 9 个 SCL 脉冲再发送停止信号。 * 如果从机因上次通信被意外中断而一直占用 SDA该操作可使其退出未完成状态。 */ static void ADXL345_I2C_BusRecovery(void) { u8 i; ADXL345_SDA_HIGH(); for(i 0U; i 9U; i) { ADXL345_SCL_LOW(); ADXL345_I2C_Delay(); ADXL345_SCL_HIGH(); ADXL345_I2C_Delay(); } ADXL345_I2C_Stop(); } /* * 向 ADXL345 的指定寄存器写入一个字节。 * 通信顺序起始信号 - 写地址 - 寄存器地址 - 数据 - 停止信号。 * 任意阶段未收到 ACK 都会立即停止通信并返回 0。 */ u8 ADXL345_WriteRegister(u8 register_address, u8 data) { ADXL345_I2C_Start(); if(ADXL345_I2C_SendByte(ADXL345_WRITE_ADDRESS) 0U) { ADXL345_I2C_Stop(); return 0U; } if(ADXL345_I2C_SendByte(register_address) 0U) { ADXL345_I2C_Stop(); return 0U; } if(ADXL345_I2C_SendByte(data) 0U) { ADXL345_I2C_Stop(); return 0U; } ADXL345_I2C_Stop(); return 1U; } /* * 从指定起始寄存器连续读取多个字节。 * * 先以写方向发送寄存器地址再发送重复起始信号并切换到读方向 * 除最后一个字节外每读完一个字节都发送 ACK最后一个字节发送 NACK。 */ u8 ADXL345_ReadRegisters(u8 start_address, u8 *data, u8 length) { u8 i; if((data 0) || (length 0U)) return 0U; ADXL345_I2C_Start(); if(ADXL345_I2C_SendByte(ADXL345_WRITE_ADDRESS) 0U) { ADXL345_I2C_Stop(); return 0U; } if(ADXL345_I2C_SendByte(start_address) 0U) { ADXL345_I2C_Stop(); return 0U; } ADXL345_I2C_Start(); if(ADXL345_I2C_SendByte(ADXL345_READ_ADDRESS) 0U) { ADXL345_I2C_Stop(); return 0U; } for(i 0U; i length; i) { data[i] ADXL345_I2C_ReadByte(); ADXL345_I2C_SendAck((i (u8)(length - 1U)) ? 1U : 0U); } ADXL345_I2C_Stop(); return 1U; } /* 从指定寄存器读取一个字节是连续读取接口的单字节封装。 */ u8 ADXL345_ReadRegister(u8 register_address, u8 *data) { return ADXL345_ReadRegisters(register_address, data, 1U); } /* * 读取器件标识寄存器。 * 正常连接的 ADXL345 应返回 0xE5通信失败时返回初始值 0x00。 */ u8 ADXL345_ReadDeviceID(void) { u8 device_id; device_id 0U; (void)ADXL345_ReadRegister(ADXL345_REG_DEVID, device_id); return device_id; } /* * 初始化软件 I2C 引脚和 ADXL345 工作参数。 * * 配置过程 * 1. 将 PA0、PA1 配置为 50MHz 开漏输出并恢复 I2C 总线 * 2. 读取 DEVID确认连接的器件确实是 ADXL345 * 3. 进入待机模式后配置全分辨率、±16g 和 100Hz 数据速率 * 4. 清零三轴偏移量关闭本示例未使用的中断和 FIFO * 5. 设置 MEASURE 位开始连续测量。 * * 返回值1 表示初始化成功0 表示器件标识错误或寄存器写入失败。 */ u8 ADXL345_Init(void) { GPIO_InitTypeDef gpio_init_structure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); gpio_init_structure.GPIO_Pin GPIO_Pin_0 | GPIO_Pin_1; gpio_init_structure.GPIO_Speed GPIO_Speed_50MHz; gpio_init_structure.GPIO_Mode GPIO_Mode_Out_OD; GPIO_Init(GPIOA, gpio_init_structure); ADXL345_SDA_HIGH(); ADXL345_SCL_HIGH(); delay_ms(5); ADXL345_I2C_BusRecovery(); if(ADXL345_ReadDeviceID() ! ADXL345_DEVICE_ID) return 0U; /* 修改测量参数前先进入待机模式。 */ if(ADXL345_WriteRegister(ADXL345_REG_POWER_CTL, 0x00U) 0U) return 0U; /* FULL_RES 1、Range 11选择全分辨率和 ±16g 量程。 */ if(ADXL345_WriteRegister(ADXL345_REG_DATA_FORMAT, 0x0BU) 0U) return 0U; /* LOW_POWER 0、Rate 0x0A选择正常功耗和 100Hz 输出速率。 */ if(ADXL345_WriteRegister(ADXL345_REG_BW_RATE, 0x0AU) 0U) return 0U; /* 教学演示暂不进行零偏校准三个偏移寄存器均写入 0。 */ if(ADXL345_WriteRegister(ADXL345_REG_OFSX, 0x00U) 0U) return 0U; if(ADXL345_WriteRegister(ADXL345_REG_OFSY, 0x00U) 0U) return 0U; if(ADXL345_WriteRegister(ADXL345_REG_OFSZ, 0x00U) 0U) return 0U; /* 本教学演示采用轮询读取因此关闭中断和 FIFO 功能。 */ if(ADXL345_WriteRegister(ADXL345_REG_INT_ENABLE, 0x00U) 0U) return 0U; if(ADXL345_WriteRegister(ADXL345_REG_FIFO_CTL, 0x00U) 0U) return 0U; /* POWER_CTL 的 MEASURE 位置 1退出待机并开始连续转换。 */ if(ADXL345_WriteRegister(ADXL345_REG_POWER_CTL, 0x08U) 0U) return 0U; delay_ms(10); return 1U; } /* * 一次连续读取 DATAX0DATAZ1 共 6 个寄存器。 * ADXL345 按低字节在前、高字节在后的顺序输出数据合并后转换为 s16 * 从而保留负加速度的二进制补码符号。 */ u8 ADXL345_ReadAcceleration(ADXL345_DataTypeDef *data) { u8 buffer[6]; if(data 0) return 0U; if(ADXL345_ReadRegisters(ADXL345_REG_DATAX0, buffer, 6U) 0U) return 0U; /* 每个轴由相邻的低、高两个字节组成。 */ >ADXL345.h代码#ifndef __ADXL345_H #define __ADXL345_H #include sys.h /* * ADXL345 三轴加速度传感器驱动头文件 * * 硬件连接 * ADXL345 SDA - STM32F103C8T6 PA0 * ADXL345 SCK/SCL - STM32F103C8T6 PA1 * * 注意ADXL345 的 CS 引脚需要接 3.3V才能进入 I2C 通信模式 * ALT ADDRESS/SDO 接地时器件的 7 位 I2C 地址为 0x53。 */ /* ADXL345 的固定器件标识读取 DEVID 寄存器应得到 0xE5。 */ #define ADXL345_DEVICE_ID 0xE5U /* 保存一次采样得到的 X、Y、Z 三轴原始有符号数据。 */ typedef struct { s16 x; /* X 轴原始数据 */ s16 y; /* Y 轴原始数据 */ s16 z; /* Z 轴原始数据 */ } ADXL345_DataTypeDef; /* * 初始化 GPIO 和 ADXL345。 * 配置为全分辨率、±16g、100Hz 输出数据速率并进入测量模式。 * 返回值1 表示初始化成功0 表示通信或器件检测失败。 */ u8 ADXL345_Init(void); /* 读取 DEVID 寄存器正常模块应返回 ADXL345_DEVICE_ID0xE5。 */ u8 ADXL345_ReadDeviceID(void); /* 向指定寄存器写入一个字节成功返回 1失败返回 0。 */ u8 ADXL345_WriteRegister(u8 register_address, u8 data); /* 从指定寄存器读取一个字节成功返回 1失败返回 0。 */ u8 ADXL345_ReadRegister(u8 register_address, u8 *data); /* 从 start_address 开始连续读取 length 个字节。 */ u8 ADXL345_ReadRegisters(u8 start_address, u8 *data, u8 length); /* 连续读取 X、Y、Z 三轴加速度原始数据。 */ u8 ADXL345_ReadAcceleration(ADXL345_DataTypeDef *data); /* * 将原始数据换算为 mg毫重力加速度。 * 全分辨率模式下的典型比例系数为 3.9mg/LSB1000mg 约等于 1g。 */ s32 ADXL345_RawToMilliG(s16 raw_value); #endif六、OLED 屏幕显示效果解析6.1 正常运行界面ADXL345 /-16g X:00000 mg Y:00000 mg Z:00998 mg字段释义/-16g当前传感器测量量程X/Y/Z三轴加速度正负号代表受力方向mg毫重力加速度单位。6.2 通信故障报错界面ADXL345 Sensor error SDA PA0 SCK PA1 ID:0x00出现报错排查顺序供电、共地、CS 引脚、SDO 地址引脚、SDA/SCL 接线、I2C 上拉电阻。七、量程、分辨率与实验现象分析ADXL345 支持 4 档量程±2g、±4g、±8g、±16g本工程选用 ±16g可捕捉大幅度晃动、冲击全分辨率模式下所有量程统一 3.9mg/LSB±16g 可达 13 位高精度。倾斜实验设备缓慢倾斜重力矢量在三轴重新分配一个轴数值减小另一轴增大静止状态下三轴平方和开根号≈1000mg。晃动冲击实验快速摆动、敲击传感器动态加速度叠加重力分量单轴读数会超过 ±1000mg属于正常现象非硬件损坏。自由落体实验脱手自由下落瞬间三轴读数全部接近 0mg失重检测是 ADXL345 内置功能本工程未启用中断。八、传感器误差来源与简易校准方案实际采样数值和理论值存在偏差主要误差来源零偏误差无重力分量轴存在固定几十 mg 偏移灵敏度误差1g 位置读数偏离 1000mg安装机械误差PCB 安装不水平重力分解至多轴干扰误差电源波动、长线接线、电机振动、温度漂移。简易校准步骤传感器水平静止放置多次采样取平均值降低随机抖动确定理论标准值平放 Z 轴 1000mgX/Y 为 0mg平均值减去理论值得到三轴零偏补偿值两种补偿方式软件读取后手动减法、写入 OFSX/OFSY/OFSZ 硬件偏移寄存器。拓展优化多次采样滑动平均滤波、一阶低通滤波消除数值抖动。

相关新闻

ok-ww鸣潮自动化:基于图像识别的智能游戏助手解决方案

ok-ww鸣潮自动化:基于图像识别的智能游戏助手解决方案

ok-ww鸣潮自动化:基于图像识别的智能游戏助手解决方案 【免费下载链接】ok-wuthering-waves 鸣潮 后台自动战斗 自动刷声骸 一键日常 Automation for Wuthering Waves 项目地址: https://gitcode.com/GitHub_Trending/ok/ok-wuthering-waves 在现代游戏体验中…

2026/8/4 4:27:46 阅读更多 →
Java毕业设计选题指南:SpringBoot与热门技术实践

Java毕业设计选题指南:SpringBoot与热门技术实践

1. Java方向计算机毕业设计选题指南作为一名带过上百个毕业设计的导师,我深知选题是毕业设计成功的第一步。2025-2026年的Java方向毕设,既要考虑技术新颖性,又要确保在有限时间内能够完成。以下是经过实战检验的选题策略:技术栈选…

2026/8/4 4:27:46 阅读更多 →
AI把我们银行的产品介绍错了怎么纠正?RAG纠偏完整技术方案

AI把我们银行的产品介绍错了怎么纠正?RAG纠偏完整技术方案

结论先行AI 搜索把银行产品介绍错了,核心原因通常不在模型「故意乱说」,而在 RAG 检索链路上游信源有问题——缺少正确、结构化、可交叉验证的产品字段,或被过期/错误第三方信息污染。纠偏需要同时做三件事:修正信源——把正确产品…

2026/8/4 4:27:46 阅读更多 →

最新新闻

Unity Shader Graph线性混合蒙皮节点:原理、应用与实战指南

Unity Shader Graph线性混合蒙皮节点:原理、应用与实战指南

1. 项目概述:从“皮”到“骨”的动画魔法 在实时渲染和游戏开发的世界里,让一个静态的3D模型“活”起来,流畅地做出奔跑、跳跃、攻击等动作,是每个开发者都要面对的核心挑战。这背后的关键技术之一,就是蒙皮&#xff0…

2026/8/4 9:33:36 阅读更多 →
07-Embedding是什么-通俗理解向量检索

07-Embedding是什么-通俗理解向量检索

Embedding(嵌入模型)是什么?用通俗语言理解向量检索系列:从零构建企业 RAG 知识库(第 7 篇)1. Embedding 是一种可比较的表示 Embedding 把文本映射成固定维度数值向量: "如何申请退款&quo…

2026/8/4 9:33:36 阅读更多 →
CTF竞赛工具链构建:逆向工程与电子取证实战指南

CTF竞赛工具链构建:逆向工程与电子取证实战指南

1. CTF竞赛工具全景解析:从入门到精通的技术栈构建在网络安全竞赛领域,CTF(Capture The Flag)已成为检验实战能力的黄金标准。作为参加过三十余场线下赛事的"老炮",我深刻体会到工具链的完备程度直接决定比赛…

2026/8/4 9:33:36 阅读更多 →
大模型应用开发实战:基于LangChain与Langfuse构建可观测、可评估的智能体系统

大模型应用开发实战:基于LangChain与Langfuse构建可观测、可评估的智能体系统

这次我们来看一个面向2026年大模型面试的综合性学习与评估项目。它不是一个单一的软件或模型,而是一个精心设计的、以实战为导向的知识体系与工具链集合。核心目标非常明确:帮助开发者系统性地准备大模型应用开发岗位的面试,覆盖从基础概念到…

2026/8/4 9:33:36 阅读更多 →
Pandas大文件处理:内存优化与高效读取技巧

Pandas大文件处理:内存优化与高效读取技巧

1. 问题背景与核心痛点 当我们需要用Pandas处理超过10GB的CSV文件时,经常会遇到内存不足的问题。这主要是因为Pandas默认会将整个文件加载到内存中,形成一个DataFrame对象。对于大型文件,这种操作方式会迅速耗尽可用内存,导致程序…

2026/8/4 9:33:36 阅读更多 →
5种惊艳效果!TranslucentTB让你的Windows任务栏瞬间变高级

5种惊艳效果!TranslucentTB让你的Windows任务栏瞬间变高级

5种惊艳效果!TranslucentTB让你的Windows任务栏瞬间变高级 【免费下载链接】TranslucentTB A lightweight utility that makes the Windows taskbar translucent/transparent. 项目地址: https://gitcode.com/gh_mirrors/tr/TranslucentTB 想让你的Windows桌…

2026/8/4 9:32:35 阅读更多 →

日新闻

AI Agent白手起家26: 使用标准事件驱动大模型实践

AI Agent白手起家26: 使用标准事件驱动大模型实践

纲要 练习目标:掌握大模型标准事件的调用回顾 LangChain 中的核心标准事件 invokestreambatchastream_eventswith_structured_output 环境准备实战代码:多种事件调用对比 同步调用与流式输出批量处理异步事件流监听结构化输出 运行说明与预期结果总结与扩…

2026/8/4 0:00:40 阅读更多 →
dealsea是什么?跨境卖家必知的美国deal站入门指南

dealsea是什么?跨境卖家必知的美国deal站入门指南

说实话,第一次听说美国这个老牌折扣网站的跨境卖家,十个有八个会问同一个问题:这个平台到底是干嘛的?我见过一个做家居出口的朋友,他在亚马逊上月销二十万美金,却从来没用过它。我给他看了首页——一屏一屏…

2026/8/4 0:01:40 阅读更多 →
清华大学重磅EST:植物自导电闪蒸焦耳热600°C/2600°C两步法!稀土超积累植物秒级转化为CeO₂-石墨烯电催化剂!

清华大学重磅EST:植物自导电闪蒸焦耳热600°C/2600°C两步法!稀土超积累植物秒级转化为CeO₂-石墨烯电催化剂!

通讯作者:邓兵、刘建国通讯单位:清华大学DOI:https://doi.org/10.1021/acs.est.6c00603研究背景稀土元素(REEs)是清洁能源技术与电子器件不可或缺的核心原料,然而传统提取方式依赖能耗高、排放大的采矿与强…

2026/8/4 0:01:40 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/3 4:58:13 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/3 1:53:31 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/4 5:26:40 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/3 13:07:03 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/3 5:19:38 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/3 8:27:36 阅读更多 →