LED彩灯智能控制系统 - 笔记整理与详解
一、系统概述
这是一个基于C语言的LED彩灯控制系统,实现了多种灯光模式切换、时间控制、状态显示和用户交互功能。
二、核心组件说明
1. 头文件与函数
#include <intrins.h> // 包含左移(_crol_)和右移(_cror_)函数
2. 时间标志位
- sys_tick:系统时间标志位,在中断服务函数中递增
- 当
sys_tick达到对应模式的流转时间时,触发LED移位操作 - 每次处理后需清零,以便下次循环
三、LED灯光模式实现
模式切换控制代码
if(sys_tick == ucled_mode_time[ucled_disp_mode]) {
sys_tick = 0; // 时间标志位清零
switch(ucled_disp_mode) {
case 0: // 模式1:L1→L8(从左到右)
ucled = _crol_(ucled, 1);
if(ucled == 0x7f) // 最后一个灯亮时切换到模式2
ucled_disp_mode = 1;
break;
case 1: // 模式2:L8→L1(从右到左)
ucled = _cror_(ucled, 1);
if(ucled == 0xfe) // 第一个灯亮时切换到模式3
ucled_disp_mode = 2;
break;
case 2: // 模式3:由外到内亮灯
ucled = ucled_data[ucled_data_index];
if(++ucled_data_index == 4) { // 数据索引递增到3时停止
ucled_data_index = 3;
ucled_disp_mode = 3; // 切换到模式4
}
break;
case 3: // 模式4:由内到外亮灯
ucled = ucled_data[ucled_data_index];
if(--ucled_data_index == 255) { // 数据索引递减到0时停止
ucled_data_index = 0;
ucled_disp_mode = 0; // 切换回模式1
}
break;
}
}
模式切换优化(避免跳过第一个LED)
case 0: // 模式1
if(ucled == 0x7e) // 判断是否从模式4切换到模式1
ucled = 0xfe; // 复位LED数据
else {
ucled = _crol_(ucled, 1); // 正常左移
if(ucled == 0x7f) // 最后一个灯亮时切换
ucled_disp_mode = 1;
}
break;
四、时间流转机制
- 直接使用
ucled_disp_mode指向不同模式的流转时间 - 无需单独定义新的时间变量
五、启动/暂停功能
- 定义0-1变量控制
sys_tick的自增 - 通过条件判断实现系统的启动和暂停
六、数码管显示控制
1. 闪烁显示设置
else if(time_set_index == 1) {
seg_buf[2] = sys_flash ? mode_time_set[disp_mode_set]/1000%10 : 10;
if(seg_buf[2] == 0) { seg_buf[2] = 10; } // 高位熄灭控制
seg_buf[3] = sys_flash ? mode_time_set[disp_mode_set]/100%10 : 10;
seg_buf[4] = sys_flash ? mode_time_set[disp_mode_set]/10%10 : 10;
seg_buf[5] = sys_flash ? mode_time_set[disp_mode_set]%10 : 10;
}
注意:不要遗漏:10,这是设置熄灭状态的关键
2. 模式三数据显示界面
switch(seg_disp_mode) {
case 0: // 运行状态界面
if(data_disp_flag == 0) {
seg_point[0] = 0; // 第一二位无小数点
seg_point[1] = 0;
seg_buf[0] = sys_operation ? 11 : 12;
seg_buf[1] = ucled_disp_mode + 1;
seg_buf[2] = ucled_mode_time[ucled_disp_mode]/1000%10;
seg_buf[3] = ucled_mode_time[ucled_disp_mode]/100%10;
seg_buf[4] = ucled_mode_time[ucled_disp_mode]/10%10;
seg_buf[5] = ucled_mode_time[ucled_disp_mode]%10;
if(seg_buf[2] == 0)
seg_buf[2] = 10; // 高位熄灭
} else { // 数据显示界面
seg_point[0] = 1; // 第一二位有小数点
seg_point[1] = 1;
seg_buf[0] = 0;
seg_buf[1] = 12;
seg_buf[2] = 13;
seg_buf[3] = ucled_disp_mode + 1;
seg_buf[4] = a/10;
seg_buf[5] = a%10;
}
break;
}
3. 界面切换逻辑
- 界面一长按可切换到界面三
- 界面三代码应写在界面二下面
- 界面切换示例:
if(key_old == 4 && seg_disp_mode == 0)
data_disp_flag = 1;
else
data_disp_flag = 0;
七、LED亮灯位置检测
int i = 0;
while((~ucled & (0x01 << i)) == 0) { // 检索第i+1个亮灯位置
i++;
}
if(ucled_disp_mode < 2)
a = i + 1; // 模式一二:显示单个位置编号
else
a = (i + 1) * 10 + (8 - i); // 模式三四:显示对称位置(如18,27等)
八、关键注意事项
- 时间标志位清零:每次模式切换后必须清零
sys_tick - 模式切换优化:避免从模式四切回模式一时跳过第一个LED
- 闪烁显示:正确设置
:10实现熄灭效果 - 高位熄灭:当数值为0时显示熄灭状态
- 界面布局:按逻辑顺序编写界面代码
整理说明:以上内容将原始笔记重新组织,按功能模块分类,添加了清晰的注释说明,使整体逻辑更加清晰易懂。