基于 STM32F103C8 的全局定位模块控制工程。主控通过两路编码器和 IMU 获取运动状态,计算底盘平面位置与航向角,并通过串口向外部控制器发送定位反馈数据。
| 路径 | 说明 |
|---|---|
code/ |
STM32CubeMX 工程、应用代码、HAL 驱动和 Keil MDK 工程 |
code/MDK-ARM/ops9.uvprojx |
Keil uVision 主工程 |
pcb/OPS9.epro |
主板 PCB 工程 |
model/ |
机械总装配模型、STL 文件和打印示例 |
example/ |
样例底盘的 STM32、PCB、模型与 HMI 工程 |
全局定位模块材料清单.xlsx |
主模块物料清单 |
- MCU:STM32F103C8,外部晶振经 PLL 配置为 72 MHz。
- 两路编码器:TIM1 / PA8、TIM2 / PA0,用于读取两侧轮速和累计脉冲。
- IMU:USART1,115200 bps,PB6 为 TX、PB7 为 RX;使用 DMA 空闲接收。
- 外部通信:USART2,115200 bps,PA2 为 TX、PA3 为 RX;使用中断收发。
- I2C:I2C1,PB8 为 SCL、PB9 为 SDA。
- 状态指示灯:PC13。
- 读取两路编码器脉冲,计算角速度、轮速和累计里程。
- 接收 IMU 偏航角,处理跨越
-PI/PI的航向累计。 - 根据当前行进方向将轮速积分为平面位置
x、y和航向z。 - 周期性通过 USART2 上报定位数据;发送帧以
0x5C开头,包含x、y、z和 CRC8。 - 接收外部控制命令;收到
0x22时会复位 MCU。
- 安装 Keil MDK-ARM,并添加 STM32F1 设备包。
- 使用 Keil uVision 打开
code/MDK-ARM/ops9.uvprojx。 - 按实际硬件确认
code/ops9.ioc中的时钟、引脚和串口配置;如使用 STM32CubeMX 重新生成代码,需保留各文件的USER CODE区域。 - 在 Keil 中选择
ops9目标,执行 Build。 - 使用 ST-Link 或兼容 SWD 调试器下载生成的固件。
当前工程的 USART1 和 USART2 都按全双工异步串口配置。若硬件改为单线、RS-485 无自动方向控制,或让一条线在收发之间切换,则属于半双工通信,必须重新设计串口收发流程。
高风险:半双工场景下,在发送未完成时重新启动接收,或在接收回调中直接发起发送,可能使 HAL 的
gState/RxState长期保持HAL_UART_STATE_BUSY_*。后续HAL_UART_Transmit_*或HAL_UART_Receive_*会持续返回HAL_BUSY,表现为串口“锁死”。
- 同一 UART 同一时刻只允许一个收发事务。发送前检查状态或维护独立的软件状态机;不要像当前
Robot_com_send_data()一样无条件高频调用HAL_UART_Transmit_IT()后又假定已经发送成功。 - 半双工方向应由明确的状态机控制:停止接收 -> 切换为发送方向 -> 启动发送 -> 在
HAL_UART_TxCpltCallback()中确认发送完成 -> 切换为接收方向 -> 重新启动接收。 - 不要在
HAL_UART_RxCpltCallback()、HAL_UARTEx_RxEventCallback()等中断回调中使用阻塞式HAL_UART_Transmit()、延时函数或复杂业务逻辑。回调只记录事件、复制数据或投递标志,实际发送放到主循环或任务中处理。 - 必须检查每次 HAL 串口调用的返回值。发生
HAL_BUSY、超时、帧错误、噪声错误或溢出错误时,先停止当前事务并清理错误标志,再按统一的恢复流程重新初始化或重新启动接收。 - 若使用 RS-485 收发器,DE/RE 的时序应覆盖整个发送过程,并以发送完成回调为准释放总线;不能仅依据写入发送寄存器就立即切换方向。
- DMA 接收缓冲区在重新启动
HAL_UARTEx_ReceiveToIdle_DMA()前不得被其他上下文修改。正常模式 DMA 完成或空闲事件后,应只重新启动一次,避免中断和主循环并发重复启动。 - 为串口事务设置合理超时和错误计数;连续异常时执行受控恢复。恢复失败后再由看门狗或上层策略复位,避免在中断中无限重试。
推荐的半双工流程如下:
空闲/接收 -> 收到完整请求 -> 停止接收并切换 TX 方向
-> 启动发送 -> Tx 完成回调 -> 切换 RX 方向 -> 重启接收
- 修改 STM32CubeMX 自动生成文件时,仅在
USER CODE BEGIN/USER CODE END区域编写用户代码。 - 业务状态、通信参数较多时使用结构体集中管理,避免分散的大量全局变量。
- 新增嵌入式函数时为函数参数补充简洁的中文注释,并保持中断服务函数短小、可预测。
- 提交前应至少验证:编码器方向、IMU 航向零点、串口帧格式、CRC8 校验和异常恢复流程。