跳到主要内容

项目 2:模拟室内照明电路

🎯 项目目标​

构建一个电灯开关模拟:

  • 使用按键切换电灯开/关
  • 控制全彩 LED 在"开"时发出白光
  • 在屏幕上显示当前开关状态

📋 所需硬件​

组件数量连接
Steamania JoyKit V21主控制器
按键模块1数字输入引脚
WS2812B 全彩 LED1板载或外部

🔧 电路设置​

  1. 按键:连接到数字输入引脚之一(如 DI0)
  2. WS2812B LED:使用板载 LED 或连接到专用引脚

💡 核心任务​

任务 1:配置按键为数字输入​

  • 使用指令 0x10 配置 IO 引脚
  • 设置适当的引脚为数字输入

任务 2:实现切换逻辑​

  • 检测按键按下(从高到低或从低到高的跳变)
  • 切换状态变量(0 = 关,1 = 开)
  • 实现去抖动以避免误触发

任务 3:控制 LED 状态​

  • 开关为"开"时 LED 发白光(0xFFFFFF)
  • 开关为"关"时 LED 关闭(0x000000)

任务 4:显示状态​

  • 在屏幕上显示"ON"或"OFF"文本
  • 可选显示当前状态指示器

📝 参考方案​

程序代码(优化版本)​

000 C7 0001 0000  ; 启用 WS2812B LED 控制
001 10 0025 00F0 ; 配置 IO 引脚:低 4 位为输入,高 4 位为输出
002 10 0020 0000 ; R20 = 灯状态(0=关,1=开)
003 10 0021 0001 ; R21 = 上一个按键状态(1=松开)
004 10 0028 FFFF ; 设置文本颜色为白色
005 0E 0000 0010 ; 跳转到主循环

; 主循环
010 14 0000 0000 ; 读取数字输入到 R00
011 17 0000 0001 ; R00 = R00 AND 0x01(仅检查 DI0)
012 06 0001 0020 ; 如果按键松开(1),跳转到 020
013 06 0001 0020 ; 如果上一个状态也是松开,跳过切换

; 按键按下时切换状态
014 12 0020 0001 ; R20 = R20 + 1(切换)
015 04 0001 0017 ; 如果 R20 > 1,跳转到重置
016 0E 0000 0018 ; 跳转到更新

017 10 0020 0000 ; 重置:R20 = 0

; 更新 LED 和显示
018 04 0000 001A ; 如果 R20 > 0,打开 LED
019 E4 0000 0000 ; LED 关
01A 55 0A00 0000 ; 显示"OFF"
01B 0E 0000 001D ; 跳转到结束

01C E4 00FF FFFF ; LED 开(白色)
01D 55 0A00 0001 ; 显示"ON"

; 结束循环
01E 11 0021 0000 ; R21 = R00(保存按键状态)
01F 02 0096 0000 ; 延时 150 毫秒(去抖动)
020 0E 0000 0010 ; 跳转回第 010 行

🔍 详细解释​

初始化(第 000-005 行)​

第 000 行:C7 0001 0000

  • 启用 WS2812B 全彩 LED 控制模块
  • 使用指令 0xE4 前必须启用

第 001 行:10 0025 00F0

  • 配置 IO 引脚方向
  • R25 = IO 配置寄存器
  • 00F0 = 二进制 11110000 = 低 4 引脚为输入,高 4 引脚为输出

第 002 行:10 0020 0000

  • 初始化灯状态变量 R20 为 0(关)
  • R20 将在 0(关)和 1(开)之间切换

第 003 行:10 0021 0001

  • 初始化上一个按键状态 R21 为 1(松开)
  • 用于边沿检测

第 004 行:10 0028 FFFF

  • 设置前景色为白色(0xFFFF,RGB565 格式)
  • 用于文本显示

第 005 行:0E 0000 0010

  • 跳转到主循环第 010 行

按键检测和切换(第 010-017 行)​

第 010 行:14 0000 0000

  • 读取数字输入值到 R00
  • 每个位代表一个 DI 引脚状态

第 011 行:17 0000 0001

  • R00 = R00 AND 0x01
  • 仅检查 DI0(位 0)
  • 结果:R00 = 0(按下)或 1(松开)

第 012 行:06 0001 0020

  • 如果 R00 == 1(按键松开),跳转到 020
  • 按键未按下时跳过切换逻辑

