# CarA **Repository Path**: lirongman/car-a ## Basic Information - **Project Name**: CarA - **Description**: ................... - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-07-24 - **Last Updated**: 2026-08-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MSPM0-G3507 循迹小车 > **MCU**: TI MSPM0G3507 (Cortex-M0+, 80MHz, LQFP-64) > **SDK**: MSPM0 SDK 2.04.00.06 > **编译器**: TI Arm Clang 4.0.0.LTS --- ## 一、项目结构 ``` . ├── main.c/h # 主程序 + 全局变量 + TIMER_0 ISR ├── LIRONGMAN.syscfg # TI SysConfig 硬件配置 ├── README.md │ ├── App/ # 应用层 │ ├── task.c/h # 裸机任务 (LED/Key/IMU/OLED/Cmd/BT) │ ├── task_mgr.c/h # 任务管理器 — 4 个预定义任务 (菜单选择+执行) │ ├── HD.c/h # 8 GPIO 红外循迹 (PID + 增量限幅 + 差速限幅) │ ├── g8_track.c/h # 8 GPIO 循迹占位 (空壳, 预留重构) │ ├── gray_track.c/h # 4 ADC 灰度传感器循迹 │ ├── Motor.c/h # TB6612 电机驱动 (含短路制动) │ ├── Motor_pid.c/h # PID 控制器 (速度/位置/角度) │ ├── Encoder.c/h # 编码器读取 │ ├── bt_send.c/h # 蓝牙发送 (UART2, 200ms → CarB) │ ├── menu.c/h # OLED 三级菜单 (旧版, 保留) │ └── button.c/h # 多功能按键库 (保留未调用) │ ├── BSP/ # 板级支持包 │ ├── clock.c/h # SysTick + 阻塞延时 │ ├── interrupt.c/h # 中断服务 (SysTick/DMA/UART/GPIO编码器/ADC) │ └── rtc.c/h # 软件 RTC (基于 SysTick) │ ├── Drivers/ # 硬件驱动 │ ├── F32C/f32c.c/h # F32C 无刷电机驱动 (保留, 未启用) │ ├── WIT/wit.c/h # JY901S IMU (DMA-UART, 7 种角度获取方式) │ ├── Gray/gray_sensor.c/h # 8通道灰度传感器 (ADC 中断扫描, 16x 过采样) │ └── OLED/ # SSD1306 (I2C) │ ├── docs/ # 技术文档 │ ├── 环境搭建指南.md │ ├── AB协同方案.md │ ├── 测试方案.md │ ├── 直角弯方案.md │ ├── 弯道矛盾分析.md │ └── 灰度传感器测试.md │ └── Debug/ # 编译输出 (SysConfig 自动生成) ├── ti_msp_dl_config.c/h └── makefile ``` --- ## 二、功能 ### 2.1 循迹 (8 GPIO 红外) 8 路数字量 GPIO(低电平=检测到黑线),加权偏差 → PID → 差速驱动。 | 引脚 | L4 | L3 | L2 | L1 | R1 | R2 | R3 | R4 | |------|----|----|----|----|----|----|----|----| | | PA14 | PB8 | PB13 | PB18 | PB10 | PB12 | PB15 | PA15 | **权重**: L4:-0.47 / L3:-0.30 / L2:-0.24 / L1:-0.05 | R1:+0.05 / R2:+0.243 / R3:+0.30 / R4:+0.47 **PID 参数** (`init_track_pid`): | kp | ki | kd | base | max_adj | |----|----|----|------|------| | 5.4 | 0.06 | 1.7 | 10 | 8.0 | **循迹算法特性** (均在 HD.c `track_pid_calculate()`): - 全白丢线:保持上次偏差,出全白瞬间 D 项 + 积分清零 - PID 输出低通滤波 (α=0.40) - 差分增量限幅 (3.0/周期) + 差速限幅 (max 12.0) - 出弯速度渐变恢复 (40%→100%, 30 周期) - 查表法 `xunji_working()` 保留不用 **圈数检测** (`track_lap_detect`): 8 传感器中 ≥4 个检测到黑线 → 短路制动停车 + 记录用时 (`g_lap_elapsed_ms`)。 **开关**: 上电进入圈数选择模式 → KEY2 切圈数(0无限→1→2→3→4→0) → KEY1 确认。运行中 KEY1 开关循迹。 ### 2.2 循迹 (4 ADC 灰度, 备用) 地址线 PB5/PB22/PB26 选通 8 通道, PA25 ADC0 CH2 采样, 16x 过采样, 归一化后加权 PID。 **权重**: CH0~CH3 正值(偏右), CH4~CH7 负值(偏左)。 ### 2.3 PID 参数 #### 底盘 (Motor_pid.c) | PID | Kp | Ki | Kd | 积分限幅 | 输出限幅 | 用途 | |-----|----|----|----|------|------|------| | Motor1/2 Speed | 30.0 | 20.0 | — | ±600 | ±999 | 直流电机速度环 | | Motor1/2 Location | 3.4 | — | 1.0 | — | ±200 | 直流电机位置环 | | Yaw | 1.0 | — | 0.2 | ±300 | ±100 | IMU 偏航角保持 (转弯用) | `PID_calc`: 标准位置式 PID + 输出限幅。`PID_yaw_calc`: 带 ±180° 跨边界处理的角度环。 #### 各任务循迹 PID (task_mgr.h) | 任务 | kp | ki | kd | base | max_adj | 说明 | |------|----|----|----|------|------|------| | T1 循迹一圈 | 5.1 | 0.04 | 1.4 | 16.5 | 13.0 | 高速, 中途+1.5补偿 | | T2 直线 | 5.4 | 0.06 | 1.7 | 11.0 | 8.0 | 梯形速度曲线, 位置停车 | | T3 循迹一圈(低速) | 5.1 | 0.04 | 1.4 | 11.0 | 13.0 | | | T4 循迹一圈(低速2) | 5.1 | 0.04 | 1.4 | 11.0 | 13.0 | 同T3 | ### 2.4 模式标志位 | 标志 | 含义 | |------|------| | `S_PID` | 速度闭环 | | `L_PID` | 位置闭环 | | `S_L_PID` | 级联 (位置外环+速度内环) | | `AS_PID` | IMU 角度+速度保持 (含 EMA 平滑切入) | | `AP_PID` | IMU 角度位置保持 | | `HD_XJ_PID` | 8 GPIO 红外循迹 | | `GRAY_XJ_PID` | 4 ADC 灰度循迹 | ISR 中 AS_PID 有 EMA 平滑切入:以当前循迹速度为起点,`AS_SMOOTH_A=0.3` 过渡,防突变。 ### 2.5 OLED 显示 128x64 OLED, 16px 字体, I2C1 (PB2/PB3): | 行 | 内容 | |----|------| | 0 | 8 GPIO 灰度位图 (0=黑线 1=白) + Y 偏航角 | | 2 | E1/E2 编码器速度 (脉冲/20ms) | | 4 | T1/T2 左右轮速度目标 | | 6 | 上一圈用时 (mm:ss.cs) 或 RTC 时间 (HH:MM:SS) | 圈数选择界面独立:模块名 + 目标圈数 + 操作提示。 ### 2.6 IMU (WIT JY901S) UART1 (PB6/PB7), DMA CH1 RX, 33 字节缓冲区,滑动窗口解析 0x55 帧头。提供 7 种角度获取方式,当前使用 `WIT_GetUnlimitedAnglesAccumulated`(增强版多圈累计)。 ### 2.7 任务管理器 KEY2 长按进入/退出。4 个预定义任务(T1: 循迹一圈 / T2: 直线位置停车 / T3/T4: 循迹一圈低速),每个任务有独立的 PID 配置和启停/完成回调。任务启停/完成自动发送 `'r'` 到串口。 ### 2.8 按键 | 按键 | 引脚 | 功能 | |------|------|------| | KEY1 | PB21 | 选择模式: 确认圈数 / 运行中: 循迹开关 / 菜单: 确认 | | KEY2 | PB11 | 选择模式: 切换圈数0~4 / 运行中: 启停; 长按: 任务管理器 | | KEY3 | PB19 | 按下发送 `'r'` 到串口 (消抖 30ms) | ### 2.9 蓝牙发送 UART2 (PA21/PA22), 115200bps。每 200ms 发送 `a\n`(yaw 0~360°)给 CarB。 ### 2.10 软件 RTC 基于 SysTick 计时,上电 00:00:00。串口 `m r HH:MM:SS` 校时。OLED 行6 无圈数记录时显示。 ### 2.11 串口调试命令 `printf` 重定向到 UART0 TX (PA0), 命令通过 UART0 RX (PA1): ``` m d — 打印编码器速度+位置 + Yaw + 圈数 m s v1 v2 — 速度闭环 m l p1 p2 — 位置闭环 m c — 级联模式 m a yaw — IMU 角度保持 m t [kp ki kd base max] — 8 GPIO 红外 PID 循迹 m g [kp ki kd base] — 4 ADC 灰度 PID 循迹 m p p1 p2 — 开环 PWM 直驱 m e — 编码器实时流 开关 (100ms 周期) m r HH:MM:SS — RTC 校时 m x — 停止所有 PID + 短路制动 ``` --- ## 三、通信接口 | 实例 | 外设 | TX | RX | 类型 | 用途 | |------|------|----|----|------|------| | UART_WIT | UART1 | PB6 | PB7 | 推挽 | JY901S IMU (DMA RX) | | UART_DEBUG | UART0 | PA0 | PA1 | **开漏** | printf + 调试命令 | | UART_F32C | UART2 | PA21 | PA22 | 推挽 | 蓝牙发送 (CarB 协同) | | I2C_OLED | I2C1 | SDA=PB3 | SCL=PB2 | 推挽 | SSD1306 OLED | > **PA0/PA1 开漏**: 需外接 4.7kΩ 上拉电阻到 3.3V。 --- ## 四、引脚总表 ### 直流电机 (TB6612) | 信号 | 引脚 | |------|------| | AIN1/AIN2 | PA26/PA24 | | STBY | PA7 | | BIN1/BIN2 | PB9/PA27 | | PWMA/PWMB | PA12/PA13 (TIMA0, 80kHz) | PWM 最小占空比 50/999 ≈5%,防堵转啸叫。`Motor_Brake()` 短路制动 (IN1=IN2=HIGH, PWM=0)。 ### 编码器 | 信号 | 引脚 | 计数方式 | |------|------|------| | E1A/E1B | PB0/PB1 | A相上升沿 → B=0 则减, B=1 则加 | | E2C/E2D | PB4/PB16 | C相上升沿 → D=0 则加, D=1 则减 | ### 循迹 8 路红外 (低有效) | L4 | L3 | L2 | L1 | R1 | R2 | R3 | R4 | |----|----|----|----|----|----|----|----| | PA14 | PB8 | PB13 | PB18 | PB10 | PB12 | PB15 | PA15 | ### 灰度 ADC 传感器 (备用) | 信号 | 引脚 | |------|------| | ADDR0/ADDR1/ADDR2 | PB5/PB22/PB26 | | AOUT | PA25 (ADC0 CH2) | ### 按键 & LED | 功能 | 引脚 | |------|------| | KEY1 / KEY2 / KEY3 | PB21 / PB11 / PB19 | | LED | PB14 | --- ## 五、主循环流程 ``` main() ├── SYSCFG_DL_init() ├── Gray 传感器 + 循迹参数初始化 ├── SysTick / RTC / Encoder / PID / OLED / TaskMgr / WIT 初始化 ├── Motor_on() ├── 中断使能 (TIMER_0, UART_DEBUG) │ while(1) ├── Task_LED() 500ms 心跳 ├── Task_Key() 按键扫描 + KEY3 + 圈数选择 + 任务管理器按键 ├── Task_IMU_Read() IMU → pitch/roll/yaw (事件驱动, newData 触发) ├── Task_UART_Debug() 编码器实时流 (m e 开关, 100ms) ├── Task_OLED() 33ms (~30fps), 支持菜单/结果/选择界面切换 ├── Vision_TimeoutCheck() 串口帧超时复位 (500ms) ├── Task_Gray_Sensor() 灰度传感器更新 (20ms, GRAY_XJ_PID=1 时激活) ├── Task_Cmd() 串口命令处理 (m s/l/c/a/t/g/p/e/r/d/x) ├── Task_BT_Send() 蓝牙发送 yaw (200ms) ├── TaskMgr_Update() 任务管理器状态机更新 └── 事件处理 (菜单进出) 中断上下文: ├── SysTick_Handler 1ms: tick_ms++, system_time_ms++ ├── TIMER_0 ISR 20ms: 编码器更新 → 圈数检测 → 循迹PID → 角度/速度/位置环 ├── ADC0_IRQHandler 灰度传感器 8 通道扫描 (16x 过采样, ~3ms, 优先级4) ├── DMA_IRQHandler DMA CH1: WIT IMU 滑动窗口解析 (优先级2) ├── UART_DEBUG ISR UART0 RX: 调试命令接收 (支持 }/\r/\n 结尾) └── GROUP1 IRQ GPIO: 编码器脉冲计数 (M1: PB0上升沿, M2: PB4上升沿) ```