三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

用STM32CubeMX和HAL库,5分钟搞定Nooploop TOFSense激光测距模块的串口通信

用STM32CubeMX和HAL库,5分钟搞定Nooploop TOFSense激光测距模块的串口通信

基于STM32CubeMX与HAL库的TOFSense激光测距快速开发指南

激光测距技术在工业自动化、机器人导航等领域应用广泛,而Nooploop的TOFSense模块凭借其高精度和小型化特点,成为许多嵌入式开发者的首选。本文将手把手带你使用STM32CubeMX和HAL库,在5分钟内搭建起与TOFSense模块的通信桥梁。

1. 硬件准备与环境搭建

在开始编码之前,我们需要确保硬件连接正确。TOFSense模块通常提供UART接口,只需将其TX、RX引脚与STM32开发板交叉连接(模块TX接开发板RX,模块RX接开发板TX),同时共地即可。供电方面,TOFSense支持3.3V-5V宽电压输入,与大多数STM32开发板兼容。

开发环境方面,你需要准备:

  • STM32CubeMX最新版本(本文基于6.6.1)
  • 支持HAL库的IDE(如Keil MDK、IAR或STM32CubeIDE)
  • 一块STM32开发板(F1/F4系列均可)

提示:初次使用TOFSense时,建议先通过USB转TTL模块连接电脑,用串口助手验证模块输出是否正常,这能快速排除硬件问题。

2. CubeMX工程配置

启动STM32CubeMX,按照以下步骤配置:

  1. 选择你的STM32型号
  2. 在"Pinout & Configuration"标签页中:
    • 启用USART(根据实际连接选择UART1/2/3等)
    • 配置为异步模式(Asynchronous)
    • 设置波特率为115200(TOFSense默认值)
  3. 在"Project Manager"标签页:
    • 设置Toolchain/IDE为你的开发环境
    • 勾选"Generate peripheral initialization as a pair of .c/.h files"

关键配置参数表:

参数项推荐值
波特率115200
数据位8 bits
停止位1 bit
校验位None
硬件流控Disable

生成代码前,务必检查引脚分配是否冲突。点击"Generate Code"按钮,CubeMX将创建完整的工程框架。

3. HAL库串口通信实现

生成的工程已经包含了UART初始化代码,我们只需实现数据收发逻辑。TOFSense支持两种工作模式:

3.1 主动查询模式

在这种模式下,STM32需要主动发送查询指令,模块才会返回数据。优点是可控性强,适合低功耗应用。

// 发送查询指令 uint8_t query_cmd[] = {0x55, 0x00, 0x00, 0x00, 0x00}; HAL_UART_Transmit(&huart1, query_cmd, sizeof(query_cmd), HAL_MAX_DELAY); // 接收数据 uint8_t rx_buffer[20]; HAL_UART_Receive(&huart1, rx_buffer, sizeof(rx_buffer), HAL_MAX_DELAY);

3.2 被动接收模式

模块自动周期上报数据,STM32只需持续监听串口。优点是实时性好,适合需要快速响应的场景。

// 开启串口接收中断 HAL_UART_Receive_IT(&huart1, rx_buffer, expected_data_length); // 在回调函数中处理数据 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == USART1) { // 解析数据 process_tof_data(rx_buffer); // 重新开启接收 HAL_UART_Receive_IT(&huart1, rx_buffer, expected_data_length); } }

4. NLink协议数据解析

TOFSense采用NLink通信协议,数据帧格式如下:

字节位置内容说明
00x55帧头
10x01设备类型(TOFSense)
2-3距离值小端格式,单位mm
4信号强度0-255,值越大越好
5校验和前面所有字节的异或值

示例解析函数:

typedef struct { uint16_t distance; uint8_t signal_strength; } TOF_Data; TOF_Data parse_tof_data(uint8_t* raw_data) { TOF_Data result; // 验证帧头 if(raw_data[0] != 0x55 || raw_data[1] != 0x01) { result.distance = 0; return result; } // 计算校验和 uint8_t checksum = 0; for(int i=0; i<5; i++) { checksum ^= raw_data[i]; } if(checksum == raw_data[5]) { // 小端格式转换 result.distance = raw_data[2] | (raw_data[3] << 8); result.signal_strength = raw_data[4]; } else { result.distance = 0; } return result; }

5. 性能优化与错误处理

在实际应用中,我们需要考虑通信的稳定性和可靠性。以下是几个实用技巧:

  • 超时处理:为所有HAL_UART函数设置合理的超时时间,避免程序卡死
  • 数据校验:除了协议规定的校验和外,可以增加帧间隔时间检查
  • 错误重试:当连续多次接收失败时,可以尝试重新初始化串口
  • 缓冲区管理:使用环形缓冲区存储接收数据,避免数据丢失
#define MAX_RETRY 3 uint8_t uart_transmit_with_retry(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) { uint8_t retry = 0; HAL_StatusTypeDef status; do { status = HAL_UART_Transmit(huart, pData, Size, 100); if(status == HAL_OK) break; retry++; HAL_Delay(10); } while(retry < MAX_RETRY); return (status == HAL_OK); }

6. 实际应用案例

将TOFSense集成到机器人避障系统中的典型流程:

  1. 初始化UART并配置TOFSense为自动上报模式
  2. 在定时中断中读取最新距离数据
  3. 实现简单的移动平均滤波,消除测量噪声
  4. 根据距离阈值触发避障动作
#define WINDOW_SIZE 5 uint16_t distance_history[WINDOW_SIZE]; uint8_t history_index = 0; uint16_t get_filtered_distance(uint16_t new_distance) { distance_history[history_index] = new_distance; history_index = (history_index + 1) % WINDOW_SIZE; uint32_t sum = 0; for(int i=0; i<WINDOW_SIZE; i++) { sum += distance_history[i]; } return (uint16_t)(sum / WINDOW_SIZE); }

在最近的一个AGV项目中,这种实现方式将测距响应时间控制在20ms以内,完全满足实时避障需求。

← 返回列表