第 013 行:06 0001 0020

  • 如果上一个状态也是松开,跳过
  • 这创建了边沿检测(仅在按下时切换,而不是按住)

第 014 行:12 0020 0001

  • 切换灯状态:R20 = R20 + 1
  • 在 0 和 1 之间交替

第 015 行:04 0001 0017

  • 如果 R20 > 1,跳转到重置行 017
  • 确保 R20 保持在 0-1 范围内

第 016 行:0E 0000 0018

  • 跳转到 LED 更新部分

第 017 行:10 0020 0000

  • 重置 R20 为 0(从 2 绕回 0)

LED 控制(第 018-01D 行)​

第 018 行:04 0000 001A

  • 如果 R20 > 0(灯开),跳转到 01A

第 019 行:E4 0000 0000

  • 关闭 LED
  • RGB = (0, 0, 0) = 黑色

第 01A 行:55 0A00 0000

  • 在位置 (10, 0) 显示"OFF"文本
  • 值 0000 代表"关"状态

第 01B 行:0E 0000 001D

  • 跳转到循环结束

第 01C 行:E4 00FF FFFF

  • 打开 LED
  • RGB = (255, 255, 255) = 白色

第 01D 行:55 0A00 0001

  • 在位置 (10, 0) 显示"ON"文本

循环管理(第 01E-020 行)​

第 01E 行:11 0021 0000

  • 保存当前按键状态到 R21
  • R21 = R00(为下一次迭代保存)

第 01F 行:02 0096 0000

  • 延时 150 毫秒
  • 0096 = 十进制 150
  • 提供去抖动以防止误触发

第 020 行:0E 0000 0010

  • 跳转回第 010 行
  • 创建无限循环以持续监测

🎨 状态转换表​

当前状态按键按下新状态LED 动作
关 (0)按下开 (1)打开(白色)
开 (1)按下关 (0)关闭(黑色)
关 (0)未按下关 (0)无变化
开 (1)未按下开 (1)无变化

🔍 关键学习点​

  1. 数字输入读取:如何从 IO 引脚读取按键状态
  2. 边沿检测:检测按键按下与按住的区别
  3. 切换逻辑:实现开/关状态机
  4. 去抖动:使用延时防止误触发
  5. 条件控制:使用比较进行决策
  6. RGB 颜色:为不同状态设置 LED 颜色

🧪 测试清单​

  • 按键正确配置为数字输入
  • 按键按下时 LED 打开(白色)
  • 再次按下按键时 LED 关闭
  • 显示显示正确的"ON"或"OFF"状态
  • 按键去抖动工作(无误触发)
  • 系统对重复按下响应可靠

💡 扩展挑战​

  1. 添加调光:使用按住按键调节 LED 亮度
  2. 多种颜色:循环不同颜色而不是简单的开/关
  3. 双按键系统:添加独立的开和关按键
  4. 自动关闭定时器:5 分钟后自动关闭
  5. 状态指示器:添加第二个 LED 显示电源状态
  6. 远程控制:使用红外或蓝牙进行无线控制

🐛 常见问题和解决方案​

问题 1:LED 快速闪烁​

原因:没有去抖动或延时不足 解决方案:增加第 01F 行的延时到 200-300ms

问题 2:按键无响应​

原因:IO 配置不正确 解决方案:验证第 001 行设置正确的引脚为输入

问题 3:LED 多次切换​

原因:按键抖动或延时太短 解决方案:增加去抖动延时或添加额外滤波

问题 4:显示显示错误文本​

原因:状态变量或比较不正确 解决方案:检查 R20 值和比较逻辑

📚 相关文档​

本项目使用的指令​

操作码名称描述文档链接
0x02延时设置毫秒级延时时间延时
0x04大于跳转如果 R00 > 立即数则跳转条件跳转
0x06等于跳转如果 R00 == 立即数则跳转条件跳转
0x0E无条件跳转跳转到指定行号无条件跳转
0x10写入寄存器将立即数写入寄存器寄存器操作
0x11复制寄存器将一个寄存器的值复制到另一个寄存器操作
0x12加立即数将立即数加到寄存器寄存器操作
0x14读 DI读取数字输入引脚到 R00数字 I/O
0x17与寄存器按位与运算位运算
0x55显示文本在屏幕上显示寄存器值文本输出
0xCB启用 WS2812B启用 LED 控制模块外部设备
0xE4设置 LED 颜色为指定 LED 设置 RGB 颜色彩灯与音乐

额外参考​