单片机第四周第一题笔记

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等)

八、关键注意事项

  1. 时间标志位清零:每次模式切换后必须清零sys_tick
  2. 模式切换优化:避免从模式四切回模式一时跳过第一个LED
  3. 闪烁显示:正确设置:10实现熄灭效果
  4. 高位熄灭:当数值为0时显示熄灭状态
  5. 界面布局:按逻辑顺序编写界面代码

整理说明:以上内容将原始笔记重新组织,按功能模块分类,添加了清晰的注释说明,使整体逻辑更加清晰易懂。