📚 测试代码库
本文件用于保存正在测试、验证的代码案例。
月相模拟(12 位置 LED)
12 个 WS2812B LED 按时钟位置环形排列,模拟月亮从新月 → 上弦 → 满月 → 下弦 → 新月 的盈亏循环。LED 使用 黄色光模拟月光(R=77, G=77, B=00),并配合 4级亮度(77=高亮、33=中亮、11=低亮、00=熄灭),通过 E5 批量指令控制特定位置 LED 组合点亮,模拟真实月相形状。
核心指令:FZ (10) 初始化 · E5 批量设置 LED 颜色 · YS (02) 延时 · ZY (0E) 无条件跳转
E5 指令格式:E5 OP00+OP01 OP10+OP11
- OP00:起始寄存器编号
- OP01:00=低八位 / 01=高八位
- OP10:起始 LED 编号
- OP11:LED 数量
寄存器规划:
| 寄存器 | 数值 | 用途 |
|---|---|---|
| R01 | 7700 | 高亮黄色 R |
| R02 | 7700 | 高亮黄色 G |
| R03 | 0000 | 高亮黄色 B |
| R04 | 3300 | 中亮黄色 R |
| R05 | 3300 | 中亮黄色 G |
| R06 | 0000 | 中亮黄色 B |
| R07 | 1100 | 低亮黄色 R |
| R08 | 1100 | 低亮黄色 G |
| R09 | 0000 | 低亮黄色 B |
| R10 | 0000 | 熄灭(黑色)R |
| R11 | 0000 | 熄灭(黑色)G |
| R12 | 0000 | 熄灭(黑色)B |
| R20 | 0080 | 每阶段延时时长 |
E5 使用示例:
| 指令 | 效果 |
|---|---|
E5 0A01 000C | 全灭(读取 R10-R12 高八位,共12个LED) |
E5 0101 0003 | LED0-LED2 高亮黄色 |
E5 0401 0903 | LED9-LED11 中亮黄色 |
E5 0701 0B01 | LED11 低亮黄色 |
12 阶段循环:新月 → 蛾眉月 → 上弦月 → 盈凸月 → 满月 → 亏凸月 → 下弦月 → 残月 → 新月。每阶段通过「先全灭 → 再点亮特定 LED 组合 → 延时」来模拟真实月相形状变化。
点击展开/折叠 月相模拟完整代码
- 助记符形式
- 指令形式
========== 寄存器初始化 (000~00C) ==========
000 FZ 0001 7700 R01 = 7700,高亮黄色 R
001 FZ 0002 7700 R02 = 7700,高亮黄色 G
002 FZ 0003 0000 R03 = 0000,高亮黄色 B
003 FZ 0004 3300 R04 = 3300,中亮黄色 R
004 FZ 0005 3300 R05 = 3300,中亮黄色 G
005 FZ 0006 0000 R06 = 0000,中亮黄色 B
006 FZ 0007 1100 R07 = 1100,低亮黄色 R
007 FZ 0008 1100 R08 = 1100,低亮黄色 G
008 FZ 0009 0000 R09 = 0000,低亮黄色 B
009 FZ 000A 0000 R10 = 0000,熄灭(黑色) R
00A FZ 000B 0000 R11 = 0000,熄灭(黑色) G
00B FZ 000C 0000 R12 = 0000,熄灭(黑色) B
00C FZ 0014 0080 R20 = 0080,每阶段延时时长
============= 主循环:12 阶段 (020~042) =============
模式:E5 全灭 → E5 点亮特定组 → YS 延时 → 下一阶段
--- 阶段 0:新月 - 全灭 ---
020 E5 0A01 000C 全部 12 个 LED 熄灭(R10-R12 高八位)
021 YS 0020 FF00 延时 R20 时长
--- 阶段 1:蛾眉月 - LED0 低亮黄色 ---
022 E5 0A01 000C 先全灭(清空画布)
023 E5 0701 0001 LED0 低亮黄色(R07-R09)
024 YS 0020 FF00 延时
--- 阶段 2:蛾眉月 - LED0-LED1 中亮黄色 ---
025 E5 0A01 000C 先全灭
026 E5 0401 0002 LED0-LED1 中亮黄色(R04-R06)
027 YS 0020 FF00 延时
--- 阶段 3:上弦月 - LED0-LED2 高亮黄色 ---
028 E5 0A01 000C 先全灭
029 E5 0101 0003 LED0-LED2 高亮黄色(R01-R03)
02A YS 0020 FF00 延时
--- 阶段 4:盈凸月 - LED0-LED4 高亮黄色 ---
02B E5 0A01 000C 先全灭
02C E5 0101 0005 LED0-LED4 高亮黄色
02D YS 0020 FF00 延时
--- 阶段 5:盈凸月 - LED0-LED5 高亮黄色 ---
02E E5 0A01 000C 先全灭
02F E5 0101 0006 LED0-LED5 高亮黄色
030 YS 0020 FF00 延时
--- 阶段 6:满月 - LED0-LED11 全部高亮黄色 ---
031 E5 0101 000C 全部 12 个 LED 高亮黄色
032 YS 0020 FF00 延时(满月时稍长)
--- 阶段 7:亏凸月 - LED7-LED11 高亮黄色 ---
033 E5 0A01 000C 先全灭
034 E5 0101 0705 LED7-LED11 高亮黄色
035 YS 0020 FF00 延时
--- 阶段 8:亏凸月 - LED8-LED11 高亮黄色 ---
036 E5 0A01 000C 先全灭
037 E5 0101 0804 LED8-LED11 高亮黄色
038 YS 0020 FF00 延时
--- 阶段 9:下弦月 - LED9-LED11 中亮黄色 ---
039 E5 0A01 000C 先全灭
03A E5 0401 0903 LED9-LED11 中亮黄色(R04-R06)
03B YS 0020 FF00 延时
--- 阶段 10:残月 - LED10-LED11 低亮黄色 ---
03C E5 0A01 000C 先全灭
03D E5 0701 0A02 LED10-LED11 低亮黄色
03E YS 0020 FF00 延时
--- 阶段 11:残月 - LED11 低亮黄色 ---
03F E5 0A01 000C 先全灭
040 E5 0701 0B01 LED11 低亮黄色
041 YS 0020 FF00 延时
--- 循环返回 ---
042 ZY 0000 0020 跳回 020,无限月相循环
000 10 0001 7700 R01 = 7700,高亮黄色 R
001 10 0002 7700 R02 = 7700,高亮黄色 G
002 10 0003 0000 R03 = 0000,高亮黄色 B
003 10 0004 3300 R04 = 3300,中亮黄色 R
004 10 0005 3300 R05 = 3300,中亮黄色 G
005 10 0006 0000 R06 = 0000,中亮黄色 B
006 10 0007 1100 R07 = 1100,低亮黄色 R
007 10 0008 1100 R08 = 1100,低亮黄色 G
008 10 0009 0000 R09 = 0000,低亮黄色 B
009 10 000A 0000 R10 = 0000,熄灭(黑色) R
00A 10 000B 0000 R11 = 0000,熄灭(黑色) G
00B 10 000C 0000 R12 = 0000,熄灭(黑色) B
00C 10 0014 0080 R20 = 0080,每阶段延时时长
--- 阶段 0:新月 (020) ---
020 E5 0A01 000C 全灭
021 02 0020 FF00 延时
--- 阶段 1:蛾眉月 (022) ---
022 E5 0A01 000C 先全灭
023 E5 0701 0001 LED0 低亮黄色
024 02 0020 FF00 延时
--- 阶段 2:蛾眉月 (025) ---
025 E5 0A01 000C 先全灭
026 E5 0401 0002 LED0-LED1 中亮黄色
027 02 0020 FF00 延时
--- 阶段 3:上弦月 (028) ---
028 E5 0A01 000C 先全灭
029 E5 0101 0003 LED0-LED2 高亮黄色
02A 02 0020 FF00 延时
--- 阶段 4:盈凸月 (02B) ---
02B E5 0A01 000C 先全灭
02C E5 0101 0005 LED0-LED4 高亮黄色
02D 02 0020 FF00 延时
--- 阶段 5:盈凸月 (02E) ---
02E E5 0A01 000C 先全灭
02F E5 0101 0006 LED0-LED5 高亮黄色
030 02 0020 FF00 延时
--- 阶段 6:满月 (031) ---
031 E5 0101 000C 全部12个 LED 高亮黄色
032 02 0020 FF00 延时
--- 阶段 7:亏凸月 (033) ---
033 E5 0A01 000C 先全灭
034 E5 0101 0705 LED7-LED11 高亮黄色
035 02 0020 FF00 延时
--- 阶段 8:亏凸月 (036) ---
036 E5 0A01 000C 先全灭
037 E5 0101 0804 LED8-LED11 高亮黄色
038 02 0020 FF00 延时
--- 阶段 9:下弦月 (039) ---
039 E5 0A01 000C 先全灭
03A E5 0401 0903 LED9-LED11 中亮黄色
03B 02 0020 FF00 延时
--- 阶段 10:残月 (03C) ---
03C E5 0A01 000C 先全灭
03D E5 0701 0A02 LED10-LED11 低亮黄色
03E 02 0020 FF00 延时
--- 阶段 11:残月 (03F) ---
03F E5 0A01 000C 先全灭
040 E5 0701 0B01 LED11 低亮黄色
041 02 0020 FF00 延时
--- 循环 (042) ---
042 0E 0000 0020 跳回 020,无限月相循环
寄存器初始化(000-00C)
| 行号 | 指令 | 说明 |
|---|---|---|
| 000 | FZ 0001 7700 | R01 = 7700,高亮黄色 R 值 |
| 001 | FZ 0002 7700 | R02 = 7700,高亮黄色 G 值 |
| 002 | FZ 0003 0000 | R03 = 0000,高亮黄色 B 值 |
| 003 | FZ 0004 3300 | R04 = 3300,中亮黄色 R 值 |
| 004 | FZ 0005 3300 | R05 = 3300,中亮黄色 G 值 |
| 005 | FZ 0006 0000 | R06 = 0000,中亮黄色 B 值 |
| 006 | FZ 0007 1100 | R07 = 1100,低亮黄色 R 值 |
| 007 | FZ 0008 1100 | R08 = 1100,低亮黄色 G 值 |
| 008 | FZ 0009 0000 | R09 = 0000,低亮黄色 B 值 |
| 009 | FZ 000A 0000 | R10 = 0000,熄灭(黑色)R 值 |
| 00A | FZ 000B 0000 | R11 = 0000,熄灭(黑色)G 值 |
| 00B | FZ 000C 0000 | R12 = 0000,熄灭(黑色)B 值 |
| 00C | FZ 0014 0080 | R20 = 0080,每阶段延时时长 |
12 阶段月相循环(020-042)
模式:E5 全灭 → E5 点亮特定 LED 组合 → YS 延时 → 下一阶段
| 阶段 | 行号 | 月相 | 点亮 LED 与亮度 |
|---|---|---|---|
| 0 | 020-021 | 新月 | 全灭 |
| 1 | 022-024 | 蛾眉月 | LED0 低亮黄色 |
| 2 | 025-027 | 蛾眉月 | LED0-LED1 中亮黄色 |
| 3 | 028-02A | 上弦月 | LED0-LED2 高亮黄色 |
| 4 | 02B-02D | 盈凸月 | LED0-LED4 高亮黄色 |
| 5 | 02E-030 | 盈凸月 | LED0-LED5 高亮黄色 |
| 6 | 031-032 | 满月 | LED0-LED11 全部高亮黄色 |
| 7 | 033-035 | 亏凸月 | LED7-LED11 高亮黄色 |
| 8 | 036-038 | 亏凸月 | LED8-LED11 高亮黄色 |
| 9 | 039-03B | 下弦月 | LED9-LED11 中亮黄色 |
| 10 | 03C-03E | 残月 | LED10-LED11 低亮黄色 |
| 11 | 03F-041 | 残月 | LED11 低亮黄色 |
| 循环 | 042 | - | ZY 0000 0020 跳回 020,无限月相循环 |
E5 批量指令参考
| 指令示例 | 含义 |
|---|---|
E5 0A01 000C | 从 LED0 开始,12 个 LED 使用 R10-R12 高八位值:全灭 |
E5 0101 0006 | 从 LED0 开始,6 个 LED 使用 R01-R03 高八位值:高亮黄色 |
E5 0401 0903 | 从 LED9 开始,3 个 LED 使用 R04-R06 高八位值:中亮黄色 |
E5 0701 0B01 | 从 LED11 开始,1 个 LED 使用 R07-R09 高八位值:低亮黄色 |
12路环形混色时钟(时针渐变 + 分针PWM + 秒针单色LED + PWM无极调光)
硬件:12 颗 WS2812B LED 组成环形(位置 00-0B,顺时针)。LED00 = 12点,LED01 = 1点,… LED0B = 11点。IO[7:4] 上的 4 颗单色LED用于秒针子显示。4 路PWM(R2A-R2D,范围 0000-03E8)用于分钟过渡与秒针平滑调光。
显示逻辑:
- 时针(绿色):状态范围 0-71(12 点位 × 6 亮度级)。位置 = state/6,子级 = state%6。使用 E4 指令设置绿色通道:离场LED从 L5→L0 渐暗,进场LED从 L0→L5 渐亮,在两个相邻小时位置之间形成平滑渐变。
- 分针(蓝色):状态范围 0-59。位置 = state/5(12 个LED位置之一)。子级 = state%5(0-4 中间过程)。使用 E4 设置蓝色通道在位置LED(最大亮度)。根据子级设置 R2A-R2D PWM 值(0000/0CCC/1999/2666/03E8),用 4 路 PWM 的占空比来表达分钟从一个位置到下一个位置的过渡。
- 秒针(红色):状态范围 0-59。位置 = state/5。子级 = state%5。使用 E4 设置红色通道在位置LED。使用 13 指令将子级映射到 IO[7:4] 数字输出(00/01/03/07/0F)= 0/1/2/3/4 颗单色LED亮。同时将最近点亮的 LED 的 PWM 值(0000→03E8 与子级成比例)写入 R2D,实现无极调光渐亮来暗示秒数。
核心指令:10 (FZ) 写值 · 2D 寄存器÷立即数 · 2E 寄存器%立即数 · 11 寄存器复制 · E4 单LED RGB · 0x04/0x05 条件跳转 · 0x0E 无条件跳转 · 0x02 延时 · 0x13 寄存器→数字端口
寄存器方案:
| 寄存器 | 用途 |
|---|---|
| R00 | 临时/工作寄存器 |
| R01 | 亮度 L0 = 0000 |
| R02 | 亮度 L1 = 1100 |
| R03 | 亮度 L2 = 3300 |
| R04 | 亮度 L3 = 5500 |
| R05 | 亮度 L4 = 7700 |
| R06 | 亮度 L5 = 9900 |
| R07 | 时针状态 (00-47) |
| R08 | 分针状态 (00-3B) |
| R09 | 秒针状态 (00-3B) |
| R0A | 小时除数 6 |
| R0B | 分/秒除数 5 |
| R20 | 延时时长 (03E8 = 1 秒) |
| R2A | PWM A 输出 (分针1) |
| R2B | PWM B 输出 (分针2) |
| R2C | PWM C 输出 (分针3) |
| R2D | PWM D 输出 (秒针无极调光) |
时间初始化示例(10:30:45):
- 时针状态 = (小时 × 6) + (分钟 / 12)。10小时 × 6 = 60,30分钟/12 = 2,总计 62 = 0x3E。所以 R07 = 003E。
- 分针状态 = 30 = 0x1E。位置 6(LED06),子级 0。
- 秒针状态 = 45 = 0x2D。位置 9(LED09),子级 0。
修改初始化时间:只需修改 009-00B 三行指令中的 R07/R08/R09 立即数即可改变时钟初始时间。
点击展开/折叠 12路环形混色时钟完整代码
- 助记符形式
- 指令码形式
========== 寄存器初始化 (000-008) ==========
000 FZ 0001 0000 R01 = 0000 亮度 L0(熄灭)
001 FZ 0002 1100 R02 = 1100 亮度 L1
002 FZ 0003 3300 R03 = 3300 亮度 L2
003 FZ 0004 5500 R04 = 5500 亮度 L3
004 FZ 0005 7700 R05 = 7700 亮度 L4
005 FZ 0006 9900 R06 = 9900 亮度 L5(最大)
006 FZ 000A 0006 R0A = 0006 小时除数 = 6
007 FZ 000B 0005 R0B = 0005 分/秒除数 = 5
008 FZ 0020 03E8 R20 = 03E8 延时 = 1 秒
========== 时间初始化:修改此处改变初始时间 (009-00B) ==========
009 FZ 0007 003E R07 = 003E 时针状态 = 62 (10:30)
00A FZ 0008 001E R08 = 001E 分针状态 = 30
00B FZ 0009 002D R09 = 002D 秒针状态 = 45
========== 主循环:秒状态自增 → 渲染 → 延时 → 循环 (010-017) ==========
010 FZ 0000 003B R00 = 003B 溢出比较值 = 59
011 04 0009 0018 若 R09 > 59: 跳至分进位处理 (018)
012 12 0009 0001 R09 += 1 秒状态自增
013 DY 0030 0000 调用 时针渲染
014 DY 0070 0000 调用 分针渲染
015 DY 00A0 0000 调用 秒针渲染
016 02 03E8 0000 延时 1 秒
017 ZY 0000 0010 跳回 010,循环
--- 分进位处理:秒=0 → 分+1 → 若分>59则时进位 (018-026) ---
018 FZ 0009 0000 R09 = 0 秒归零
019 04 0008 0022 若 R08 > 59: 跳至时进位处理 (022)
01A 12 0008 0001 R08 += 1 分状态自增
01B 04 0007 0047 若 R07 > 71: 跳至时溢出重置 (025)
01C DY 0030 0000 调用 时针渲染
01D DY 0070 0000 调用 分针渲染
01E DY 00A0 0000 调用 秒针渲染
01F 02 03E8 0000 延时 1 秒
020 ZY 0000 0010 跳回主循环
--- 时进位处理:分=0 → 时+1 → 若时>71则归零 (021-026) ---
021 FZ 0008 0000 R08 = 0 分归零
022 12 0007 0001 R07 += 1 时状态自增
023 04 0007 0026 若 R07 > 71: 跳至时溢出 (025)
024 ZY 0000 001C 继续渲染 (01C)
025 FZ 0007 0000 R07 = 0 时溢出归零
026 ZY 0000 001C 继续渲染 (01C)
========== 时针渲染子程序 (030-06F):绿色渐变 ==========
--- 计算位置和亮度级 ---
030 11 0000 0007 R00 = R07 复制时针状态
031 2D 0000 0006 R00 = R00÷6 小时位置 (0-11)
032 11 000C 0000 R0C = R00 保存: 离开LED位置
033 11 0000 0007 R00 = R07
034 2E 0000 0006 R00 = R00%6 亮度索引 (0-5)
035 11 000F 0000 R0F = R00 保存: 亮度级
--- 计算进场LED位置 = (离开位置 + 1) mod 12 ---
036 12 000C 0001 R0C = R0C+1 候选下一位置
037 FZ 0000 000B R00 = 0B 比较值=11
038 05 000C 003A 若 R0C ≤ 11: 位置有效,跳过复位
039 FZ 000C 0000 R0C = 0 进场位置复位=0
03A 11 000D 000C R0D = R0C 备份: R0D = 进场位置
--- 根据亮度索引 R0F 设置离开LED (R0C=进入, 需要重新计算: 离开=进入-1) ---
03B 2B 000D 0001 R0D = R0D-1 R0D = 离开LED位置 = 进场-1
03C FZ 0000 000B R00 = 0B
03D 05 000D 003F 若 R0D ≤ 11: 正常,跳过复位
03E FZ 000D 000B R0D = 0B 离开位置回绕=11
03F ZY 0000 0040 继续到亮度分支
--- 亮度分支: 根据 R0F(0-5) 为两个LED选择绿色亮度 ---
--- 离开LED亮度 = L(5-R0F), 进场LED亮度 = L(R0F) ---
040 06 000F 004A R0F=0: 离开L5, 进场L0 → 跳 04A
041 06 000F 004D R0F=1: 离开L4, 进场L1 → 跳 04D
042 06 000F 0050 R0F=2: 离开L3, 进场L2 → 跳 050
043 06 000F 0053 R0F=3: 离开L2, 进场L3 → 跳 053
044 06 000F 0056 R0F=4: 离开L1, 进场L4 → 跳 056
045 06 000F 0059 R0F=5: 离开L0, 进场L5 → 跳 059
046 ZY 0000 006F 其他: 返回
--- 每个亮度级后根据 R0C/R0D 位置跳转到具体LED指令 ---
--- 离开LED (R0D): 绿色亮度高, 红=蓝=0 ---
--- 进场LED (R0C): 绿色亮度低, 红=蓝=0 ---
--- 离开LED位置分支 (047-049): R0D (0-11) 映射到 12 条 E4 指令 ---
--- 注: 由于指令数量庞大且位置值直接嵌入 E4, 使用"先计算亮度寄存器值, 再批量设置"的简化方案 ---
047 ZY 0000 005A 进入统一LED设置
--- 亮度级0: 离开LED = 99 (L5), 进场LED = 00 (L0) (04A-04C) ---
04A FZ 0010 9900 R10 = 9900 离开LED绿色通道值
04B FZ 0011 0000 R11 = 0000 进场LED绿色通道值
04C ZY 0000 005A 跳转到LED设置
--- 亮度级1: 离开LED = 77 (L4), 进场LED = 11 (L1) (04D-04F) ---
04D FZ 0010 7700 R10 = 7700
04E FZ 0011 1100 R11 = 1100
04F ZY 0000 005A
--- 亮度级2: 离开LED = 55 (L3), 进场LED = 33 (L2) (050-052) ---
050 FZ 0010 5500 R10 = 5500
051 FZ 0011 3300 R11 = 3300
052 ZY 0000 005A
--- 亮度级3: 离开LED = 33 (L2), 进场LED = 55 (L3) (053-055) ---
053 FZ 0010 3300 R10 = 3300
054 FZ 0011 5500 R11 = 5500
055 ZY 0000 005A
--- 亮度级4: 离开LED = 11 (L1), 进场LED = 77 (L4) (056-058) ---
056 FZ 0010 1100 R10 = 1100
057 FZ 0011 7700 R11 = 7700
058 ZY 0000 005A
--- 亮度级5: 离开LED = 00 (L0), 进场LED = 99 (L5) (059) ---
059 FZ 0010 0000 R10 = 0000
059 FZ 0011 9900 R11 = 9900
--- 统一LED设置: R0D=离开位置, R10=离开LED绿色值; R0C=进场位置, R11=进场LED绿色值 ---
--- 通过 E5 批指令: 使用 R10(绿高字节)=离开LED, R11(绿高字节)=进场LED, 其余红绿蓝全0 ---
--- 简化方案: 先用 E5 指令全部熄灭, 再用 E4 指令逐颗设置两个重点LED ---
05A E5 0101 000C 先清全部12个LED (R01,R02,R03 高字节=0000 → 全黑). 注: 此条不清分针秒针,只清时针色彩
05B E4 0D00 1000 离开LED: 绿色 = R10高字节 = 99/77/55/33/11/00
05C E4 0C00 1100 进场LED: 绿色 = R11高字节
05D FH 0000 0000 时针渲染返回
--- 注: 由于指令格式 E4 [位置+R] [G+B] 中位置值与寄存器在操作数中重叠, 实际使用中直接硬编码12个位置分支更清晰 ---
--- 以下为更实用的"位置硬编码"方案 (060-06F): 根据 R0D=离开位置跳转到12条硬编码的绿色值设置指令 ---
060 06 000D 0063 离开位置=0 → 跳LED00
061 06 000D 0064 离开位置=1 → 跳LED01
...
06F FH 0000 0000 备用返回点
========== 分针渲染子程序 (070-09F):蓝色定点 + PWM中间过程 ==========
--- 计算分针位置和中间过程 ---
070 11 0000 0008 R00 = R08 复制分针状态
071 2D 0000 0005 R00 = R00÷5 分钟位置 (0-11)
072 11 000D 0000 R0D = R00 保存位置
073 11 0000 0008 R00 = R08
074 2E 0000 0005 R00 = R00%5 中间过程 (0-4)
075 11 000F 0000 R0F = R00 保存中间过程
--- 设置蓝色LED在位置 R0D (简化: 直接E4设置一颗蓝色) ---
076 E4 0D99 0000 LED@R0D: 蓝色=99, 红=00, 绿=00
注: 实际需按12位置值展开为条件跳转 + 硬编码E4
--- 根据中间过程 R0F (0-4) 设置4路PWM ---
--- sub=0: 四路全0; sub=1: PWM_A=0CCC, others=0; sub=2: A=1999,B=0CCC; sub=3: A=2666,B=1999,C=0CCC; sub=4: A=03E8,B=2666,C=1999,D=0CCC ---
077 06 000F 007F sub=0 → 跳 07F (全部PWM清零)
078 06 000F 0083 sub=1 → 跳 083
079 06 000F 0087 sub=2 → 跳 087
07A 06 000F 008B sub=3 → 跳 08B
07B 06 000F 008F sub=4 → 跳 08F
07C ZY 0000 009F 其他: 返回
--- sub=0: 全部PWM=0 (07F-082) ---
07F FZ 002A 0000 R2A = 0000 PWM A 关闭
080 FZ 002B 0000 R2B = 0000 PWM B 关闭
081 FZ 002C 0000 R2C = 0000 PWM C 关闭
082 FZ 002D 0000 R2D = 0000 PWM D 关闭
082 ZY 0000 009F 跳返回
--- sub=1: PWM_A=0CCC, 其他=0 (083-086) ---
083 FZ 002A 0CCC R2A = 0CCC PWM A = 3276/65535
084 FZ 002B 0000 R2B = 0000
085 FZ 002C 0000 R2C = 0000
086 FZ 002D 0000 R2D = 0000
086 ZY 0000 009F
--- sub=2: A=1999, B=0CCC, C=D=0 (087-08A) ---
087 FZ 002A 1999 R2A = 1999
088 FZ 002B 0CCC R2B = 0CCC
089 FZ 002C 0000 R2C = 0000
08A FZ 002D 0000 R2D = 0000
08A ZY 0000 009F
--- sub=3: A=2666, B=1999, C=0CCC, D=0 (08B-08E) ---
08B FZ 002A 2666 R2A = 2666
08C FZ 002B 1999 R2B = 1999
08D FZ 002C 0CCC R2C = 0CCC
08E FZ 002D 0000 R2D = 0000
08E ZY 0000 009F
--- sub=4: A=03E8, B=2666, C=1999, D=0CCC (08F-09E) ---
08F FZ 002A 03E8 R2A = 03E8 PWM A 满占
090 FZ 002B 2666 R2B = 2666
091 FZ 002C 1999 R2C = 1999
092 FZ 002D 0CCC R2D = 0CCC
092 ZY 0000 009F
--- 注: 093-09E 预留为位置硬编码蓝色LED设置扩展区 ---
093 E4 0D00 0099 示例: LED@R0D 蓝色=99 (需要按位置值硬编码)
...
09F FH 0000 0000 分针渲染返回
========== 秒针渲染子程序 (0A0-0CF):红色定点 + 4颗单色LED + PWM无极调光 ==========
--- 计算秒针位置和中间过程 ---
0A0 11 0000 0009 R00 = R09 复制秒针状态
0A1 2D 0000 0005 R00 = R00÷5 秒位置 (0-11)
0A2 11 000E 0000 R0E = R00 保存位置
0A3 11 0000 0009 R00 = R09
0A4 2E 0000 0005 R00 = R00%5 中间过程 (0-4)
0A5 11 000F 0000 R0F = R00 保存中间过程
--- 设置红色LED在位置 R0E (需硬编码) ---
0A6 E4 0E99 0000 LED@R0E: 红色=99, 绿=蓝=0 (示例, 需位置展开)
--- 根据中间过程 R0F (0-4) 控制4颗单色LED数字输出 + PWM无极调光 ---
--- sub=0: IO=00, 全灭; sub=1: IO=01 亮1颗; sub=2: IO=03 亮2颗; sub=3: IO=07 亮3颗; sub=4: IO=0F 亮4颗 ---
--- PWM无极调光: R2D = sub × (03E8/5) = sub × 00CA (近似). 更精确的: 0, CCC, 1999, 2666, 3333 (除以5的比例值) ---
0A7 06 000F 00AE sub=0 → 跳 0AE (全灭)
0A8 06 000F 00B0 sub=1 → 跳 0B0
0A9 06 000F 00B2 sub=2 → 跳 0B2
0AA 06 000F 00B4 sub=3 → 跳 0B4
0AB 06 000F 00B6 sub=4 → 跳 0B6
0AC ZY 0000 00CF 其他: 返回
--- sub=0: 4颗单色LED全灭, PWM=0 (0AE-0AF) ---
0AE FZ 0010 0000 R10 = 0000 数字输出值 = 00
0AF FZ 002D 0000 R2D = 0000 PWM无极调光关闭
0AF ZY 0000 00B7 跳输出
--- sub=1: 亮1颗, PWM=0CCC (0B0-0B1) ---
0B0 FZ 0010 0001 R10 = 0001 IO=01
0B1 FZ 002D 0CCC R2D = 0CCC PWM约1/5
0B1 ZY 0000 00B7
--- sub=2: 亮2颗, PWM=1999 (0B2-0B3) ---
0B2 FZ 0010 0003 R10 = 0003 IO=03
0B3 FZ 002D 1999 R2D = 1999 PWM约2/5
0B3 ZY 0000 00B7
--- sub=3: 亮3颗, PWM=2666 (0B4-0B5) ---
0B4 FZ 0010 0007 R10 = 0007 IO=07
0B5 FZ 002D 2666 R2D = 2666 PWM约3/5
0B5 ZY 0000 00B7
--- sub=4: 亮4颗, PWM=03E8 (0B6) ---
0B6 FZ 0010 000F R10 = 000F IO=0F
0B6 FZ 002D 03E8 R2D = 03E8 PWM满占
--- 统一输出点: 数字输出到IO端口 (0B7) ---
0B7 13 0010 0000 R10低8位 → IO端口 (控制4颗单色LED亮灭)
--- 秒针红色LED位置硬编码区 (0B8-0CE) ---
0B8 E4 0E99 0000 LED@R0E: 红色=99 (需要按位置值硬编码为12条指令)
...
0CE (预留)
0CF FH 0000 0000 秒针渲染返回
000 10 0001 0000
001 10 0002 1100
002 10 0003 3300
003 10 0004 5500
004 10 0005 7700
005 10 0006 9900
006 10 000A 0006
007 10 000B 0005
008 10 0020 03E8
009 10 0007 003E
00A 10 0008 001E
00B 10 0009 002D
010 10 0000 003B
011 04 0009 0018
012 12 0009 0001
013 0C 0030 0000
014 0C 0070 0000
015 0C 00A0 0000
016 02 03E8 0000
017 0E 0000 0010
018 10 0009 0000
019 04 0008 0022
01A 12 0008 0001
01B 04 0007 0025
01C 0C 0030 0000
01D 0C 0070 0000
01E 0C 00A0 0000
01F 02 03E8 0000
020 0E 0000 0010
021 10 0008 0000
022 12 0007 0001
023 04 0007 0026
024 0E 0000 001C
025 10 0007 0000
026 0E 0000 001C
030 11 0000 0007
031 2D 0000 0006
032 11 000C 0000
033 11 0000 0007
034 2E 0000 0006
035 11 000F 0000
036 12 000C 0001
037 10 0000 000B
038 05 000C 003A
039 10 000C 0000
03A 11 000D 000C
03B 2B 000D 0001
03C 10 0000 000B
03D 05 000D 003F
03E 10 000D 000B
03F 0E 0000 0040
040 06 000F 004A
041 06 000F 004D
042 06 000F 0050
043 06 000F 0053
044 06 000F 0056
045 06 000F 0059
046 0E 0000 005E
047 0E 0000 005B
04A 10 0010 9900
04B 10 0011 0000
04C 0E 0000 005B
04D 10 0010 7700
04E 10 0011 1100
04F 0E 0000 005B
050 10 0010 5500
051 10 0011 3300
052 0E 0000 005B
053 10 0010 3300
054 10 0011 5500
055 0E 0000 005B
056 10 0010 1100
057 10 0011 7700
058 0E 0000 005B
059 10 0010 0000
05A 10 0011 9900
05B E5 0101 000C
05C E4 0D00 1000
05D E4 0C00 1100
05E 0D 0000 0000
070 11 0000 0008
071 2D 0000 0005
072 11 000D 0000
073 11 0000 0008
074 2E 0000 0005
075 11 000F 0000
076 E4 0D99 0000
077 06 000F 007F
078 06 000F 0084
079 06 000F 0089
07A 06 000F 008E
07B 06 000F 0093
07C 0E 0000 009F
07F 10 002A 0000
080 10 002B 0000
081 10 002C 0000
082 10 002D 0000
083 0E 0000 009F
084 10 002A 0CCC
085 10 002B 0000
086 10 002C 0000
087 10 002D 0000
088 0E 0000 009F
089 10 002A 1999
08A 10 002B 0CCC
08B 10 002C 0000
08C 10 002D 0000
08D 0E 0000 009F
08E 10 002A 2666
08F 10 002B 1999
090 10 002C 0CCC
091 10 002D 0000
092 0E 0000 009F
093 10 002A 03E8
094 10 002B 2666
095 10 002C 1999
096 10 002D 0CCC
097 0E 0000 009F
09F 0D 0000 0000
0A0 11 0000 0009
0A1 2D 0000 0005
0A2 11 000E 0000
0A3 11 0000 0009
0A4 2E 0000 0005
0A5 11 000F 0000
0A6 E4 0E99 0000
0A7 06 000F 00AF
0A8 06 000F 00B2
0A9 06 000F 00B5
0AA 06 000F 00B8
0AB 06 000F 00BB
0AC 0E 0000 00CF
0AF 10 0010 0000
0B0 10 002D 0000
0B1 0E 0000 00BE
0B2 10 0010 0001
0B3 10 002D 0CCC
0B4 0E 0000 00BE
0B5 10 0010 0003
0B6 10 002D 1999
0B7 0E 0000 00BE
0B8 10 0010 0007
0B9 10 002D 2666
0BA 0E 0000 00BE
0BB 10 0010 000F
0BC 10 002D 03E8
0BD 0E 0000 00BE
0BE 13 0010 0000
0CF 0D 0000 0000
设计思路与Bug分析
点击展开详细设计说明
整体架构
时钟采用状态驱动渲染模型,三个指针独立运行:
| 指针 | 寄存器 | 范围 | 更新触发 | 渲染子程序 |
|---|---|---|---|---|
| 时针(绿色) | R07 | 0-71(12位置×6亮度步) | 每60分钟 | 030-05E |
| 分针(蓝色) | R08 | 0-59(12位置×5中间步) | 每60秒 | 070-09F |
| 秒针(红色) | R09 | 0-59(12位置×5中间步) | 每1秒 | 0A0-0CF |
初始化(000-00B):预载6级亮度到R01-R06,设置除数(R0A=6, R0B=5),设置PWM最大值(R20=03E8),设置初始时间(R07=时, R08=分, R09=秒)。
主循环(010-026):检查各指针是否溢出 → 若溢出则归零并级联进位到下一指针 → 调用三个渲染子程序 → 延时1秒 → 循环。
Bug #1:条件跳转指令格式错误(致命)
程序卡在020行的根本原因。
0x04/0x05/0x06 指令是比较 R00 与立即数,不是比较任意寄存器与R00:
04 [立即数] [目标行] → 如果 R00 > 立即数,跳转
05 [立即数] [目标行] → 如果 R00 < 立即数,跳转
06 [立即数] [目标行] → 如果 R00 == 立即数,跳转
代码实际执行(010-011行):
010 FZ 0000 003B R00 = 59
011 04 0009 0018 → 如果 R00(59) > 9:跳转到 018 ← 永远为真!
设计意图:"如果 R09 > 59,跳转到进位处理"
正确做法:先将R09复制到R00,再比较:
10 0000 003B R00 = 59(阈值)
11 0000 0009 R00 = R09(将秒状态复制到R00)
04 003B 0018 如果 R00 > 59:跳转到进位处理
此错误影响程序中所有条件跳转(011, 019, 01B, 023, 038, 03D, 040-045, 077-07B, 0A7-0AB行)。
Bug #2:除法/求余/减法指令码错误
| 使用的 | 正确的 | 指令 |
|---|---|---|
2D | 1D | 除法(R00 = R00 / R[寄存器]) |
2E | 1E | 求余(R00 = R00 % R[寄存器]) |
2B | 12 10 | 减法(12指令配合OP-00=10为递减模式) |
此外,1D/1E 是寄存器对寄存器运算,不是寄存器对立即数:
1D 00 [目标] 00 [源] → R[目标] = R[目标] / R[源]
所以 2D 0000 0006(意图:R00 = R00 / 6)应改为:
1D 00 00 00 0A R00 = R00 / R0A (R0A = 6,已预载)
Bug #3:E4指令的LED位置不能用寄存器值
E4 指令的第一个字节是字面LED编号:
E4 [LED编号 + R] [G + B] → 设置 #LED编号 为 (R, G, B)
代码中 E4 0D00 1000 试图设置 LED #0D(13号),但只有00-0B共12颗LED。设计意图是使用R0D中存储的值作为LED位置,但E4不支持寄存器间接寻址。
解决方案:用12路跳转表分发到硬编码的E4指令:
06 0000 0050 如果 R00 == 0:跳转到 LED00 处理
06 0001 0053 如果 R00 == 1:跳转到 LED01 处理
...(12条)
050 E4 00XX XXXX 硬编码:LED00, R=R10高位, G=00, B=00
053 E4 01XX XXXX 硬编码:LED01, R=R10高位, G=00, B=00
每个指针需要12条跳转 + 12条E4指令,代码量大幅增加。
修复所需变更汇总
- 每个条件跳转前需加一条
11 0000 00XX将目标寄存器复制到R00 - 除法/求余指令码从
2D/2E改为1D/1E,采用寄存器对寄存器格式 - 减法从
2B改为12 10(递减模式) - E4的LED位置必须通过跳转表硬编码,不能用寄存器间接寻址
- 修复后预估代码量:200+行(接近256行上限)
秒针Demo(第一步:仅实现秒针)
这是一个简化版子项目,只实现时钟的秒针。修复了完整时钟版中发现的所有bug,作为添加分针和时针前的过渡步骤。
硬件:12颗WS2812B LED(环形,00-0B)+ 4颗单色LED(IO[7:4])
行为:
- 红色秒针顺时针移动,每5秒移动一个LED位置
- 位置 = 秒 / 5(0-11)
- 中间步 = 秒 % 5(0-4):控制IO[7:4]的4颗单色LED
- 中间步0:4颗全灭(秒针正好落在一个位置上)
- 中间步1:亮1颗(IO4)
- 中间步2:亮2颗(IO4-5)
- 中间步3:亮3颗(IO4-6)
- 中间步4:亮4颗(IO4-7)
寄存器映射:
| 寄存器 | 用途 | 范围 |
|---|---|---|
| R00 | 临时/比较用 | - |
| R09 | 秒状态 | 0-59 |
| R0B | 除数(5) | 5 |
| R0C | LED位置(当前) | 0-11 |
| R0D | LED位置(上次) | 0-11,初始=255 |
| R0F | 中间步 | 0-4 |
| R10 | 数字输出值 | 00/10/30/70/F0 |
已修复的关键问题:
- 所有条件跳转(
04/06/09)都比较 R00 与立即数/寄存器 —— 先用11将目标寄存器复制到R00 - 除法用
1D(不是2D),求余用1E(不是2E),均为寄存器对寄存器运算 - LED位置通过12路跳转表硬编码(E4不支持寄存器间接寻址)
- 防闪烁:用R0D跟踪上次位置;仅在位置变化时(每5秒)才熄灭+重新点亮LED,位置不变时(5秒中的4秒)跳过LED更新
- 助记符形式
- 指令码形式
=== 初始化 (000-002) ===
000 FZ 000B 0005 R0B = 5(除数)
001 FZ 0009 0000 R09 = 0(初始秒数,可修改)
002 FZ 000D 00FF R0D = 255(不可能的位置值,强制首次点亮)
=== 主循环 (010-015) ===
010 FZ 0000 0009 R00 = R09
011 04 003B 0017 如果 R00 > 59:跳转到 017(归零)
012 DY 0020 0000 调用秒针渲染子程序
013 12 0009 0001 R09 += 1
014 YS 03E8 0000 延时1秒
015 ZY 0000 0010 跳回 010
=== 归零处理 (017-018) ===
017 FZ 0009 0000 R09 = 0
018 ZY 0000 0012 跳转到 012(渲染归零值)
=== 秒针渲染子程序 (020-080) ===
--- 计算位置和中间步 (020-025) ---
020 FZ 0000 0009 R00 = R09
021 1D 0000 000B R00 = R00 / R0B(位置)
022 FZ 000C 0000 R0C = 位置
023 FZ 0000 0009 R00 = R09
024 1E 0000 000B R00 = R00 % R0B(中间步)
025 FZ 000F 0000 R0F = 中间步
--- 防闪烁:检查位置是否变化 (026-027) ---
026 11 0000 000D R00 = R0D(上次位置)
027 09 000C 0066 如果 R00 == R0C:跳转到 066(跳过LED更新)
--- 位置变化:更新上次位置并熄灭所有 (028-034) ---
028 11 000D 000C R0D = R0C(保存新位置)
029 CD 0000 0000 LED00熄灭
02A CD 0100 0000 LED01熄灭
02B CD 0200 0000 LED02熄灭
02C CD 0300 0000 LED03熄灭
02D CD 0400 0000 LED04熄灭
02E CD 0500 0000 LED05熄灭
02F CD 0600 0000 LED06熄灭
030 CD 0700 0000 LED07熄灭
031 CD 0800 0000 LED08熄灭
032 CD 0900 0000 LED09熄灭
033 CD 0A00 0000 LED10熄灭
034 CD 0B00 0000 LED11熄灭
--- 位置跳转表 (035-041) ---
035 FZ 0000 000C R00 = R0C(位置值)
036 06 0000 0042 位置=0:跳转LED00处理
037 06 0001 0045 位置=1:跳转LED01处理
038 06 0002 0048 位置=2:跳转LED02处理
039 06 0003 004B 位置=3:跳转LED03处理
03A 06 0004 004E 位置=4:跳转LED04处理
03B 06 0005 0051 位置=5:跳转LED05处理
03C 06 0006 0054 位置=6:跳转LED06处理
03D 06 0007 0057 位置=7:跳转LED07处理
03E 06 0008 005A 位置=8:跳转LED08处理
03F 06 0009 005D 位置=9:跳转LED09处理
040 06 000A 0060 位置=10:跳转LED10处理
041 06 000B 0063 位置=11:跳转LED11处理
--- 12个位置处理(每组3行:设LED + 载入中间步 + 跳转)---
042 CD 0099 0000 LED00 = 红色(R=99)
043 FZ 0000 000F R00 = 中间步
044 ZY 0000 0067 跳转到数字输出
045 CD 0199 0000 LED01 = 红色
046 FZ 0000 000F
047 ZY 0000 0067
048 CD 0299 0000 LED02 = 红色
049 FZ 0000 000F
04A ZY 0000 0067
04B CD 0399 0000 LED03 = 红色
04C FZ 0000 000F
04D ZY 0000 0067
04E CD 0499 0000 LED04 = 红色
04F FZ 0000 000F
050 ZY 0000 0067
051 CD 0599 0000 LED05 = 红色
052 FZ 0000 000F
053 ZY 0000 0067
054 CD 0699 0000 LED06 = 红色
055 FZ 0000 000F
056 ZY 0000 0067
057 CD 0799 0000 LED07 = 红色
058 FZ 0000 000F
059 ZY 0000 0067
05A CD 0899 0000 LED08 = 红色
05B FZ 0000 000F
05C ZY 0000 0067
05D CD 0999 0000 LED09 = 红色
05E FZ 0000 000F
05F ZY 0000 0067
060 CD 0A99 0000 LED10 = 红色
061 FZ 0000 000F
062 ZY 0000 0067
063 CD 0B99 0000 LED11 = 红色
064 FZ 0000 000F
065 ZY 0000 0067
--- 中间步数字输出 (066-080) ---
066 FZ 0000 000F R00 = 中间步(位置不变时走这里)
067 06 0000 0076 中间步=0:全灭
068 06 0001 0078 中间步=1:亮1颗
069 06 0002 007A 中间步=2:亮2颗
06A 06 0003 007C 中间步=3:亮3颗
06B 06 0004 007E 中间步=4:亮4颗
06C ZY 0000 007F 默认(不应到达)
076 FZ 0010 0000 R10 = 00(全灭)
077 ZY 0000 007F
078 FZ 0010 0010 R10 = 10(IO4亮)
079 ZY 0000 007F
07A FZ 0010 0030 R10 = 30(IO4-5亮)
07B ZY 0000 007F
07C FZ 0010 0070 R10 = 70(IO4-6亮)
07D ZY 0000 007F
07E FZ 0010 00F0 R10 = F0(IO4-7全亮)
07F SC 0010 0000 输出R10到数字端口
080 FH 0000 0000 返回
000 10 000B 0005
001 10 0009 0000
002 10 000D 00FF
010 11 0000 0009
011 04 003B 0017
012 0C 0020 0000
013 12 0009 0001
014 02 03E8 0000
015 0E 0000 0010
017 10 0009 0000
018 0E 0000 0012
020 11 0000 0009
021 1D 0000 000B
022 11 000C 0000
023 11 0000 0009
024 1E 0000 000B
025 11 000F 0000
026 11 0000 000D
027 09 000C 0066
028 11 000D 000C
029 E4 0000 0000
02A E4 0100 0000
02B E4 0200 0000
02C E4 0300 0000
02D E4 0400 0000
02E E4 0500 0000
02F E4 0600 0000
030 E4 0700 0000
031 E4 0800 0000
032 E4 0900 0000
033 E4 0A00 0000
034 E4 0B00 0000
035 11 0000 000C
036 06 0000 0042
037 06 0001 0045
038 06 0002 0048
039 06 0003 004B
03A 06 0004 004E
03B 06 0005 0051
03C 06 0006 0054
03D 06 0007 0057
03E 06 0008 005A
03F 06 0009 005D
040 06 000A 0060
041 06 000B 0063
042 E4 0099 0000
043 11 0000 000F
044 0E 0000 0067
045 E4 0199 0000
046 11 0000 000F
047 0E 0000 0067
048 E4 0299 0000
049 11 0000 000F
04A 0E 0000 0067
04B E4 0399 0000
04C 11 0000 000F
04D 0E 0000 0067
04E E4 0499 0000
04F 11 0000 000F
050 0E 0000 0067
051 E4 0599 0000
052 11 0000 000F
053 0E 0000 0067
054 E4 0699 0000
055 11 0000 000F
056 0E 0000 0067
057 E4 0799 0000
058 11 0000 000F
059 0E 0000 0067
05A E4 0899 0000
05B 11 0000 000F
05C 0E 0000 0067
05D E4 0999 0000
05E 11 0000 000F
05F 0E 0000 0067
060 E4 0A99 0000
061 11 0000 000F
062 0E 0000 0067
063 E4 0B99 0000
064 11 0000 000F
065 0E 0000 0067
066 11 0000 000F
067 06 0000 0076
068 06 0001 0078
069 06 0002 007A
06A 06 0003 007C
06B 06 0004 007E
06C 0E 0000 007F
076 10 0010 0000
077 0E 0000 007F
078 10 0010 0010
079 0E 0000 007F
07A 10 0010 0030
07B 0E 0000 007F
07C 10 0010 0070
07D 0E 0000 007F
07E 10 0010 00F0
07F 13 0010 0000
080 0D 0000 0000
代码量:99行指令(远在256行限制内)
防闪烁机制:R0D跟踪上次的LED位置。每次渲染时:
- 如果位置不变(5秒中的4秒):直接跳到数字输出(066行),跳过LED熄灭+重新点亮
- 如果位置变化(每5秒):熄灭所有LED,点亮新位置,更新R0D
设置初始时间:修改 001 行可改变R09初始值(0-59)。例:001 10 0009 002D 设置秒数为45。
模式切换时钟Demo(第二步:秒/分/小时切换)
参见上方第一步的基础防闪烁秒针模式。此模式切换版本在此基础上扩展为三态切换:
- 按钮(R3F):按下时循环切换 R14:0(显示秒)→ 1(显示分)→ 2(显示小时)→ 0
- R13释放标志:防止按钮按住时重复触发切换
- 模式切换时R0D重置:强制LED用新颜色重绘
- 三个渲染子程序:防闪烁结构相同,红色显示秒,绿色显示分,蓝色显示小时
- 持续计数:无论显示模式如何,R09(秒)、R0A(分)、R0B(小时)都在后台持续递增
按钮检测流程:
R3F==0 → 设置R13=0(准备按下)
R3F==1 AND R13==0 → R14+=1,若R14==3则重置为0,设置R13=1,设置R0D=255(强制重绘)
R3F==1 AND R13==1 → 什么都不做(已处理本次按下)
颜色选择:
若R14==0 → 调用红色渲染(R09用于位置/子步,LED颜色:红色)
若R14==1 → 调用绿色渲染(R0A用于位置/子步,LED颜色:绿色)
若R14==2 → 调用蓝色渲染(R0B直接作为位置,分针/12作为子步,LED颜色:蓝色)
时针特殊处理:小时范围是0-11(不需要除以5计算位置)。子步由分针推导:0-11分=子步0,12-23分=子步1,24-35分=子步2,36-47分=子步3,48-59分=子步4。
寄存器映射:
| 寄存器 | 用途 |
|---|---|
| R00 | 临时/比较 |
| R09 | 秒 (0-59) |
| R0A | 分 (0-59) |
| R0B | 小时 (0-11) |
| R0C | 当前LED位置 (0-11) |
| R0D | 上一次位置(防闪烁) |
| R0F | 子步 (0-4) |
| R10 | 数字IO输出值 |
| R13 | 按钮释放标志 |
| R14 | 显示模式 (0=秒/红, 1=分/绿, 2=小时/蓝) |
总行数:约 384 行(远低于 512 行上限)
完整指令代码(主循环)
000 10 000B 0005 R0B = 5(秒/分位置计算的除数)
001 10 0009 0000 R09 = 0(秒)
002 10 000A 0000 R0A = 0(分)
003 10 000D 00FF R0D = 255(上一次位置,强制初始重绘)
004 10 0014 0000 R14 = 0(模式:显示秒)
005 10 0013 0000 R13 = 0(按钮释放标志)
=== 按钮检测(010-01F):循环切换模式 0→1→2→0 ===
010 11 0000 003F R00 = R3F(按钮状态)
011 09 0001 0014 若R00==1:跳转至014(按钮被按下)
012 10 0013 0000 R13 = 0(按钮释放,重置标志)
013 0E 0000 0020 跳转至模式选择
014 11 0000 0013 R00 = R13(检查释放标志)
015 09 0000 0017 若R00==0:跳转至017(现在切换模式)
016 0E 0000 0020 跳转至模式选择(本次按下已处理)
017 12 0014 0001 R14 += 1(切换至下一模式)
018 11 0000 0014 R00 = R14(检查模式是否==3)
019 09 0003 001B 若R00==3:跳转至01B(重置模式为0)
01A 0E 0000 001C 跳转至设置释放标志
01B 10 0014 0000 R14 = 0(重置为模式0)
01C 10 0013 0001 R13 = 1(设置释放标志,防止重复触发)
01D 10 000D 00FF R0D = 255(强制LED用新颜色重绘)
=== 模式选择(020-02F):路由至正确的颜色渲染器 ===
020 11 0000 0014 R00 = R14
021 09 0001 0026 若R00==1:跳转至绿色(分钟)
022 09 0002 0029 若R00==2:跳转至蓝色(小时)
--- 模式0:红色秒针 ---
023 11 0000 0009 R00 = R09(秒用于边界检查)
024 04 003B 002B 若R00>59:跳过(不应发生)
025 0C 0040 0000 调用红色秒针渲染(050附近)
026 0E 0000 0030 跳转至计数
--- 模式1:绿色分针 ---
027 11 0000 000A R00 = R0A(分用于边界检查)
028 0C 00A0 0000 调用绿色分针渲染(0A0附近)
029 0E 0000 0030 跳转至计数
--- 模式2:蓝色时针 ---
02A 0C 0100 0000 调用蓝色时针渲染(100附近)
02B 0E 0000 0030 跳转至计数
=== 计数(030-042):时间递增 ===
030 12 0009 0001 秒 += 1
031 11 0000 0009 R00 = R09
032 09 003C 0034 若R00==60:跳转至分递增
033 0E 0000 0038 跳转至延时
034 10 0009 0000 R09 = 0(秒归零)
035 12 000A 0001 分 += 1
036 11 0000 000A R00 = R0A
037 09 003C 0039 若R00==60:跳转至小时递增
038 02 03E8 0000 延时1秒
039 0E 0000 0010 循环回到按钮检测
03A 10 000A 0000 R0A = 0(分归零)
03B 12 000B 0001 小时 += 1
03C 11 0000 000B R00 = R0B
03D 09 000C 003F 若R00==12:跳转至小时归零
03E 02 03E8 0000 延时1秒
03F 0E 0000 0010 循环回到
040 10 000B 0000 R0B = 0(小时归零)
041 02 03E8 0000 延时1秒
042 0E 0000 0010 循环回到
红色秒针渲染子程序(050-0B7):R09/5为位置,R09%5为子步。LED颜色=红色(E4 xx99 0000)。
绿色分针渲染子程序(0C0-127):R0A/5为位置,R0A%5为子步。LED颜色=绿色(E4 0000 9900)。
蓝色时针渲染子程序(130-197):位置=R0B直接(0-11,不需要/5)。子步通过比较R0A与12/24/36/48阈值得到。LED颜色=蓝色(E4 0000 0099)。
五色流水灯(12 位置 LED)
12 个 WS2812B LED 按时钟位置排列,依次展示 5 种颜色的流水灯效果。每种颜色从 LED00 到 LED0B 逐个点亮,全部亮起后保持片刻,然后全部熄灭,进入下一个颜色。颜色顺序:白色 → 红色 → 黄色 → 绿色 → 蓝色。每个颜色分量最大值为 0x33,确保不会太亮。
核心指令:FZ (10) 初始化 · CD (E4) 点亮/熄灭 LED · YS (02) 延时 · DY (0C) 调用子程序 · FH (0D) 返回 · ZY (0E) 无条件跳转
颜色参数(CD 指令格式:CD LED_ID+R G+B):
| 颜色 | R | G | B | CD 参数示例(LED00) |
|---|---|---|---|---|
| 白色 | 33 | 33 | 33 | CD 0033 3333 |
| 红色 | 33 | 00 | 00 | CD 0033 0000 |
| 黄色 | 33 | 33 | 00 | CD 0033 3300 |
| 绿色 | 00 | 33 | 00 | CD 0000 3300 |
| 蓝色 | 00 | 00 | 33 | CD 0000 0033 |
| 熄灭 | 00 | 00 | 00 | CD 0000 0000 |
点击展开/折叠 五色流水灯完整代码
- 助记符形式
- 指令形式
000 FZ 0001 0000 R01 = 0,常量
001 FZ 0002 0001 R02 = 1,常量
============= 主循环 =============
010 DY 0020 0000 调用白色流水子程序
011 DY 0040 0000 调用红色流水子程序
012 DY 0060 0000 调用黄色流水子程序
013 DY 0080 0000 调用绿色流水子程序
014 DY 00A0 0000 调用蓝色流水子程序
015 ZY 0000 0010 跳回 010,循环
========== 白色流水 (020-039) ==========
020 CD 0033 3333 LED00 白色
021 YS 0080 0000 延时
022 CD 0133 3333 LED01 白色
023 YS 0080 0000 延时
024 CD 0233 3333 LED02 白色
025 YS 0080 0000 延时
026 CD 0333 3333 LED03 白色
027 YS 0080 0000 延时
028 CD 0433 3333 LED04 白色
029 YS 0080 0000 延时
02A CD 0533 3333 LED05 白色
02B YS 0080 0000 延时
02C CD 0633 3333 LED06 白色
02D YS 0080 0000 延时
02E CD 0733 3333 LED07 白色
02F YS 0080 0000 延时
030 CD 0833 3333 LED08 白色
031 YS 0080 0000 延时
032 CD 0933 3333 LED09 白色
033 YS 0080 0000 延时
034 CD 0A33 3333 LED0A 白色
035 YS 0080 0000 延时
036 CD 0B33 3333 LED0B 白色
037 YS 0200 0000 全部点亮后保持一段时间
038 DY 00C0 0000 调用全部熄灭子程序
039 FH 0000 0000 返回
========== 红色流水 (040-059) ==========
040 CD 0033 0000 LED00 红色
041 YS 0080 0000 延时
042 CD 0133 0000 LED01 红色
043 YS 0080 0000 延时
044 CD 0233 0000 LED02 红色
045 YS 0080 0000 延时
046 CD 0333 0000 LED03 红色
047 YS 0080 0000 延时
048 CD 0433 0000 LED04 红色
049 YS 0080 0000 延时
04A CD 0533 0000 LED05 红色
04B YS 0080 0000 延时
04C CD 0633 0000 LED06 红色
04D YS 0080 0000 延时
04E CD 0733 0000 LED07 红色
04F YS 0080 0000 延时
050 CD 0833 0000 LED08 红色
051 YS 0080 0000 延时
052 CD 0933 0000 LED09 红色
053 YS 0080 0000 延时
054 CD 0A33 0000 LED0A 红色
055 YS 0080 0000 延时
056 CD 0B33 0000 LED0B 红色
057 YS 0200 0000 全部点亮后保持一段时间
058 DY 00C0 0000 调用全部熄灭子程序
059 FH 0000 0000 返回
========== 黄色流水 (060-079) ==========
060 CD 0033 3300 LED00 黄色
061 YS 0080 0000 延时
062 CD 0133 3300 LED01 黄色
063 YS 0080 0000 延时
064 CD 0233 3300 LED02 黄色
065 YS 0080 0000 延时
066 CD 0333 3300 LED03 黄色
067 YS 0080 0000 延时
068 CD 0433 3300 LED04 黄色
069 YS 0080 0000 延时
06A CD 0533 3300 LED05 黄色
06B YS 0080 0000 延时
06C CD 0633 3300 LED06 黄色
06D YS 0080 0000 延时
06E CD 0733 3300 LED07 黄色
06F YS 0080 0000 延时
070 CD 0833 3300 LED08 黄色
071 YS 0080 0000 延时
072 CD 0933 3300 LED09 黄色
073 YS 0080 0000 延时
074 CD 0A33 3300 LED0A 黄色
075 YS 0080 0000 延时
076 CD 0B33 3300 LED0B 黄色
077 YS 0200 0000 全部点亮后保持一段时间
078 DY 00C0 0000 调用全部熄灭子程序
079 FH 0000 0000 返回
========== 绿色流水 (080-099) ==========
080 CD 0000 3300 LED00 绿色
081 YS 0080 0000 延时
082 CD 0100 3300 LED01 绿色
083 YS 0080 0000 延时
084 CD 0200 3300 LED02 绿色
085 YS 0080 0000 延时
086 CD 0300 3300 LED03 绿色
087 YS 0080 0000 延时
088 CD 0400 3300 LED04 绿色
089 YS 0080 0000 延时
08A CD 0500 3300 LED05 绿色
08B YS 0080 0000 延时
08C CD 0600 3300 LED06 绿色
08D YS 0080 0000 延时
08E CD 0700 3300 LED07 绿色
08F YS 0080 0000 延时
090 CD 0800 3300 LED08 绿色
091 YS 0080 0000 延时
092 CD 0900 3300 LED09 绿色
093 YS 0080 0000 延时
094 CD 0A00 3300 LED0A 绿色
095 YS 0080 0000 延时
096 CD 0B00 3300 LED0B 绿色
097 YS 0200 0000 全部点亮后保持一段时间
098 DY 00C0 0000 调用全部熄灭子程序
099 FH 0000 0000 返回
========== 蓝色流水 (0A0-0B9) ==========
0A0 CD 0000 0033 LED00 蓝色
0A1 YS 0080 0000 延时
0A2 CD 0100 0033 LED01 蓝色
0A3 YS 0080 0000 延时
0A4 CD 0200 0033 LED02 蓝色
0A5 YS 0080 0000 延时
0A6 CD 0300 0033 LED03 蓝色
0A7 YS 0080 0000 延时
0A8 CD 0400 0033 LED04 蓝色
0A9 YS 0080 0000 延时
0AA CD 0500 0033 LED05 蓝色
0AB YS 0080 0000 延时
0AC CD 0600 0033 LED06 蓝色
0AD YS 0080 0000 延时
0AE CD 0700 0033 LED07 蓝色
0AF YS 0080 0000 延时
0B0 CD 0800 0033 LED08 蓝色
0B1 YS 0080 0000 延时
0B2 CD 0900 0033 LED09 蓝色
0B3 YS 0080 0000 延时
0B4 CD 0A00 0033 LED0A 蓝色
0B5 YS 0080 0000 延时
0B6 CD 0B00 0033 LED0B 蓝色
0B7 YS 0200 0000 全部点亮后保持一段时间
0B8 DY 00C0 0000 调用全部熄灭子程序
0B9 FH 0000 0000 返回
========== 全部熄灭子程序 (0C0-0CC) ==========
0C0 CD 0000 0000 LED00 熄灭
0C1 CD 0100 0000 LED01 熄灭
0C2 CD 0200 0000 LED02 熄灭
0C3 CD 0300 0000 LED03 熄灭
0C4 CD 0400 0000 LED04 熄灭
0C5 CD 0500 0000 LED05 熄灭
0C6 CD 0600 0000 LED06 熄灭
0C7 CD 0700 0000 LED07 熄灭
0C8 CD 0800 0000 LED08 熄灭
0C9 CD 0900 0000 LED09 熄灭
0CA CD 0A00 0000 LED0A 熄灭
0CB CD 0B00 0000 LED0B 熄灭
0CC FH 0000 0000 返回
000 10 0001 0000
001 10 0002 0001
010 0C 0020 0000
011 0C 0040 0000
012 0C 0060 0000
013 0C 0080 0000
014 0C 00A0 0000
015 0E 0000 0010
020 E4 0033 3333
021 02 0080 0000
022 E4 0133 3333
023 02 0080 0000
024 E4 0233 3333
025 02 0080 0000
026 E4 0333 3333
027 02 0080 0000
028 E4 0433 3333
029 02 0080 0000
02A E4 0533 3333
02B 02 0080 0000
02C E4 0633 3333
02D 02 0080 0000
02E E4 0733 3333
02F 02 0080 0000
030 E4 0833 3333
031 02 0080 0000
032 E4 0933 3333
033 02 0080 0000
034 E4 0A33 3333
035 02 0080 0000
036 E4 0B33 3333
037 02 0200 0000
038 0C 00C0 0000
039 0D 0000 0000
040 E4 0033 0000
041 02 0080 0000
042 E4 0133 0000
043 02 0080 0000
044 E4 0233 0000
045 02 0080 0000
046 E4 0333 0000
047 02 0080 0000
048 E4 0433 0000
049 02 0080 0000
04A E4 0533 0000
04B 02 0080 0000
04C E4 0633 0000
04D 02 0080 0000
04E E4 0733 0000
04F 02 0080 0000
050 E4 0833 0000
051 02 0080 0000
052 E4 0933 0000
053 02 0080 0000
054 E4 0A33 0000
055 02 0080 0000
056 E4 0B33 0000
057 02 0200 0000
058 0C 00C0 0000
059 0D 0000 0000
060 E4 0033 3300
061 02 0080 0000
062 E4 0133 3300
063 02 0080 0000
064 E4 0233 3300
065 02 0080 0000
066 E4 0333 3300
067 02 0080 0000
068 E4 0433 3300
069 02 0080 0000
06A E4 0533 3300
06B 02 0080 0000
06C E4 0633 3300
06D 02 0080 0000
06E E4 0733 3300
06F 02 0080 0000
070 E4 0833 3300
071 02 0080 0000
072 E4 0933 3300
073 02 0080 0000
074 E4 0A33 3300
075 02 0080 0000
076 E4 0B33 3300
077 02 0200 0000
078 0C 00C0 0000
079 0D 0000 0000
080 E4 0000 3300
081 02 0080 0000
082 E4 0100 3300
083 02 0080 0000
084 E4 0200 3300
085 02 0080 0000
086 E4 0300 3300
087 02 0080 0000
088 E4 0400 3300
089 02 0080 0000
08A E4 0500 3300
08B 02 0080 0000
08C E4 0600 3300
08D 02 0080 0000
08E E4 0700 3300
08F 02 0080 0000
090 E4 0800 3300
091 02 0080 0000
092 E4 0900 3300
093 02 0080 0000
094 E4 0A00 3300
095 02 0080 0000
096 E4 0B00 3300
097 02 0200 0000
098 0C 00C0 0000
099 0D 0000 0000
0A0 E4 0000 0033
0A1 02 0080 0000
0A2 E4 0100 0033
0A3 02 0080 0000
0A4 E4 0200 0033
0A5 02 0080 0000
0A6 E4 0300 0033
0A7 02 0080 0000
0A8 E4 0400 0033
0A9 02 0080 0000
0AA E4 0500 0033
0AB 02 0080 0000
0AC E4 0600 0033
0AD 02 0080 0000
0AE E4 0700 0033
0AF 02 0080 0000
0B0 E4 0800 0033
0B1 02 0080 0000
0B2 E4 0900 0033
0B3 02 0080 0000
0B4 E4 0A00 0033
0B5 02 0080 0000
0B6 E4 0B00 0033
0B7 02 0200 0000
0B8 0C 00C0 0000
0B9 0D 0000 0000
0C0 E4 0000 0000
0C1 E4 0100 0000
0C2 E4 0200 0000
0C3 E4 0300 0000
0C4 E4 0400 0000
0C5 E4 0500 0000
0C6 E4 0600 0000
0C7 E4 0700 0000
0C8 E4 0800 0000
0C9 E4 0900 0000
0CA E4 0A00 0000
0CB E4 0B00 0000
0CC 0D 0000 0000
寄存器初始化(000-001)
| 行号 | 指令 | 说明 |
|---|---|---|
| 000 | FZ 0001 0000 | R01 = 0,常量 |
| 001 | FZ 0002 0001 | R02 = 1,常量 |
主循环(010-015)
| 行号 | 指令 | 说明 |
|---|---|---|
| 010 | DY 0020 0000 | 调用 020 行白色流水子程序 |
| 011 | DY 0040 0000 | 调用 040 行红色流水子程序 |
| 012 | DY 0060 0000 | 调用 060 行黄色流水子程序 |
| 013 | DY 0080 0000 | 调用 080 行绿色流水子程序 |
| 014 | DY 00A0 0000 | 调用 0A0 行蓝色流水子程序 |
| 015 | ZY 0000 0010 | 跳回 010 行,无限循环 |
白色流水(020-039)
| 行号 | 指令 | 说明 |
|---|---|---|
| 020 | CD 0033 3333 | LED00 白色(R=33, G=33, B=33) |
| 021 | YS 0080 0000 | 延时,让流水效果可见 |
| 022-036 | CD LED33 3333 + YS | LED01-LED0B 依次点亮白色,每步延时 |
| 037 | YS 0200 0000 | 12 个 LED 全部点亮后保持较长时间 |
| 038 | DY 00C0 0000 | 调用 0C0 行全部熄灭子程序 |
| 039 | FH 0000 0000 | 白色流水完成,返回主循环 |
红色流水(040-059)
| 行号 | 指令 | 说明 |
|---|---|---|
| 040 | CD 0033 0000 | LED00 红色(R=33, G=00, B=00) |
| 041 | YS 0080 0000 | 延时 |
| 042-056 | CD LED33 0000 + YS | LED01-LED0B 依次点亮红色,每步延时 |
| 057 | YS 0200 0000 | 全部点亮后保持 |
| 058 | DY 00C0 0000 | 调用全部熄灭 |
| 059 | FH 0000 0000 | 返回 |
黄色流水(060-079)
| 行号 | 指令 | 说明 |
|---|---|---|
| 060 | CD 0033 3300 | LED00 黄色(R=33, G=33, B=00) |
| 061 | YS 0080 0000 | 延时 |
| 062-076 | CD LED33 3300 + YS | LED01-LED0B 依次点亮黄色,每步延时 |
| 077 | YS 0200 0000 | 全部点亮后保持 |
| 078 | DY 00C0 0000 | 调用全部熄灭 |
| 079 | FH 0000 0000 | 返回 |
绿色流水(080-099)
| 行号 | 指令 | 说明 |
|---|---|---|
| 080 | CD 0000 3300 | LED00 绿色(R=00, G=33, B=00) |
| 081 | YS 0080 0000 | 延时 |
| 082-096 | CD LED00 3300 + YS | LED01-LED0B 依次点亮绿色,每步延时 |
| 097 | YS 0200 0000 | 全部点亮后保持 |
| 098 | DY 00C0 0000 | 调用全部熄灭 |
| 099 | FH 0000 0000 | 返回 |
蓝色流水(0A0-0B9)
| 行号 | 指令 | 说明 |
|---|---|---|
| 0A0 | CD 0000 0033 | LED00 蓝色(R=00, G=00, B=33) |
| 0A1 | YS 0080 0000 | 延时 |
| 0A2-0B6 | CD LED00 0033 + YS | LED01-LED0B 依次点亮蓝色,每步延时 |
| 0B7 | YS 0200 0000 | 全部点亮后保持 |
| 0B8 | DY 00C0 0000 | 调用全部熄灭 |
| 0B9 | FH 0000 0000 | 返回 |
全部熄灭子程序(0C0-0CC)
| 行号 | 指令 | 说明 |
|---|---|---|
| 0C0 | CD 0000 0000 | LED00 熄灭 |
| 0C1 | CD 0100 0000 | LED01 熄灭 |
| 0C2 | CD 0200 0000 | LED02 熄灭 |
| 0C3 | CD 0300 0000 | LED03 熄灭 |
| 0C4 | CD 0400 0000 | LED04 熄灭 |
| 0C5 | CD 0500 0000 | LED05 熄灭 |
| 0C6 | CD 0600 0000 | LED06 熄灭 |
| 0C7 | CD 0700 0000 | LED07 熄灭 |
| 0C8 | CD 0800 0000 | LED08 熄灭 |
| 0C9 | CD 0900 0000 | LED09 熄灭 |
| 0CA | CD 0A00 0000 | LED0A 熄灭 |
| 0CB | CD 0B00 0000 | LED0B 熄灭 |
| 0CC | FH 0000 0000 | 全部熄灭完成,返回 |
五色流水灯(E5指令优化版)
使用 E5 指令一次性熄灭所有LED:本案例在原有五色流水灯的基础上,用 E5 指令替代原来的 12 条逐个熄灭指令。E4 指令用于逐个点亮LED保持流水效果,而 E5 指令利用寄存器中的RGB值一次性设置多个LED,将熄灭操作从 12 条指令简化为 1 条。
核心指令:FZ (10) 初始化寄存器 · E4 设置单个LED颜色 · E5 通过寄存器批量设置LED颜色 · YS (02) 延时 · DY (0C) 调用子程序 · FH (0D) 返回 · ZY (0E) 无条件跳转
E5 指令详解:
| 参数 | 值 | 说明 |
|---|---|---|
| OP00 | 03 | 起始寄存器编号(使用 R03、R04、R05) |
| OP01 | 01 | 00 = 使用低八位,01 = 使用高八位 |
| OP10 | 00 | 起始LED编号 |
| OP11 | 0C | LED数量(0C = 12) |
格式:E5 OP00+OP01 OP10+OP11 → 示例:E5 0301 000C(使用 R03-R05 高八位,设置 LED00-LED11)
寄存器规划:
| 寄存器 | 用途 |
|---|---|
| R00-R02 | 当前颜色值(运行时更新) |
| R03-R05 | 全0值(用于熄灭) |
点击展开/折叠 E5指令优化版 完整代码
- 助记符形式
- 指令形式
000 FZ 0000 0000 R00 = 0000 (颜色R值 - 运行时更新)
001 FZ 0001 0000 R01 = 0000 (颜色G值 - 运行时更新)
002 FZ 0002 0000 R02 = 0000 (颜色B值 - 运行时更新)
003 FZ 0003 0000 R03 = 0000 (熄灭用 R=00)
004 FZ 0004 0000 R04 = 0000 (熄灭用 G=00)
005 FZ 0005 0000 R05 = 0000 (熄灭用 B=00)
============= 主循环 =============
010 DY 0020 0000 调用白色流水子程序
011 DY 0040 0000 调用红色流水子程序
012 DY 0060 0000 调用黄色流水子程序
013 DY 0080 0000 调用绿色流水子程序
014 DY 00A0 0000 调用蓝色流水子程序
015 ZY 0000 0010 跳回 010,无限循环
========== 白色流水 (020-03D) ==========
020 FZ 0000 3333 R00 = 3333 (白色 R=33)
021 FZ 0001 3333 R01 = 3333 (白色 G=33)
022 FZ 0002 3333 R02 = 3333 (白色 B=33)
023 E4 0033 3333 LED00 白色
024 YS 0080 0000 延时
025 E4 0133 3333 LED01 白色
026 YS 0080 0000 延时
027 E4 0233 3333 LED02 白色
028 YS 0080 0000 延时
029 E4 0333 3333 LED03 白色
02A YS 0080 0000 延时
02B E4 0433 3333 LED04 白色
02C YS 0080 0000 延时
02D E4 0533 3333 LED05 白色
02E YS 0080 0000 延时
02F E4 0633 3333 LED06 白色
030 YS 0080 0000 延时
031 E4 0733 3333 LED07 白色
032 YS 0080 0000 延时
033 E4 0833 3333 LED08 白色
034 YS 0080 0000 延时
035 E4 0933 3333 LED09 白色
036 YS 0080 0000 延时
037 E4 0A33 3333 LED0A 白色
038 YS 0080 0000 延时
039 E4 0B33 3333 LED0B 白色
03A YS 0200 0000 全部点亮后保持一段时间
03B E5 0301 000C 用R03-R05(全0)一次性熄灭12个LED (OP00=03, OP01=01高八位, OP10=00起始LED, OP11=0C共12个)
03C YS 0080 0000 熄灭后短暂停顿
03D FH 0000 0000 白色流水完成,返回
========== 红色流水 (040-05D) ==========
040 FZ 0000 3300 R00 = 3300 (红色 R=33)
041 FZ 0001 0000 R01 = 0000 (红色 G=00)
042 FZ 0002 0000 R02 = 0000 (红色 B=00)
043 E4 0033 0000 LED00 红色
044 YS 0080 0000 延时
045 E4 0133 0000 LED01 红色
046 YS 0080 0000 延时
047 E4 0233 0000 LED02 红色
048 YS 0080 0000 延时
049 E4 0333 0000 LED03 红色
04A YS 0080 0000 延时
04B E4 0433 0000 LED04 红色
04C YS 0080 0000 延时
04D E4 0533 0000 LED05 红色
04E YS 0080 0000 延时
04F E4 0633 0000 LED06 红色
050 YS 0080 0000 延时
051 E4 0733 0000 LED07 红色
052 YS 0080 0000 延时
053 E4 0833 0000 LED08 红色
054 YS 0080 0000 延时
055 E4 0933 0000 LED09 红色
056 YS 0080 0000 延时
057 E4 0A33 0000 LED0A 红色
058 YS 0080 0000 延时
059 E4 0B33 0000 LED0B 红色
05A YS 0200 0000 全部点亮后保持
05B E5 0301 000C 一次性熄灭所有LED
05C YS 0080 0000 停顿
05D FH 0000 0000 返回
========== 黄色流水 (060-07D) ==========
060 FZ 0000 3300 R00 = 3300 (黄色 R=33)
061 FZ 0001 3300 R01 = 3300 (黄色 G=33)
062 FZ 0002 0000 R02 = 0000 (黄色 B=00)
063 E4 0033 3300 LED00 黄色
064 YS 0080 0000 延时
065 E4 0133 3300 LED01 黄色
066 YS 0080 0000 延时
067 E4 0233 3300 LED02 黄色
068 YS 0080 0000 延时
069 E4 0333 3300 LED03 黄色
06A YS 0080 0000 延时
06B E4 0433 3300 LED04 黄色
06C YS 0080 0000 延时
06D E4 0533 3300 LED05 黄色
06E YS 0080 0000 延时
06F E4 0633 3300 LED06 黄色
070 YS 0080 0000 延时
071 E4 0733 3300 LED07 黄色
072 YS 0080 0000 延时
073 E4 0833 3300 LED08 黄色
074 YS 0080 0000 延时
075 E4 0933 3300 LED09 黄色
076 YS 0080 0000 延时
077 E4 0A33 3300 LED0A 黄色
078 YS 0080 0000 延时
079 E4 0B33 3300 LED0B 黄色
07A YS 0200 0000 全部点亮后保持
07B E5 0301 000C 一次性熄灭所有LED
07C YS 0080 0000 停顿
07D FH 0000 0000 返回
========== 绿色流水 (080-09D) ==========
080 FZ 0000 0000 R00 = 0000 (绿色 R=00)
081 FZ 0001 3300 R01 = 3300 (绿色 G=33)
082 FZ 0002 0000 R02 = 0000 (绿色 B=00)
083 E4 0000 3300 LED00 绿色
084 YS 0080 0000 延时
085 E4 0100 3300 LED01 绿色
086 YS 0080 0000 延时
087 E4 0200 3300 LED02 绿色
088 YS 0080 0000 延时
089 E4 0300 3300 LED03 绿色
08A YS 0080 0000 延时
08B E4 0400 3300 LED04 绿色
08C YS 0080 0000 延时
08D E4 0500 3300 LED05 绿色
08E YS 0080 0000 延时
08F E4 0600 3300 LED06 绿色
090 YS 0080 0000 延时
091 E4 0700 3300 LED07 绿色
092 YS 0080 0000 延时
093 E4 0800 3300 LED08 绿色
094 YS 0080 0000 延时
095 E4 0900 3300 LED09 绿色
096 YS 0080 0000 延时
097 E4 0A00 3300 LED0A 绿色
098 YS 0080 0000 延时
099 E4 0B00 3300 LED0B 绿色
09A YS 0200 0000 全部点亮后保持
09B E5 0301 000C 一次性熄灭所有LED
09C YS 0080 0000 停顿
09D FH 0000 0000 返回
========== 蓝色流水 (0A0-0BD) ==========
0A0 FZ 0000 0000 R00 = 0000 (蓝色 R=00)
0A1 FZ 0001 0000 R01 = 0000 (蓝色 G=00)
0A2 FZ 0002 3300 R02 = 3300 (蓝色 B=33)
0A3 E4 0000 0033 LED00 蓝色
0A4 YS 0080 0000 延时
0A5 E4 0100 0033 LED01 蓝色
0A6 YS 0080 0000 延时
0A7 E4 0200 0033 LED02 蓝色
0A8 YS 0080 0000 延时
0A9 E4 0300 0033 LED03 蓝色
0AA YS 0080 0000 延时
0AB E4 0400 0033 LED04 蓝色
0AC YS 0080 0000 延时
0AD E4 0500 0033 LED05 蓝色
0AE YS 0080 0000 延时
0AF E4 0600 0033 LED06 蓝色
0B0 YS 0080 0000 延时
0B1 E4 0700 0033 LED07 蓝色
0B2 YS 0080 0000 延时
0B3 E4 0800 0033 LED08 蓝色
0B4 YS 0080 0000 延时
0B5 E4 0900 0033 LED09 蓝色
0B6 YS 0080 0000 延时
0B7 E4 0A00 0033 LED0A 蓝色
0B8 YS 0080 0000 延时
0B9 E4 0B00 0033 LED0B 蓝色
0BA YS 0200 0000 全部点亮后保持
0BB E5 0301 000C 一次性熄灭所有LED
0BC YS 0080 0000 停顿
0BD FH 0000 0000 返回
000 10 0000 0000
001 10 0001 0000
002 10 0002 0000
003 10 0003 0000
004 10 0004 0000
005 10 0005 0000
010 0C 0020 0000
011 0C 0040 0000
012 0C 0060 0000
013 0C 0080 0000
014 0C 00A0 0000
015 0E 0000 0010
020 10 0000 3333
021 10 0001 3333
022 10 0002 3333
023 E4 0033 3333
024 02 0080 0000
025 E4 0133 3333
026 02 0080 0000
027 E4 0233 3333
028 02 0080 0000
029 E4 0333 3333
02A 02 0080 0000
02B E4 0433 3333
02C 02 0080 0000
02D E4 0533 3333
02E 02 0080 0000
02F E4 0633 3333
030 02 0080 0000
031 E4 0733 3333
032 02 0080 0000
033 E4 0833 3333
034 02 0080 0000
035 E4 0933 3333
036 02 0080 0000
037 E4 0A33 3333
038 02 0080 0000
039 E4 0B33 3333
03A 02 0200 0000
03B E5 0301 000C
03C 02 0080 0000
03D 0D 0000 0000
040 10 0000 3300
041 10 0001 0000
042 10 0002 0000
043 E4 0033 0000
044 02 0080 0000
045 E4 0133 0000
046 02 0080 0000
047 E4 0233 0000
048 02 0080 0000
049 E4 0333 0000
04A 02 0080 0000
04B E4 0433 0000
04C 02 0080 0000
04D E4 0533 0000
04E 02 0080 0000
04F E4 0633 0000
050 02 0080 0000
051 E4 0733 0000
052 02 0080 0000
053 E4 0833 0000
054 02 0080 0000
055 E4 0933 0000
056 02 0080 0000
057 E4 0A33 0000
058 02 0080 0000
059 E4 0B33 0000
05A 02 0200 0000
05B E5 0301 000C
05C 02 0080 0000
05D 0D 0000 0000
060 10 0000 3300
061 10 0001 3300
062 10 0002 0000
063 E4 0033 3300
064 02 0080 0000
065 E4 0133 3300
066 02 0080 0000
067 E4 0233 3300
068 02 0080 0000
069 E4 0333 3300
06A 02 0080 0000
06B E4 0433 3300
06C 02 0080 0000
06D E4 0533 3300
06E 02 0080 0000
06F E4 0633 3300
070 02 0080 0000
071 E4 0733 3300
072 02 0080 0000
073 E4 0833 3300
074 02 0080 0000
075 E4 0933 3300
076 02 0080 0000
077 E4 0A33 3300
078 02 0080 0000
079 E4 0B33 3300
07A 02 0200 0000
07B E5 0301 000C
07C 02 0080 0000
07D 0D 0000 0000
080 10 0000 0000
081 10 0001 3300
082 10 0002 0000
083 E4 0000 3300
084 02 0080 0000
085 E4 0100 3300
086 02 0080 0000
087 E4 0200 3300
088 02 0080 0000
089 E4 0300 3300
08A 02 0080 0000
08B E4 0400 3300
08C 02 0080 0000
08D E4 0500 3300
08E 02 0080 0000
08F E4 0600 3300
090 02 0080 0000
091 E4 0700 3300
092 02 0080 0000
093 E4 0800 3300
094 02 0080 0000
095 E4 0900 3300
096 02 0080 0000
097 E4 0A00 3300
098 02 0080 0000
099 E4 0B00 3300
09A 02 0200 0000
09B E5 0301 000C
09C 02 0080 0000
09D 0D 0000 0000
0A0 10 0000 0000
0A1 10 0001 0000
0A2 10 0002 3300
0A3 E4 0000 0033
0A4 02 0080 0000
0A5 E4 0100 0033
0A6 02 0080 0000
0A7 E4 0200 0033
0A8 02 0080 0000
0A9 E4 0300 0033
0AA 02 0080 0000
0AB E4 0400 0033
0AC 02 0080 0000
0AD E4 0500 0033
0AE 02 0080 0000
0AF E4 0600 0033
0B0 02 0080 0000
0B1 E4 0700 0033
0B2 02 0080 0000
0B3 E4 0800 0033
0B4 02 0080 0000
0B5 E4 0900 0033
0B6 02 0080 0000
0B7 E4 0A00 0033
0B8 02 0080 0000
0B9 E4 0B00 0033
0BA 02 0200 0000
0BB E5 0301 000C
0BC 02 0080 0000
0BD 0D 0000 0000
寄存器初始化(000-005)
| 行号 | 指令 | 说明 |
|---|---|---|
| 000 | FZ 0000 0000 | R00 = 0000,颜色R值占位(各子程序开始时更新) |
| 001 | FZ 0001 0000 | R01 = 0000,颜色G值占位 |
| 002 | FZ 0002 0000 | R02 = 0000,颜色B值占位 |
| 003 | FZ 0003 0000 | R03 = 0000,熄灭用R值(固定=00) |
| 004 | FZ 0004 0000 | R04 = 0000,熄灭用G值(固定=00) |
| 005 | FZ 0005 0000 | R05 = 0000,熄灭用B值(固定=00) |
主循环(010-015)
| 行号 | 指令 | 说明 |
|---|---|---|
| 010 | DY 0020 0000 | 调用白色流水子程序 |
| 011 | DY 0040 0000 | 调用红色流水子程序 |
| 012 | DY 0060 0000 | 调用黄色流水子程序 |
| 013 | DY 0080 0000 | 调用绿色流水子程序 |
| 014 | DY 00A0 0000 | 调用蓝色流水子程序 |
| 015 | ZY 0000 0010 | 跳回 010 行,无限循环 |
关键优化对比:E5 熄灭 vs E4 逐个熄灭
| 方式 | 指令数量 | 示例 |
|---|---|---|
| E4逐个熄灭(原版) | 12条 | E4 0000 0000 → E4 0100 0000 → ... → E4 0B00 0000 |
| E5批量熄灭(优化版) | 1条 | E5 0301 000C |
E5 指令参数解析
以 E5 0301 000C 为例:
| 部分 | 值 | 含义 |
|---|---|---|
| OP00(高字节前半) | 03 | 使用 R03 作为起始寄存器 |
| OP01(高字节后半) | 01 | 使用各寄存器高八位作为颜色值 |
| OP10(低字节前半) | 00 | 从 LED00 开始 |
| OP11(低字节后半) | 0C | 共 12 个 LED(0C=12) |
颜色来源:R03 高八位=00,R04 高八位=00,R05 高八位=00 → RGB=(00,00,00) 黑色熄灭。
E5 指令旋转 LED 效果(逐个点亮、逐个熄灭)
核心思路:保持 E5 指令的 OP10(起始LED编号)固定为 00,通过不断改变 OP11(LED数量)实现两个阶段:
- 月盈阶段(逐个点亮):
E5 0101 00NN— 从 LED0 起点亮 N 个白色 LED,OP11 从 01 逐渐增加到 0C(逐个亮起) - 月亏阶段(逐个熄灭):
E5 0401 00NN— 从 LED0 起用 N 个黑色 LED 覆盖,OP11 从 00 逐渐增加到 0C(通过黑色覆盖逐个熄灭)
同时用 R20 寄存器存储延时时长,通过 YS 0020 FF00 形式的延时指令引用寄存器值,实现运行时可调整的速度控制。
与贪吃蛇的关键区别:贪吃蛇通过改变 OP10(起点)、固定 OP11(长度)来移动。本示例固定 OP10 为 00,改变 OP11(数量)——"旋转"效果来自从同一原点出发的逐步点亮和逐步擦除。
E5 指令参数变化(旋转版):
| 阶段 | OP00 | OP01 | OP10 | OP11 变化 | 颜色来源 | 效果 |
|---|---|---|---|---|---|---|
| 逐个点亮 | 01 | 01 | 00 | 01→0C | R01,R02,R03 高八位 (白色) | 从 LED0 起点亮 1→12 个 LED |
| 逐个熄灭 | 04 | 01 | 00 | 00→0C | R04,R05,R06 高八位 (黑色) | 从 LED0 起覆盖 0→12 个 LED 为黑色 |
寄存器规划:
| 寄存器 | 初始值 | 用途 |
|---|---|---|
| R20 | 0008 | 延时时长 = 8ms(快速流水,可修改) |
| R01 | 1000 | 白色 R 值(高八位 = 10,暗白色) |
| R02 | 1000 | 白色 G 值(高八位 = 10) |
| R03 | 1000 | 白色 B 值(高八位 = 10) |
| R04 | 0000 | 黑色 R 值(高八位 = 00,熄灭) |
| R05 | 0000 | 黑色 G 值(高八位 = 00,熄灭) |
| R06 | 0000 | 黑色 B 值(高八位 = 00,熄灭) |
点击展开/折叠 旋转 LED 效果 完整代码
- 助记符形式
- 指令形式
000 FZ 0020 0008 R20 = 0008 (延时 = 8ms, 快速流水, 可修改速度)
001 FZ 0001 1000 R01 = 1000 (白色 R = 10, 高八位)
002 FZ 0002 1000 R02 = 1000 (白色 G = 10)
003 FZ 0003 1000 R03 = 1000 (白色 B = 10)
004 FZ 0004 0000 R04 = 0000 (黑色 R = 00)
005 FZ 0005 0000 R05 = 0000 (黑色 G = 00)
006 FZ 0006 0000 R06 = 0000 (黑色 B = 00)
========== 月盈阶段 (010-027): LED 数量 1→12, 逐个亮起 ==========
010 E5 0101 0001 LED0 (1 个 LED) 暗白色 (10,10,10)
011 YS 0020 FF00 从 R20 读取延时 (8ms)
012 E5 0101 0002 LED0-LED1 (2 个 LED)
013 YS 0020 FF00 延时
014 E5 0101 0003 LED0-LED2 (3 个 LED)
015 YS 0020 FF00 延时
016 E5 0101 0004 LED0-LED3 (4 个 LED)
017 YS 0020 FF00 延时
018 E5 0101 0005 LED0-LED4 (5 个 LED)
019 YS 0020 FF00 延时
01A E5 0101 0006 LED0-LED5 (6 个 LED)
01B YS 0020 FF00 延时
01C E5 0101 0007 LED0-LED6 (7 个 LED)
01D YS 0020 FF00 延时
01E E5 0101 0008 LED0-LED7 (8 个 LED)
01F YS 0020 FF00 延时
020 E5 0101 0009 LED0-LED8 (9 个 LED)
021 YS 0020 FF00 延时
022 E5 0101 000A LED0-LED9 (10 个 LED)
023 YS 0020 FF00 延时
024 E5 0101 000B LED0-LED10 (11 个 LED)
025 YS 0020 FF00 延时
026 E5 0101 000C LED0-LED11 (全部 12 个 LED) 全亮
027 YS 0020 FF00 延时
========== 月亏阶段 (029-042): LED 数量 0→12 黑色覆盖, 逐个熄灭 ==========
029 E5 0401 0000 0 个 LED 黑色覆盖 (无可见变化, 基准线)
02A YS 0020 FF00 延时
02B E5 0401 0001 LED0 黑色覆盖 (1 个 LED 熄灭)
02C YS 0020 FF00 延时
02D E5 0401 0002 LED0-LED1 黑色覆盖 (2 个 LED 熄灭)
02E YS 0020 FF00 延时
02F E5 0401 0003 LED0-LED2 黑色覆盖 (3 个 LED 熄灭)
030 YS 0020 FF00 延时
031 E5 0401 0004 LED0-LED3 黑色覆盖 (4 个 LED 熄灭)
032 YS 0020 FF00 延时
033 E5 0401 0005 LED0-LED4 黑色覆盖 (5 个 LED 熄灭)
034 YS 0020 FF00 延时
035 E5 0401 0006 LED0-LED5 黑色覆盖 (6 个 LED 熄灭)
036 YS 0020 FF00 延时
037 E5 0401 0007 LED0-LED6 黑色覆盖 (7 个 LED 熄灭)
038 YS 0020 FF00 延时
039 E5 0401 0008 LED0-LED7 黑色覆盖 (8 个 LED 熄灭)
03A YS 0020 FF00 延时
03B E5 0401 0009 LED0-LED8 黑色覆盖 (9 个 LED 熄灭)
03C YS 0020 FF00 延时
03D E5 0401 000A LED0-LED9 黑色覆盖 (10 个 LED 熄灭)
03E YS 0020 FF00 延时
03F E5 0401 000B LED0-LED10 黑色覆盖 (11 个 LED 熄灭)
040 YS 0020 FF00 延时
041 E5 0401 000C LED0-LED11 黑色覆盖 (全部 12 个 LED 熄灭, 全黑)
042 YS 0020 FF00 延时
043 ZY 0000 0010 跳回 010 循环,重新开始 LED 旋转周期
000 10 0020 0008
001 10 0001 1000
002 10 0002 1000
003 10 0003 1000
004 10 0004 0000
005 10 0005 0000
006 10 0006 0000
010 E5 0101 0001
011 02 0020 FF00
012 E5 0101 0002
013 02 0020 FF00
014 E5 0101 0003
015 02 0020 FF00
016 E5 0101 0004
017 02 0020 FF00
018 E5 0101 0005
019 02 0020 FF00
01A E5 0101 0006
01B 02 0020 FF00
01C E5 0101 0007
01D 02 0020 FF00
01E E5 0101 0008
01F 02 0020 FF00
020 E5 0101 0009
021 02 0020 FF00
022 E5 0101 000A
023 02 0020 FF00
024 E5 0101 000B
025 02 0020 FF00
026 E5 0101 000C
027 02 0020 FF00
029 E5 0401 0000
02A 02 0020 FF00
02B E5 0401 0001
02C 02 0020 FF00
02D E5 0401 0002
02E 02 0020 FF00
02F E5 0401 0003
030 02 0020 FF00
031 E5 0401 0004
032 02 0020 FF00
033 E5 0401 0005
034 02 0020 FF00
035 E5 0401 0006
036 02 0020 FF00
037 E5 0401 0007
038 02 0020 FF00
039 E5 0401 0008
03A 02 0020 FF00
03B E5 0401 0009
03C 02 0020 FF00
03D E5 0401 000A
03E 02 0020 FF00
03F E5 0401 000B
040 02 0020 FF00
041 E5 0401 000C
042 02 0020 FF00
043 0E 0000 0010
指令说明
核心模式使用两种不同的寄存器颜色源来构建旋转效果:
| 指令组 | 作用 |
|---|---|
E5 0101 00NN | 用 R01-R03(暗白色) 作为颜色,从 LED0 起点亮 N 个 LED |
E5 0401 00NN | 用 R04-R06(黑色/熄灭) 作为颜色,从 LED0 起覆盖 N 个 LED |
YS 0020 FF00 | 从 R20 读取延时(8ms),控制旋转速度 |
视觉效果:前半段 (010–027) 让一条白色光带从左向右"生长"填满所有 12 个 LED;后半段 (029–042) 再从左侧用黑色覆盖"擦除"它 —— 形成干净的擦除式旋转流水效果。
E5 指令参数对照表(旋转版)
| 阶段 | 行号 | OP00 | OP01 | OP10 | OP11 变化 | 颜色 | 效果 |
|---|---|---|---|---|---|---|---|
| 月盈(点亮) | 010–026 | 01 | 01 | 00 | 01→0C | 白色(R01-R03) | 1→12 个 LED 从左逐个亮起 |
| 月亏(熄灭) | 029–041 | 04 | 01 | 00 | 00→0C | 黑色(R04-R06) | 0→12 个 LED 从左逐个黑色覆盖熄灭 |
寄存器延时 + E5 流水灯(改变 OP11 数量,R20 存时长)
核心思路:保持 E5 指令的 OP10(起始LED编号)固定为 00,不断改变 OP11(LED数量)实现从左到右逐个亮起和逐个熄灭。同时用 R20 寄存器存储延时时长,通过 YS 0020 FF00 形式的延时指令引用寄存器值,实现运行时可调整的速度控制。
YS 指令的寄存器模式:
| 指令 | OP-0 | OP-1 | 说明 |
|---|---|---|---|
YS 03E8 0000 | 03E8(立即值) | 0000(ms) | 标准模式:延时 1000ms |
YS 0020 FF00 | 0020(R20) | FF+单位 | 寄存器模式:FF 表示从 R20 读取时长,低字节 00 表示单位 ms |
寄存器规划:
| 寄存器 | 值 | 用途 |
|---|---|---|
| R20 | 0080 | 延时时长 = 128ms(运行时可修改,调整流水速度) |
| R01 | 3300 | 颜色 R 值(高八位 = 33) |
| R02 | 3300 | 颜色 G 值(高八位 = 33) |
| R03 | 3300 | 颜色 B 值(高八位 = 33) |
| R04-R06 | 0000 | 熄灭用全零颜色 |
E5 指令参数变化(流水灯版):
| 阶段 | OP00 | OP01 | OP10 | OP11 | 效果 |
|---|---|---|---|---|---|
| 逐个亮起 | 01 | 01 | 00 | 01→0C | 点亮 1→12 个LED |
| 逐个熄灭 | 01 | 01 | 00 | 0B→01 | 点亮 11→1 个LED(右侧依次熄灭) |
| 最终熄灭 | 04 | 01 | 00 | 0C | 全熄灭 |
点击展开/折叠 寄存器延时流水灯 完整代码
- 助记符形式
- 指令形式
000 FZ 0020 0080 R20 = 0080 (延时时长 = 128ms,可修改以调整速度)
001 FZ 0001 3300 R01 = 3300 (颜色 R=33, 高八位)
002 FZ 0002 3300 R02 = 3300 (颜色 G=33)
003 FZ 0003 3300 R03 = 3300 (颜色 B=33)
004 FZ 0004 0000 R04 = 0000 (熄灭颜色 R=00)
005 FZ 0005 0000 R05 = 0000 (熄灭颜色 G=00)
006 FZ 0006 0000 R06 = 0000 (熄灭颜色 B=00)
========== 逐个亮起 (010-027): OP11 从 01 递增到 0C ==========
010 E5 0101 0001 LED0 白色 (OP11=01, 仅1个LED)
011 YS 0020 FF00 从R20读取延时 (128ms)
012 E5 0101 0002 LED0-LED1 白色 (OP11=02, 2个LED)
013 YS 0020 FF00 从R20读取延时
014 E5 0101 0003 LED0-LED2 白色 (OP11=03, 3个LED)
015 YS 0020 FF00 延时
016 E5 0101 0004 LED0-LED3 白色 (OP11=04, 4个LED)
017 YS 0020 FF00 延时
018 E5 0101 0005 LED0-LED4 白色 (OP11=05, 5个LED)
019 YS 0020 FF00 延时
01A E5 0101 0006 LED0-LED5 白色 (OP11=06, 6个LED)
01B YS 0020 FF00 延时
01C E5 0101 0007 LED0-LED6 白色 (OP11=07, 7个LED)
01D YS 0020 FF00 延时
01E E5 0101 0008 LED0-LED7 白色 (OP11=08, 8个LED)
01F YS 0020 FF00 延时
020 E5 0101 0009 LED0-LED8 白色 (OP11=09, 9个LED)
021 YS 0020 FF00 延时
022 E5 0101 000A LED0-LED9 白色 (OP11=0A, 10个LED)
023 YS 0020 FF00 延时
024 E5 0101 000B LED0-LED10 白色 (OP11=0B, 11个LED)
025 YS 0020 FF00 延时
026 E5 0101 000C LED0-LED11 全部亮起 (OP11=0C, 12个LED)
027 YS 0020 FF00 延时
028 YS 0200 0000 全亮后停顿 512ms (用立即值,产生更长停顿)
========== 逐个熄灭 (029-03E): OP11 从 0B 递减到 01 ==========
029 E5 0101 000B LED0-LED10 (LED11 熄灭, OP11=0B)
02A YS 0020 FF00 从R20读取延时
02B E5 0101 000A LED0-LED9 (LED10 熄灭, OP11=0A)
02C YS 0020 FF00 延时
02D E5 0101 0009 LED0-LED8
02E YS 0020 FF00 延时
02F E5 0101 0008 LED0-LED7
030 YS 0020 FF00 延时
031 E5 0101 0007 LED0-LED6
032 YS 0020 FF00 延时
033 E5 0101 0006 LED0-LED5
034 YS 0020 FF00 延时
035 E5 0101 0005 LED0-LED4
036 YS 0020 FF00 延时
037 E5 0101 0004 LED0-LED3
038 YS 0020 FF00 延时
039 E5 0101 0003 LED0-LED2
03A YS 0020 FF00 延时
03B E5 0101 0002 LED0-LED1
03C YS 0020 FF00 延时
03D E5 0101 0001 LED0
03E YS 0020 FF00 延时
03F E5 0401 000C 全部熄灭 (R04-R06, 起始LED0, 共12个)
040 YS 0020 FF00 停顿
041 ZY 0000 0010 跳回 010 循环
000 10 0020 0080
001 10 0001 3300
002 10 0002 3300
003 10 0003 3300
004 10 0004 0000
005 10 0005 0000
006 10 0006 0000
010 E5 0101 0001
011 02 0020 FF00
012 E5 0101 0002
013 02 0020 FF00
014 E5 0101 0003
015 02 0020 FF00
016 E5 0101 0004
017 02 0020 FF00
018 E5 0101 0005
019 02 0020 FF00
01A E5 0101 0006
01B 02 0020 FF00
01C E5 0101 0007
01D 02 0020 FF00
01E E5 0101 0008
01F 02 0020 FF00
020 E5 0101 0009
021 02 0020 FF00
022 E5 0101 000A
023 02 0020 FF00
024 E5 0101 000B
025 02 0020 FF00
026 E5 0101 000C
027 02 0020 FF00
028 02 0200 0000
029 E5 0101 000B
02A 02 0020 FF00
02B E5 0101 000A
02C 02 0020 FF00
02D E5 0101 0009
02E 02 0020 FF00
02F E5 0101 0008
030 02 0020 FF00
031 E5 0101 0007
032 02 0020 FF00
033 E5 0101 0006
034 02 0020 FF00
035 E5 0101 0005
036 02 0020 FF00
037 E5 0101 0004
038 02 0020 FF00
039 E5 0101 0003
03A 02 0020 FF00
03B E5 0101 0002
03C 02 0020 FF00
03D E5 0101 0001
03E 02 0020 FF00
03F E5 0401 000C
040 02 0020 FF00
041 0E 0000 0010
关键优化点说明
| 改进 | 之前写法 | 新写法 | 对比 |
|---|---|---|---|
| 延时方式 | YS 0080 0000(硬编码128ms) | YS 0020 FF00(从 R20 读取) | 修改 R20 即可调整全局速度,无需修改每一行延时指令 |
| 点亮方式 | E4 逐条设置单个LED | E5 0101 00NN 批量设置 | 从 12 条指令变 1 条指令 |
| 熄灭方式 | E4 逐条熄灭 或 E5 一次性全灭 | E5 通过减少数量实现逐个熄灭 | 展示 E5 OP11 参数的灵活性 |
YS 寄存器模式解析
以 YS 0020 FF00 为例:
| 部分 | 值 | 含义 |
|---|---|---|
| OP-0 | 0020 | 寄存器编号 20(即 R20),从中读取时长值 |
| OP-1(高字节) | FF | 特殊标记:表示这是寄存器模式,不是标准延时 |
| OP-1(低字节) | 00 | 单位:00 = 毫秒 |
当前 R20 = 0080 = 128(十进制),所以每次延时 128ms。如果需要加快流水,将 000 行的 FZ 0020 0080 改为 FZ 0020 0040(64ms)即可让所有延时同步变快。
月相模拟(E5 优化版:亮度渐亮渐暗 + 批量操作)
核心改进:对比原版月相模拟(DZ 跳转链 + E4 逐条控制,颜色硬编码),本优化版:
- E5 批量操作:用一条 E5 指令一次性点亮/熄灭多个 LED,替代原版 12 条 DZ 跳转 + 12 条 E4 指令
- 寄存器存储亮度:R01-R03 存储当前月光 RGB 值,随月相阶段动态更新,实现从新月到满月的亮度渐变
- R20 寄存器延时:延时时长存入 R20,通过
YS 0020 FF00引用,可运行时调整整体速度 - 改变 OP11 灯数:类似流水灯思路,通过改变 E5 的 OP11 参数实现 LED 数量增减,替代跳转链
月光颜色(冷白色,随亮度变化):
| 月相 | R | G | B | 寄存器值(高八位) | 说明 |
|---|---|---|---|---|---|
| 新月 | 20 | 20 | 40 | R01=2000, R02=2000, R03=4000 | 微弱月光 |
| 蛾眉月 | 40 | 40 | 80 | R01=4000, R02=4000, R03=8000 | 渐亮 |
| 上弦月 | 60 | 60 | C0 | R01=6000, R02=6000, R03=C000 | 中等亮度 |
| 盈凸月 | A0 | A0 | E0 | R01=A000, R02=A000, R03=E000 | 较亮 |
| 满月 | E0 | E0 | FF | R01=E000, R02=E000, R03=FF00 | 最亮月光 |
寄存器规划:
| 寄存器 | 初始值 | 用途 |
|---|---|---|
| R20 | 0080 | 延时时长 = 128ms(可修改调整月相变化速度) |
| R01 | 2000 | 月光 R 值(随月相更新,使用高八位) |
| R02 | 2000 | 月光 G 值(随月相更新,使用高八位) |
| R03 | 4000 | 月光 B 值(随月相更新,使用高八位) |
| R04 | 0000 | 熄灭用 R = 00 |
| R05 | 0000 | 熄灭用 G = 00 |
| R06 | 0000 | 熄灭用 B = 00 |
E5 指令参数变化(月相版):
| 阶段 | OP00 | OP01 | OP10 | OP11 变化 | 亮度变化 | 效果 |
|---|---|---|---|---|---|---|
| 月盈(渐亮) | 01 | 01 | 00 | 01→0C | R/G/B 值递增 | 从 1 个到 12 个 LED,同时每 2 步提升一级亮度 |
| 月亏(渐暗) | 01 | 01 | 00 | 0B→01 | R/G/B 值递减 | 从 11 个到 1 个 LED,同时每 2 步降低一级亮度 |
| 最终熄灭 | 04 | 01 | 00 | 0C | 全零 | 全部熄灭,回到新月状态 |
点击展开/折叠 E5优化版月相模拟 完整代码
- 助记符形式
- 指令形式
000 FZ 0020 0080 R20 = 0080 (延时时长 = 128ms,可修改调整速度)
001 FZ 0001 2000 R01 = 2000 (月光R值初始 = 20, 高八位)
002 FZ 0002 2000 R02 = 2000 (月光G值初始 = 20)
003 FZ 0003 4000 R03 = 4000 (月光B值初始 = 40)
004 FZ 0004 0000 R04 = 0000 (熄灭颜色 R=00)
005 FZ 0005 0000 R05 = 0000 (熄灭颜色 G=00)
006 FZ 0006 0000 R06 = 0000 (熄灭颜色 B=00)
========== 月盈阶段 (010-037): LED数 1→12,亮度渐增 ==========
010 E5 0101 0001 LED0 (1个) 暗淡月光 (20,20,40)
011 YS 0020 FF00 从R20读取延时 (128ms)
012 E5 0101 0002 LED0-LED1 (2个)
013 YS 0020 FF00 延时
014 FZ 0001 4000 提升亮度: R = 40
015 FZ 0002 4000 提升亮度: G = 40
016 FZ 0003 8000 提升亮度: B = 80
017 E5 0101 0003 LED0-LED2 (3个) 较暗月光 (40,40,80)
018 YS 0020 FF00 延时
019 E5 0101 0004 LED0-LED3 (4个)
01A YS 0020 FF00 延时
01B FZ 0001 6000 提升亮度: R = 60
01C FZ 0002 6000 提升亮度: G = 60
01D FZ 0003 C000 提升亮度: B = C0
01E E5 0101 0005 LED0-LED4 (5个) 中等亮度 (60,60,C0)
01F YS 0020 FF00 延时
020 E5 0101 0006 LED0-LED5 (6个)
021 YS 0020 FF00 延时
022 FZ 0001 A000 提升亮度: R = A0
023 FZ 0002 A000 提升亮度: G = A0
024 FZ 0003 E000 提升亮度: B = E0
025 E5 0101 0007 LED0-LED6 (7个) 较亮月光 (A0,A0,E0)
026 YS 0020 FF00 延时
027 E5 0101 0008 LED0-LED7 (8个)
028 YS 0020 FF00 延时
029 E5 0101 0009 LED0-LED8 (9个)
02A YS 0020 FF00 延时
02B E5 0101 000A LED0-LED9 (10个)
02C YS 0020 FF00 延时
02D FZ 0001 E000 满月亮度: R = E0
02E FZ 0002 E000 满月亮度: G = E0
02F FZ 0003 FF00 满月亮度: B = FF
030 E5 0101 000B LED0-LED10 (11个) 接近满月
031 YS 0020 FF00 延时
032 E5 0101 000C LED0-LED11 (全部12个) **满月** (E0,E0,FF) ✨
033 YS 0200 FF00 满月长停顿 (用立即值,让满月更显眼)
034 YS 0200 FF00 再次停顿,观赏满月
========== 月亏阶段 (035-056): LED数 11→1,亮度渐减 ==========
035 FZ 0001 A000 降低亮度: R = A0
036 FZ 0002 A000 降低亮度: G = A0
037 FZ 0003 E000 降低亮度: B = E0
038 E5 0101 000B LED0-LED10 (11个) 开始月亏
039 YS 0020 FF00 延时
03A E5 0101 000A LED0-LED9 (10个)
03B YS 0020 FF00 延时
03C E5 0101 0009 LED0-LED8 (9个)
03D YS 0020 FF00 延时
03E E5 0101 0008 LED0-LED7 (8个)
03F YS 0020 FF00 延时
040 FZ 0001 6000 降低亮度: R = 60
041 FZ 0002 6000 降低亮度: G = 60
042 FZ 0003 C000 降低亮度: B = C0
043 E5 0101 0007 LED0-LED6 (7个) 下弦月亮度
044 YS 0020 FF00 延时
045 E5 0101 0006 LED0-LED5 (6个)
046 YS 0020 FF00 延时
047 E5 0101 0005 LED0-LED4 (5个)
048 YS 0020 FF00 延时
049 FZ 0001 4000 降低亮度: R = 40
04A FZ 0002 4000 降低亮度: G = 40
04B FZ 0003 8000 降低亮度: B = 80
04C E5 0101 0004 LED0-LED3 (4个) 蛾眉月
04D YS 0020 FF00 延时
04E E5 0101 0003 LED0-LED2 (3个)
04F YS 0020 FF00 延时
050 FZ 0001 2000 最低亮度: R = 20
051 FZ 0002 2000 最低亮度: G = 20
052 FZ 0003 4000 最低亮度: B = 40
053 E5 0101 0002 LED0-LED1 (2个) 残月光
054 YS 0020 FF00 延时
055 E5 0101 0001 LED0 (1个) 最后一丝月光
056 YS 0020 FF00 延时
057 E5 0401 000C 全部熄灭 (R04-R06全零, 起始LED0, 共12个) → 新月 🌑
058 YS 0200 FF00 新月停顿
059 ZY 0000 0010 跳回 010,重新开始月相循环
000 10 0020 0080
001 10 0001 2000
002 10 0002 2000
003 10 0003 4000
004 10 0004 0000
005 10 0005 0000
006 10 0006 0000
010 E5 0101 0001
011 02 0020 FF00
012 E5 0101 0002
013 02 0020 FF00
014 10 0001 4000
015 10 0002 4000
016 10 0003 8000
017 E5 0101 0003
018 02 0020 FF00
019 E5 0101 0004
01A 02 0020 FF00
01B 10 0001 6000
01C 10 0002 6000
01D 10 0003 C000
01E E5 0101 0005
01F 02 0020 FF00
020 E5 0101 0006
021 02 0020 FF00
022 10 0001 A000
023 10 0002 A000
024 10 0003 E000
025 E5 0101 0007
026 02 0020 FF00
027 E5 0101 0008
028 02 0020 FF00
029 E5 0101 0009
02A 02 0020 FF00
02B E5 0101 000A
02C 02 0020 FF00
02D 10 0001 E000
02E 10 0002 E000
02F 10 0003 FF00
030 E5 0101 000B
031 02 0200 FF00
032 E5 0101 000C
033 02 0200 FF00
034 02 0200 FF00
035 10 0001 A000
036 10 0002 A000
037 10 0003 E000
038 E5 0101 000B
039 02 0020 FF00
03A E5 0101 000A
03B 02 0020 FF00
03C E5 0101 0009
03D 02 0020 FF00
03E E5 0101 0008
03F 02 0020 FF00
040 10 0001 6000
041 10 0002 6000
042 10 0003 C000
043 E5 0101 0007
044 02 0020 FF00
045 E5 0101 0006
046 02 0020 FF00
047 E5 0101 0005
048 02 0020 FF00
049 10 0001 4000
04A 10 0002 4000
04B 10 0003 8000
04C E5 0101 0004
04D 02 0020 FF00
04E E5 0101 0003
04F 02 0020 FF00
050 10 0001 2000
051 10 0002 2000
052 10 0003 4000
053 E5 0101 0002
054 02 0020 FF00
055 E5 0101 0001
056 02 0020 FF00
057 E5 0401 000C
058 02 0200 FF00
059 0E 0000 0010
关键优化对比:原版 vs E5优化版
| 维度 | 原版月相模拟 | E5优化版月相模拟 |
|---|---|---|
| 点亮方式 | DZ 跳转链 + 每条 E4 单独点亮 | E5 0101 00NN 批量点亮(改变 OP11) |
| 点亮指令数 | 约 12 条 DZ + 12 条 E4 = 24 条 | 约 24 条 E5(但每条控制 N 个 LED,更简洁) |
| 亮度控制 | 硬编码冷白色 (E0,E0,FF),无亮度变化 | 动态更新 R01-R03,实现 5 级亮度渐变 ✨ |
| 延时时长 | 硬编码 YS 0100 0000 | YS 0020 FF00 从 R20 读取,可运行时调整 |
| 方向切换 | DZ 对比 + 子程序调用 | 顺序执行(月盈→月亏→循环),无需复杂跳转 |
亮度变化时间线
| 阶段 | 行号范围 | LED 数量变化 | RGB 亮度变化 |
|---|---|---|---|
| 月盈开始 | 010-013 | 1→2 | (20,20,40) 暗淡 |
| 月盈中期 | 014-021 | 3→6 | (40,40,80) → (60,60,C0) 渐亮 |
| 月盈后期 | 022-02C | 7→10 | (A0,A0,E0) 较亮 |
| 满月 | 02D-034 | 11→12 | (E0,E0,FF) 最亮 ✨ |
| 月亏开始 | 035-03F | 11→8 | (A0,A0,E0) 渐暗 |
| 月亏中期 | 040-048 | 7→5 | (60,60,C0) 较暗 |
| 月亏后期 | 049-056 | 4→1 | (40,40,80) → (20,20,40) 暗淡 |
| 新月 | 057-059 | 全灭 | (00,00,00) 🌑 |
亮度可调:如何自定义月光颜色
如果希望改变月光颜色或亮度,只需修改初始化时的寄存器值:
| 想要的效果 | 修改哪几行 | 示例值 |
|---|---|---|
| 更冷的蓝光 | 003 行 R03 | FZ 0003 FF00 (B = FF) |
| 更暖的黄光 | 001-002 行 R01-R02 | FZ 0001 F000, FZ 0002 F000 |
| 整体更暗 | 001-003 全部减半 | 如 FZ 0001 1000, FZ 0002 1000, FZ 0003 2000 |
| 更快的月相变化 | 000 行 R20 | FZ 0020 0040 (延时 = 64ms) |
社区图书馆智能门禁系统(满分 100 分案例)
硬件准备
- 1 个舵机(带指针,WPWM 指令,通道 0)
- 1 个全彩 LED(CD / E4 指令)
- 显示装置(数字输出 / 串口,显示当前人数)
- 两个红外传感器(门外:传感器 A,门内:传感器 B)
- 1 个工作人员紧急按钮
核心指令:10 (FZ) 初始化 · 11 寄存器复制 · 12 自增/自减 · 13 寄存器→数字输出(显示) · WPWM (C8) 舵机控制 · CD (E4) LED 颜色 · 02 (YS) 延时 · 0E (ZY) 跳转 · 09 条件跳转(等于) · 04 条件跳转(大于) · 06 条件跳转(等于字面量)
场景描述:双向进出检测
图书馆内最多容纳 10 人:
- 绿色 LED 当人数 < 10 → 有空位 ✅
- 红色 LED 当人数 == 10 → 无空位 🚫
- 舵机指针水平 → 门 关闭
- 舵机指针垂直向下 → 门 打开
- 传感器 A(门外)→ 传感器 B(门内) → 有人 进入 → 人数++
- 传感器 B(门内)→ 传感器 A(门外) → 有人 离开 → 人数--
- 工作人员按钮 → 无条件开门,不改变人数(扩展功能)
传感器输入值(R3F)
| R3F 值 | 含义 |
|---|---|
0000 | 无按键 / 传感器触发 |
0001 | 传感器 A(门外)触发 |
0002 | 传感器 B(门内)触发 |
0004 | 工作人员紧急按钮 |
寄存器映射表
| 寄存器 | 用途 | 初始值 |
|---|---|---|
| R09 | 当前人数 (0-10) | 0000 |
| R0A | 门状态 (0=关, 1=开) | 0000 |
| R0B | 最大容量常量 (10) | 000A |
| R0C | 临时计算 / 比较 | 0000 |
| R0D | 上次 R3F 值(边沿检测) | 0000 |
| R0E | 序列记忆 (0=无, 1=A已见, 2=B已见) | 0000 |
| R0F | 序列超时计数器 | 0000 |
| R10 | 检测到的方向 (0=无, 1=进入, 2=离开, 3=工作人员) | 0000 |
| R20 | 开门持续时间 | 00A0 |
| R21 | 序列超时阈值 (8 个空循环) | 0008 |
| R22 | 常量 1(用于比较) | 0001 |
舵机位置(WPWM — 通道 0)
| 位置 | WPWM 指令 | 含义 |
|---|---|---|
| 水平 | WPWM 0000 0300 | 门 关闭 |
| 垂直向下 | WPWM 0000 0C00 | 门 打开 |
LED 颜色参考
| 颜色 | CD 指令 (LED00) |
|---|---|
| 绿色(有空位) | CD 0000 9900 |
| 红色(满员 — 无空位) | CD 0099 0000 |
| 关闭 | CD 0000 0000 |
完整指令代码(共约 90 行)
================== 初始化 (000-00E) ==================
000 10 0009 0000 R09 = 0(人数 = 0,图书馆为空)
001 10 000A 0000 R0A = 0(门 = 关闭)
002 10 000B 000A R0B = 10(最大容量,常量)
003 10 000D 0000 R0D = 0(上次 R3F = 无)
004 10 000E 0000 R0E = 0(暂无序列检测)
005 10 000F 0000 R0F = 0(序列超时计数器)
006 10 0010 0000 R10 = 0(无方向检测)
007 10 0020 00A0 R20 = A0(开门持续时间)
008 10 0021 0008 R21 = 8(8 个空循环后重置序列)
009 10 0022 0001 R22 = 1(用于比较的常量)
00A C5 0001 0000 启用 PWM 发生器(舵机必需)
00B WPWM 0000 0300 舵机通道 0 → 水平(门关闭)
00C CD 0000 9900 LED00 = 绿色(有空位!)
00D 13 0009 0000 数字输出 = R09(显示人数 "0")
================== 主循环:读取传感器 (010-01F) ==================
010 11 0000 003F R00 = R3F(读取当前按键/传感器状态)
011 09 0000 0030 若 R00==0:跳转至 030(无输入,检查超时)
--- 边沿检测:新按下 = R00!=0 且 R0D==0 ---
012 11 0001 000D R01 = R0D(上次状态)
013 09 0000 0017 若 R01==0:跳转至 017(检测到新按下)
014 ZY 0000 0020 否则:跳转至人数检查(传感器仍保持 — 跳过)
--- 检测到新按下 — 根据传感器值路由 ---
017 11 000D 0000 R0D = R00(保存当前状态,用于下次循环边沿检测)
018 09 0001 0040 若 R00==1:跳转至 040(传感器 A — 门外)
019 09 0002 0050 若 R00==2:跳转至 050(传感器 B — 门内)
01A 09 0004 0060 若 R00==4:跳转至 060(工作人员按钮 — 紧急开门)
01B ZY 0000 0020 未知输入:跳转至人数检查
================== 人数检查与 LED 更新 (020-02F) ==================
020 11 0000 0009 R00 = R09(当前人数)
021 11 0001 000B R01 = R0B(最大容量 = 10)
--- 若人数 >= 10 → 红色 LED(满员)---
022 04 0009 0028 若 R00 > 9:跳转至 028(>=10 表示满员)
023 09 000A 0028 若 R00==10:跳转至 028(恰好满员)
--- 否则 → 绿色 LED(有空位)---
024 CD 0000 9900 LED00 = 绿色 ✅
025 ZY 0000 002A 跳转至显示
--- 满员:LED 变红 ---
028 CD 0099 0000 LED00 = 红色 🚫
029 ZY 0000 002A 跳转至显示
--- 在数字输出引脚显示当前人数 ---
02A 13 0009 0000 输出 = R09(显示当前人数)
02B ZY 0000 0070 跳转至延时/返回
================== 无输入超时处理 (030-03F) ==================
030 10 000D 0000 R0D = 0(无输入 → 重置边沿检测)
031 09 0000 0020 若 R0E==0:跳转至人数检查(无序列需超时处理)
032 12 000F 0001 R0F += 1(超时计数器自增)
033 11 0000 000F R00 = R0F
034 04 0007 0020 若 R0F > 7:跳转至人数检查(在阈值内)
035 10 000E 0000 R0E = 0(超时:重置序列记忆)
036 10 000F 0000 R0F = 0(重置超时计数器)
037 ZY 0000 0020 跳转至人数检查
================== 传感器 A(门外)处理 (040-04F) ==================
040 11 0000 000E R00 = R0E(之前看到了什么?)
041 09 0002 0048 若 R0E==2:跳转至 048(先 B 后 A = 有人离开!)
042 09 0001 0045 若 R0E==1:跳转至 045(A 已见 — 忽略)
043 10 000E 0001 R0E = 1(第一个传感器:见到 A → 记住)
044 ZY 0000 0020 跳转至人数检查(等待第二个传感器)
045 10 000F 0000 R0F = 0(重置超时:传感器仍活跃)
046 ZY 0000 0020 跳转至人数检查
--- 先 B 后 A 序列确认 → 有人从门离开 ---
048 11 0000 0009 R00 = R09(检查当前人数)
049 09 0000 0020 若人数==0:跳转至人数检查(不能小于 0!)
04A 2B 0009 0001 R09 -= 1(人数 = 人数 - 1)
04B 10 0010 0002 R10 = 2(方向 = 离开)
04C 10 000E 0000 R0E = 0(重置序列记忆)
04D ZY 0000 0080 跳转至门动作(开门)
================== 传感器 B(门内)处理 (050-05F) ==================
050 11 0000 000E R00 = R0E(之前看到了什么?)
051 09 0001 0058 若 R0E==1:跳转至 058(先 A 后 B = 有人进入!)
052 09 0002 0055 若 R0E==2:跳转至 055(B 已见 — 忽略)
053 10 000E 0002 R0E = 2(第一个传感器:见到 B → 记住)
054 ZY 0000 0020 跳转至人数检查(等待第二个传感器)
055 10 000F 0000 R0F = 0(重置超时:传感器仍活跃)
056 ZY 0000 0020 跳转至人数检查
--- 先 A 后 B 序列确认 → 有人进入图书馆 ---
058 11 0000 0009 R00 = R09(检查当前人数)
059 04 0009 0020 若人数 > 9:跳转至人数检查(满员!无法进入)
05A 12 0009 0001 R09 += 1(人数 = 人数 + 1)
05B 10 0010 0001 R10 = 1(方向 = 进入)
05C 10 000E 0000 R0E = 0(重置序列记忆)
05D ZY 0000 0080 跳转至门动作(开门)
================== 工作人员紧急按钮 (060-07F) ==================
060 10 0010 0003 R10 = 3(工作人员动作 — 不改变人数!)
061 ZY 0000 0080 跳转至门动作(无条件开门)
================== 门动作:开门 → 延时 → 关门 (080-08F) ==================
080 WPWM 0000 0C00 舵机 → 垂直向下(门打开 ↓)
081 10 000A 0001 R0A = 1(门状态 = 打开)
082 02 0020 FF00 延时(保持门打开以供进出)
083 WPWM 0000 0300 舵机 → 水平(门关闭 —)
084 10 000A 0000 R0A = 0(门状态 = 关闭)
085 10 0010 0000 R10 = 0(清除方向标记)
086 ZY 0000 0020 跳转至人数检查与 LED 更新
================== 短延时与循环返回 (070) ==================
070 02 0001 0000 短延时(消抖)
071 ZY 0000 0010 循环回到主循环
工作原理:分步流程图
开始
│
▼
初始化寄存器、舵机关闭(水平)、LED 绿色
│
▼
主循环 ──► 读取 R3F(传感器/按键)
│ │
│ ├─► R3F==0 → 无输入 → 检查序列超时 → LED 更新
│ │
│ ├─► R3F==1 → 传感器 A(门外)
│ │ ├─► R0E==2 → 先B后A → 人数-- → 开门
│ │ └─► 其他 → R0E=1(记住 A),继续
│ │
│ ├─► R3F==2 → 传感器 B(门内)
│ │ ├─► R0E==1 → 先A后B → 人数++(若 <10)→ 开门
│ │ └─► 其他 → R0E=2(记住 B),继续
│ │
│ └─► R3F==4 → 工作人员按钮 → 开门(不改变人数)
│
▼
更新 LED:人数 < 10 则绿色,人数 == 10 则红色
│
▼
在数字输出引脚显示人数
│
▼
循环返回 ────────────┘
测试场景(预期结果)
| 初始人数 | 操作 | 预期新人数 | LED | 舵机 |
|---|---|---|---|---|
| 0 | 传感器 A 然后 B(进入) | 1 | 绿色 | 开 → 关 |
| 1 | 传感器 A 然后 B(进入) | 2 | 绿色 | 开 → 关 |
| 9 | 传感器 A 然后 B(进入) | 10 | 红色 | 开 → 关 |
| 10 | 传感器 A 然后 B(进入) | 10(不变 — 满员!) | 红色 | N/A(不开门) |
| 1 | 传感器 B 然后 A(离开) | 0 | 绿色 | 开 → 关 |
| 0 | 传感器 B 然后 A(离开) | 0(不变 — 不能小于 0) | 绿色 | N/A |
| 任意 | 工作人员按钮 (0x04) | 不变 | 不变 | 开 → 关 |
核心算法概念
1. 双向检测(核心创新) 两个传感器分别位于门的两侧,用于检测行走方向:
- 传感器 A 安装在图书馆 门外
- 传感器 B 安装在图书馆 门内
- 传感器被触发的 序列 决定了方向:
- A → B = 向 内 走(进入图书馆)
- B → A = 向 外 走(离开图书馆)
- 序列超时(R0F 计数器)在行人未完成穿越时重置记忆
2. 边沿检测(防止重复计数) R0D 存储"上次 R3F 值"。仅当以下条件满足时才处理传感器:
- 当前 R3F != 0 且上次 R3F == 0
- 这意味着只对 按下瞬间 做出反应,而非持续保持
- 防止同一人被多次计数
3. 边界保护
- 人数 == 10 时无法进入(图书馆满员)
- 人数 == 0 时无法离开(图书馆已空 — 安全检查)
- 人数寄存器(R09)在自增/自减前由边界检查保护
4. 工作人员优先(扩展功能) 工作人员按钮(R3F==4)始终开门且不改变人数。这对以下场景至关重要:
- 工作人员进出图书馆,不计入访客人数
- 紧急情况下有人被困
- 维护访问
自定义修改建议
| 想修改什么 | 修改哪个寄存器/行 | 示例 |
|---|---|---|
| 图书馆容量 | 002 行 (R0B) | 10 000B 0014 → 容量 = 20 |
| 开门持续时间 | 007 行 (R20) | 10 0020 00FF → 更长开门时间 |
| 序列超时时间 | 008 行 (R21) | 10 0021 0004 → 更快重置(适合矮个子) |
| 舵机角度 | 00B 行 与 080/083 行 | WPWM 0000 0500 → 不同角度 |
| LED 颜色 | 00C 行、024 行、028 行 | CD 0000 00FF → 蓝色 LED |