mothercup/docs/数码管显示设计说明书.md
evan.liu 44172e861a 整理《数码管显示设计说明书》(仅文档)
- 新增 docs/数码管显示设计说明书.md: 汇总当日数码管联调成果
  (脚号映射/位序/Charlieplexing公式/段码表/温度解码/软件接口/CLI命令/踩坑/示例)
- docs/开发日志.md: 新增 §69
2026-09-13 10:45:16 +08:00

148 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# YF30137 数码管显示设计说明书
> 版本:V1.1(2026-09-06,融合当日数码管联调的位序修正与 GPIOA 时钟修复)
> 关联文档:`docs/YF30137_驱动真值表.md`(完整段→脚真值表)、`docs/开发日志.md` §58~§68
> 固件:`mcm-ddc-ble/src/app_display.c/h`(驱动)、`mcm-ddc-ble/src/cli_core.c`(CLI 命令)
---
## 1. 概述
数码屏为 **YF30137 七脚 Charlieplexing 温度显示模块**:7 个 IO 脚两两复用电极,点亮 5 个数字位 + 2 个指示段。驱动由独立的 FreeRTOS 任务 `display_task` 逐段扫描完成。
温度显示格式:**`[百][十][个][F/C][小数]` + `°F` + 小数点**,量程 **0.0 ~ 999.9**(1 位小数)。
---
## 2. 硬件连接(脚号 → MCU 引脚)
数码管脚 1~7(网络 `LED_1`~`LED_7`)与 MCU 引脚一一对应:
| 数码管脚 | 网络 | MCU 引脚 | | 数码管脚 | 网络 | MCU 引脚 |
|---|---|---|---|---|---|---|
| pin1 | LED_1 | **PB0** | | pin5 | LED_5 | **PB11** |
| pin2 | LED_2 | **PB1** | | pin6 | LED_6 | **PB13** |
| pin3 | LED_3 | **PA0** | | pin7 | LED_7 | **PA6** |
| pin4 | LED_4 | **PA1** | | | | |
- 7 个脚分布在 **GPIOA**(PA0/PA1/PA6)与 **GPIOB**(PB0/PB1/PB11/PB13)两个端口。
- ⚠️ **两个端口时钟都必须使能**(`RCC_APB2_PERIPH_GPIOA` / `RCC_APB2_PERIPH_GPIOB`),否则 PA0/PA1/PA6 无输出(见 §9 踩坑 1)。
---
## 3. 显示位序定义(重要:当日修正)
| 位 | 含义 | 说明 |
|---|---|---|
| **DIG1** | 百位 | 数字 0~9,前导零消隐 |
| **DIG2** | 十位 | 数字 0~9,前导零消隐 |
| **DIG3** | 个位 | 数字 0~9,恒显示 |
| **DIG4** | 单位字母 | **华氏显 `F`、摄氏显 `C`**(非数字位、非固定 F)|
| **DIG5** | 小数位(十分位) | 数字 0~9,恒显示 |
| **DIG6-A** | 华氏标志 °F | 华氏点亮、摄氏熄灭 |
| **DIG6-B** | 小数点 | 恒点亮(小数位恒显示) |
> 旧代码曾把 DIG1~5 当作 5 个全功能数字位、DIG4 当普通数字位——**已修正**。
> 注意 DIG6-A/DIG6-B 是**两个独立的单指示段**,不是逐位小数点(硬件特性)。
---
## 4. Charlieplexing 驱动原理
**段 S(A=0…G=6)在位 D(DIG1=1…DIG5=5)点亮**,由一对脚 `高→低` 驱动,其余 5 脚高阻:
```
高脚索引 h = (S + D) % 7 → 脚号 = h + 1
低脚索引 l = (D - 1) + (S + D) / 7 → 脚号 = l + 1
```
**DIG6 两个固定脚对**:
| 段 | 功能 | 点亮方式 |
|---|---|---|
| A6 | 华氏 °F | 脚7 高、脚6 低(`PA6 高 → PB13 低`)|
| B6 | 小数点 | 脚1 高、脚7 低(`PB0 高 → PA6 低`)|
**扫描要点**:逐段点亮(每段 250µs)→ 点完立即把两脚切回高阻(输入)→ 点下一段;同一数字的多段不能同时点(脚共用,否则鬼影)。一个完整扫描帧约 20ms。
---
## 5. 字符段码表(bit0=A … bit6=G)
| 字符 | 段码 | 字符 | 段码 | 字符 | 段码 |
|---|---|---|---|---|---|
| 0 | 0x3F | 1 | 0x06 | 2 | 0x5B |
| 3 | 0x4F | 4 | 0x66 | 5 | 0x6D |
| 6 | 0x7D | 7 | 0x07 | 8 | 0x7F |
| 9 | 0x6F | A | 0x77 | b | 0x7C |
| **C** | **0x39** | d | 0x5E | E | 0x79 |
| **F** | **0x71** | — | 负号 G 段 | 0x40 | |
- `F`(单位字母)= **0x71**(AEFG)、`C`(单位字母)= **0x39**(ADEF),用于 DIG4。
- 完整每个数字位的段→脚真值表见 `docs/YF30137_驱动真值表.md`(段→脚公式不变,只是位语义按 §3 修正)。
---
## 6. 温度解码(`display_decode`)
输入温度 `value`(float),输出 5 个位字符码:
1. 钳位:`value < 0 → 0`;`value > 999.9 → 999.9`;
2. `scaled = (int)(value × 10 + 0.5)`(×10 转 0.1℃ 分辨率);
3. 落位:`DIG5(小数)=scaled%10` → `DIG3(个)=(scaled/10)%10` → `DIG2(十)=(scaled/100)%10` → `DIG1(百)=(scaled/1000)%10`;
4. 前导零消隐:百位为 0 消隐,百位已消隐且十位为 0 再消隐十位;个位与小数位恒显示;
5. **DIG4 = 华氏 `0x0F`(F) / 摄氏 `0x0C`(C)**;
6. 小数点(DIG6-B)恒亮;华氏标志(DIG6-A)随华氏/摄氏开关。
> 驱动**不做 F/C 数值换算**:华氏/摄氏只切换 DIG4 字母与 DIG6-A 指示,数值原样显示(单位换算由上层完成)。
---
## 7. 软件架构与接口(`app_display.c/h`)
| 接口 | 说明 |
|---|---|
| `void display_set(float value, uint8_t type, uint8_t base)` | 设温度值 0.0~999.9;`type` 华氏/摄氏;`base` 已废弃(兼容保留)|
| `void display_set_raw(const uint8_t digits[5], uint8_t type)` | 直接写 5 个位字符码(绕过温度解码,用于 `Err`/`Lo`/`Hi` 等状态字)|
| `void display_auto_set(uint8_t on)` / `uint8_t display_auto_get(void)` | 自动扫描开关(关后 7 脚置高阻,交出手动控制)|
| `int display_pin_map(uint8_t pin_no, GPIO_Module**, uint16_t*)` | 数码管脚号 1~7 → GPIO 端口+掩码 |
| `void display_task(void*)` | 扫描任务:优先级 1、栈 256 字、20ms/帧、每段 250µs,循环喂狗 |
内部状态:`g_disp_value/g_disp_type/g_disp_base`(数值)、`g_disp_raw/g_disp_raw_digits`(裸码模式)、`g_disp_auto`(自动开关)。
---
## 8. CLI 命令(`cli_core.c`)
| 命令 | 说明 |
|---|---|
| `disp <value> [f]` | 设温度显示;`f` = 华氏(DIG4 显 F + DIG6-A 亮),默认摄氏 |
| `dispauto [on|off]` | 自动扫描开关(查询/设置)|
| `dispset <pin1-7\|all> [0\|1\|z]` | 手动驱动数码管脚:`0` 低 / `1` 高 / `z` 高阻;`all` 一键全脚 |
| `disptest` | 显示自检:0.0~9.0 → 12.3/456.7/999.9 → 36.5F/36.5C |
| `apptest` | 温度量程扫测:0.1~9.9(步0.1) → 10~99(步1) → 100~990(步10) → 999.0,摄氏+华氏各一轮 |
| `pinset <pxN> [0\|1]` | 通用 GPIO 读写(非数码管专用)|
---
## 9. 关键踩坑与修正记录(当日)
1. **GPIOA 时钟未使能 → PA0/PA1/PA6 无输出**:数码管驱动删掉 `LedInit` 后 GPIOA 时钟失去使能点(GPIOB 因 USART 仍在使能)。修复:`display_task` 开头显式使能 GPIOA+GPIOB,`dispset` 内再防御性使能一次。
2. **位序理解错误**:旧代码把 DIG1~5 当 5 个全功能数字位、DIG4 当数字位。修正:DIG4 是单位字母、DIG5 是小数位。
3. **DIG4 从"固定 F"改为"F/C"**:华氏显 F、摄氏显 C。
4. **量程**:0.0~999.9(百十个小·数共 4 位数字 + 1 位单位),非 9999.9。
5. **裸码模式**:`display_set_raw` 用于显示 0~9/A~F 之外的状态字符(如 Err),`display_set` 会清掉裸码回到数值解码。
---
## 10. 温度显示示例
| 温度 | DIG1(百) | DIG2(十) | DIG3(个) | DIG4 | DIG5(小数) | 小数点 | °F |
|---|---|---|---|---|---|---|---|
| 0.0 ℃ | (空) | (空) | 0 | C | 0 | 亮 | 灭 |
| 8.5 ℃ | (空) | (空) | 8 | C | 5 | 亮 | 灭 |
| 36.5 ℃ | (空) | 3 | 6 | C | 5 | 亮 | 灭 |
| 36.5 ℉ | (空) | 3 | 6 | **F** | 5 | 亮 | **亮** |
| 100.0 ℃ | 1 | 0 | 0 | C | 0 | 亮 | 灭 |
| 999.9 ℉ | 9 | 9 | 9 | **F** | 9 | 亮 | **亮** |