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

6.9 KiB
Raw Blame History

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 引脚)

数码管脚 17(网络 LED_1LED_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.19.9(步0.1) → 1099(步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 用于显示 09/AF 之外的状态字符(如 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 亮 亮