feat: report wheel speed and GPIO state periodically

This commit is contained in:
shenlefengnai-rgb
2026-10-05 19:49:49 +08:00
parent 34627fa6a0
commit 68e8fdbcb8
7 changed files with 234 additions and 335 deletions
+13 -15
View File
@@ -11,8 +11,8 @@
1. 接收并处理串口命令。
2. 接收 CAN1、CAN2 的 DAC 控制帧。
3. 读取四路定时器捕获值并计算频率。
4. 汇总 15 路 GPIO 变化并上报。
5. 每 500 ms 上报 ADC、每 20 ms 上报四路频率。
4. 汇总 15 路 GPIO 状态与本周期变化,并每秒上报一次。
5. 每 500 ms 上报 ADC、每 20 ms 上报双路轮速。
6. 每 500 ms 翻转运行指示灯,每 100 ms 发送 CAN 心跳。
`PE0` 为正常运行心跳灯;若进入 `Error_Handler()`,`PE0` 和 `PE1` 会快速同时翻转。
@@ -22,10 +22,8 @@
| 功能 | MCU 引脚/外设 | 当前配置 |
|---|---|---|
| 15 路状态输入 | `PD0`~`PD14` | 双边沿 EXTI,状态位直接对应端口位 |
| 频率 1 | `PA0` / `TIM5_CH1` | 上升沿输入捕获,32 位计数器,16 MHz 计数时钟 |
| 频率 2 | `PA2` / `TIM9_CH1` | 上升沿输入捕获,16 位计数器,100 kHz 计数时钟 |
| 频率 3 | `PA6` / `TIM3_CH1` | 上升沿输入捕获,16 位计数器,100 kHz 计数时钟 |
| 频率 4 | `PB14` / `TIM12_CH1` | 上升沿输入捕获,16 位计数器,100 kHz 计数时钟 |
| 左前轮速 | `PA0` / `TIM5_CH1` | 上升沿输入捕获,32 位计数器,16 MHz 计数时钟 |
| 右前轮速 | `PA6` / `TIM3_CH1` | 上升沿输入捕获,16 位计数器,100 kHz 计数时钟 |
| 电压采集 | `PB0` / `ADC1_IN8` | 480 周期采样,16 次过采样 + 4 次报告均值滤波 |
| CAN1 | `PB8` RX、`PB9` TX | 标准帧,500 kbit/s |
| CAN2 | `PB5` RX、`PB6` TX | 标准帧,500 kbit/s |
@@ -38,15 +36,15 @@
## 3. 15 路状态输入
`PD0`~`PD14` 的逻辑电平组成一个 15 位无符号数:bit0 对应 `PD0`,bit14 对应 `PD14`。任何一路变化会触发 EXTI 回调,主循环中合并同一时段的变化并输出:
`PD0`~`PD14` 的逻辑电平组成一个 15 位无符号数:bit0 对应 `PD0`,bit14 对应 `PD14`。任何一路变化会触发 EXTI 回调,变化掩码会在当前 1 秒周期内累积;`0x6A6` 固定每秒发送一次:
```text
GPIO changed mask=0x0004 state=0x0005
```
- `state`:当前 15 路完整状态。
- `mask`:相对于上一次 GPIO 状态帧发生变化的位。
- 上电时也会发送一帧状态,变化掩码为 0。
- `mask`:过去 1 秒内发生过变化的位;同一路即使变化多次也只置 1。
- 上电后首个周期结束时发送第一帧;若无变化,变化掩码为 0。
每秒串口还会打印一次完整状态,例如 `GPIO state=0x0005`。
@@ -61,16 +59,16 @@ ADC 原始值 -> 3.3 V ADC 电压 -> 100 kΩ / 30 kΩ 分压反算 -> 标定系
标定系数固定为 `12300 / 11656`:即以实测输入 12.3 V、旧换算结果 11656 mV 为基准。每次报告读取 16 次 ADC 后求平均,再对最近 4 次报告做移动平均;报告周期为 500 ms,滤波窗口约 2 秒。输出示例:
```text
ADC=12300mV PWM=10,0,0,0Hz
ADC=12300mV WheelSpeed=LF:0.289m/s RF:0.577m/s
```
若硬件分压电阻或外部标定基准改变,应同步修改 `main.c` 中的 `ADC_DIVIDER_*` 和 `ADC_CALIBRATION_*` 宏。
## 5. 四路频率输入
## 5. 双路轮速输入
四路频率按 `PA0`、`PA2`、`PA6`、`PB14` 顺序输出。频率由相邻两个上升沿的计数差计算;超过 1 秒没有边沿则显示 0 Hz。当前固件只测频率,不测 PWM 占空比。
仅采集左前轮速 `PA0` 和右前轮速 `PA6`。频率由相邻两个上升沿的计数差计算;超过 1 秒没有边沿则输出 0 m/s。每圈 49 个方波、轮周长 1414 mm,因此 `轮速(m/s) = 方波频率(Hz) × 1.414 / 49`。
后三路 16 位定时器采用 100 kHz 计数时钟,以避免低频输入时 16 位溢出。其可无歧义测量的最低频率约为 1.53 Hz;TIM5 为 32 位计数器,低频范围更大。
`0x6A2` 每 20 ms 发送两个 `uint16`:左前在 Byte0–1,右前在 Byte2–3。原始值的单位为 mm/s,DBC 的物理量纲为 `0.001 m/s`;最高表示 65.535 m/s。PA6 的 TIM3 为 100 kHz、16 位计数器,低频无歧义测量下限约 1.53 Hz;PA0 的 TIM5 为 32 位计数器,低频范围更大。
## 6. CAN 通信
@@ -80,11 +78,11 @@ CAN1 和 CAN2 使用相同协议,所有主动上报均分别发送到两条总
|---:|---|---|---|
| `0x6A0` | 心跳 | 每 100 ms | `A1 01 seq_L seq_H uptime_0..3` |
| `0x6A1` | ADC 电压 | 每 500 ms | 输入电压 `uint16`,单位 mV |
| `0x6A2` | 四路频率 | 每 20 ms | 4 个 `uint16`,单位 Hz,顺序 PA0/PA2/PA6/PB14 |
| `0x6A2` | 双路轮速 | 每 20 ms | 左前 PA0、右前 PA6 各一个 `uint16`,单位 `0.001 m/s`,DLC=4 |
| `0x6A3` | DAC 设置命令 | 接收 | `[DAC 编号][mV_L][mV_H]`;每路在 100 ms 内未收到本路下一帧时归零 |
| `0x6A4` | DAC 应答 | 每次 DAC 设置后 | `[结果][DAC 编号][mV_L][mV_H]` |
| `0x6A5` | ASSI 灯控 | 接收 | `byte0`:`0=AS_OFF`、`1=AS_READY`、`2=AS_DRIVING`、`3=AS_EMERGENCY`、`4=AS_FINISHED` |
| `0x6A6` | GPIO 状态 | 上电、任一输入变化 | 状态 `uint16`、变化掩码 `uint16`、时间戳 `uint32 ms` |
| `0x6A6` | GPIO 状态 | 每 1 s | 状态 `uint16`、变化掩码 `uint16`、时间戳 `uint32 ms` |
心跳帧中板号为 `0xA1`、协议版本为 `0x01`,序号与上电时间均为低字节在前。完整信号定义和量纲以 [DBC 文件](SDC_ACQ_DAC.dbc) 为准。