当前位置: 首页 > news >正文

【STM32实战—TOF激光测距】第二篇、I2C协议驱动TOF10120实现精准距离采集与滤波

1. TOF10120激光测距模块基础解析

第一次接触TOF10120这个激光测距模块时,我被它的小巧体积和180cm的测量范围惊艳到了。这个模块特别适合用在智能小车避障或者家居智能设备上,实测在10cm到180cm范围内误差可以控制在±1cm以内。模块支持3.3V和5V供电,我用STM32的3.3V直接供电完全没问题,连续工作几小时也不会发烫。

模块背面有6个引脚,实际使用中我们只需要关注4个:VCC(红)、GND(黑)、SCL(绿)、SDA(蓝)。这里有个小细节要注意——模块支持I2C和串口两种通信方式,但实测I2C方式更稳定,特别是当你的STM32串口资源紧张时。我刚开始调试时犯了个错误,把TXD和RXD也接上了,后来发现根本用不到,白白浪费了两个IO口。

2. I2C硬件连接与初始化

2.1 硬件接线方案

我用的是STM32F103C8T6最小系统板,选择PB12和PB13作为I2C引脚。接线时有个坑要注意:模块的I2C是3.3V电平的,如果你用的开发板是5V电平,记得要加电平转换电路。我的接法是这样的:

  • 模块VCC → 3.3V
  • 模块GND → GND
  • 模块SCL → PB12
  • 模块SDA → PB13

这里有个实用技巧:在SDA和SCL线上各加一个4.7kΩ的上拉电阻到3.3V,能显著提高通信稳定性。我刚开始没加上拉电阻,发现偶尔会通信失败,加上后就再没出过问题。

2.2 GPIO初始化代码

在tof.h中定义引脚配置:

#define I2C_SCL_PIN GPIO_Pin_12 #define I2C_SCL_PORT GPIOB #define I2C_SDA_PIN GPIO_Pin_13 #define I2C_SDA_PORT GPIOB

初始化函数这样写:

void UserI2c_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(I2C_SCL_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN; GPIO_Init(I2C_SDA_PORT, &GPIO_InitStructure); GPIO_SetBits(I2C_SCL_PORT, I2C_SCL_PIN); GPIO_SetBits(I2C_SDA_PORT, I2C_SDA_PIN); }

3. I2C通信协议实现

3.1 基础通信函数

写I2C驱动时,最关键的是时序控制。下面这个发送起始信号的函数,我调试了好久才稳定:

void UserI2c_Start(void) { USERI2C_SDA_1; delay_us(5); USERI2C_SCL_1; delay_us(5); USERI2C_SDA_0; // START条件:SCL高电平时SDA下降沿 delay_us(5); USERI2C_SCL_0; delay_us(30); }

发送一个字节的函数要注意时钟同步:

void UserI2c_Send_Byte(unsigned char txd) { unsigned char t; USERI2C_SCL_0; delay_us(5); for(t=0; t<8; t++) { if((txd & 0x80) >> 0) USERI2C_SDA_1; else USERI2C_SDA_0; txd <<= 1; delay_us(5); USERI2C_SCL_1; delay_us(5); USERI2C_SCL_0; } }

3.2 读写寄存器实现

模块的寄存器读写有固定格式。写寄存器函数:

unsigned char SensorWritenByte(unsigned char Devid, unsigned char *TXBuff, unsigned char SubAdd, unsigned char Size) { unsigned char i = 0; UserI2c_Start(); UserI2c_Send_Byte(Devid | 0x00); if(0 == UserI2c_Wait_Ack()) { UserI2c_Stop(); return 0; } UserI2c_Send_Byte(SubAdd & 0xff); if(0 == UserI2c_Wait_Ack()) { UserI2c_Stop(); return 0; } for(i=0; i<Size; i++) { UserI2c_Send_Byte(TXBuff[Size-i-1]); if(0 == UserI2c_Wait_Ack()) { UserI2c_Stop(); return 0; } } UserI2c_Stop(); return 1; }

4. 距离数据采集与滤波

4.1 实时模式与滤波模式对比

TOF10120支持两种数据模式:

  • 实时模式(0x08寄存器置1):响应快但数据跳动大
  • 滤波模式(0x08寄存器置0):数据稳定但有约100ms延迟

在main.c中这样配置:

dirt_detection_flag=0; // 0-滤波模式 1-实时模式 SensorWritenByte(devid, (unsigned char *)&dirt_detection_flag, 0x08, 1);

实测数据对比:

模式响应时间数据波动适用场景
实时<10ms±3cm高速检测
滤波~100ms±0.5cm精确测量

4.2 数据读取实现

读取滤波后的距离值(单位:mm):

SensorReadnByte(devid, (unsigned char *)&length_aveval, 0x04, 2); printf("距离:%d mm\r\n", length_aveval);

这里有个重要技巧:读取前最好加个延时,我一般用100ms间隔读取,这样数据最稳定。曾经试过10ms读取一次,发现会出现通信错误。

5. 实际应用中的问题排查

5.1 常见通信故障

调试时遇到最多的问题是I2C无响应,通常有几个原因:

  1. 电源不稳:示波器看3.3V是否有波动
  2. 上拉电阻缺失:SCL/SDA必须加4.7kΩ上拉
  3. 时序问题:用逻辑分析仪抓波形看时序是否符合标准

5.2 数据异常处理

当读到异常值(如65535)时,建议这样处理:

#define MAX_VALID_DISTANCE 1800 // 180cm if(length_aveval > MAX_VALID_DISTANCE) { // 重试读取 SensorReadnByte(devid, (unsigned char *)&length_aveval, 0x04, 2); if(length_aveval > MAX_VALID_DISTANCE) { printf("测量超限!\r\n"); length_aveval = MAX_VALID_DISTANCE; } }

6. 不同场景下的优化建议

6.1 智能小车避障

建议配置:

  • 使用滤波模式
  • 采样间隔150ms
  • 触发距离设置80cm
  • 开启模块的自动校准功能(0x0A寄存器置1)

6.2 室内定位应用

优化方案:

  • 多个模块协同工作
  • 采用中值滤波算法
  • 校准环境参数(0x0B寄存器)
  • 使用固定测量间隔(如200ms)

7. 进阶技巧与性能提升

7.1 软件滤波增强

除了硬件滤波,可以加移动平均滤波:

#define FILTER_SIZE 5 unsigned int filter_buf[FILTER_SIZE]; unsigned int filter_index = 0; unsigned int moving_average_filter(unsigned int new_val) { filter_buf[filter_index++] = new_val; if(filter_index >= FILTER_SIZE) filter_index = 0; unsigned int sum = 0; for(int i=0; i<FILTER_SIZE; i++) { sum += filter_buf[i]; } return sum / FILTER_SIZE; }

7.2 低功耗优化

通过配置0x0C寄存器可以降低功耗:

unsigned char low_power_mode = 1; // 1-低功耗模式 SensorWritenByte(devid, &low_power_mode, 0x0C, 1);

实测功耗对比:

  • 正常模式:12mA
  • 低功耗模式:6mA
  • 休眠模式:0.5mA(需通过0x0D寄存器唤醒)
http://www.jsqmd.com/news/804205/

相关文章:

  • 2026年4月评价高的日本游学中介口碑分析,日本短期游学咨询/日本留学中介/日语考级培训,日本游学机构口碑分析 - 品牌推荐师
  • 初次使用Taotoken平台从注册到完成API调用的全程指引
  • Delphi 12 出现“[FireDAC][Phys][SQLite][sqlite3]-303.Capability is not supported”的错误。
  • 淘金币自动化助手终极指南:3分钟完成淘宝日常任务
  • 在OpenClawAgent工作流中集成Taotoken实现多模型调度能力
  • 按类型搜索文件
  • AI模型镜像仓库实战指南:从Stable Diffusion到GPT的本地部署与集成
  • CTF解题复盘:我是如何一步步解开BUUCTF安洵杯那道easy misc的(附盲水印与Base全家桶实战)
  • MobaXterm密钥生成解决方案:零成本解锁专业版功能实现远程开发效率革命
  • 海洋塑料垃圾AI量化系统:YOLOv8多光谱鲁棒检测实战
  • 手把手教你用非root用户搞定Hadoop集群:从‘ERROR: Attempting to operate on hdfs namenode as root’说开去
  • 深度学习在系外行星探测中的应用:ExoDNN框架解析与实践
  • 弯曲波触觉反馈技术:为触摸屏注入真实按键手感的工程实践
  • 计算机视觉入门:从OpenCV到PyTorch的实践指南
  • 奇瑞的“亲儿子”实锤了!纵横品牌与奇瑞集团28年技术积淀的深度绑定 - 行业深度观察
  • STC8H8K64U单片机IAP升级实战:从官方例程到自定义协议的完整移植指南
  • 计算机视觉在智慧农业中的实战:从算法到田间部署全解析
  • Taotoken Token Plan套餐如何帮助个人开发者有效控制成本
  • 在旧版iOS设备上部署ChatGPT客户端:逆向工程与兼容性实战
  • 告别手动改包!用Fiddler的Free HTTP插件实现自动化测试(附实战配置)
  • 为OpenClaw智能体工作流配置Taotoken作为统一的模型调用后端
  • 2026年排插有哪些品牌?值得关注的实力之选 - 品牌排行榜
  • 空间计算驱动VR变革:从环境理解到裸手交互的架构演进与开发实践
  • 环境可靠性测试(SPC)的需求
  • 建模慢、更新滞后?镜像视界动态重建,设备调整模型自动同步
  • 扩散模型如何重塑建筑设计流程:从概念生成到性能优化的AI协作
  • AI赋能医院物流:基于PDCA循环的智能供应链韧性提升实践
  • 对比按量计费与Token Plan套餐,哪种方式更适合你的项目
  • Dify实战指南:从零构建大模型应用与智能体开发全流程
  • 2026苏州别墅装修公司深度测评:高端定制整装服务品牌甄选 - 品牌种草官