志→目标, 自我提升

51单片机之5050全彩LED模块

钱魏Way · · 7 次浏览
!文章内容如有错误或排版问题,请提交反馈,非常感谢!

5050全彩LED是共阳极设计(V接正极),通过控制R、G、B引脚的负极调光。使用PWM(脉宽调制)调整R、G、B的占空比,混合出不同颜色。

系统目标

  • MCU: STC89C52RC
  • LED模块:普通 5050 RGB 模块(共阴极,4引脚:VCC、R、G、B)
  • 控制方式:用 51 单片机 软件 PWM 控制 RGB 三色亮度
  • 输入方式:使用0 ~ P3.7 八个独立按键控制 8 种灯效

接线说明

名称 引脚 说明
R P2.0 红灯控制(低电平亮)
G P2.1 绿灯控制(低电平亮)
B P2.2 蓝灯控制(低电平亮)
VCC +5V 接电源正极
GND GND 接电源负极
按键 P3.0~P3.7 低电平有效(带上拉)

灯效定义(按键模式切换)

按键(P3.x) 灯效说明
P3.0 红色常亮
P3.1 绿色常亮
P3.2 蓝色常亮
P3.3 呼吸灯(红)
P3.4 RGB轮换
P3.5 彩色渐变
P3.6 快速闪烁随机色
P3.7 熄灭

主程序(Keil C 源码)

#include <REGX52.H>

#define uchar unsigned char
#define uint unsigned int

// RGB 引脚定义
sbit R_LED = P2^0;
sbit G_LED = P2^1;
sbit B_LED = P2^2;

uchar mode = 0;  // 当前灯效模式
uchar R_val = 0, G_val = 0, B_val = 0;  // PWM值

// 简单延时
void Delay_ms(uint ms) {
    uint i, j;
    for (i = 0; i < ms; i++)
        for (j = 0; j < 123; j++);
}

// 读取按键状态(低电平有效)
void KeyScan() {
    uchar key = P3 ^ 0xFF;  // 获取按键值(P3.0~P3.7)
      uchar i; 
    for (i = 0; i < 8; i++) {
        if ((key >> i) & 0x01) {
            mode = i;  // 切换灯效
        }
    }
}

// 软件PWM输出,周期为256(约1ms)
void RGB_PWM_Output() {
    uchar i; 
    for (i = 0; i < 255; i++) {
        R_LED = (i < R_val) ? 0 : 1;
        G_LED = (i < G_val) ? 0 : 1;
        B_LED = (i < B_val) ? 0 : 1;
    }
}

// 呼吸灯变量
uchar breathe = 0;
bit up = 1;

// 随机数种子
uint seed = 12345;
uchar random() {
    seed = seed * 25173 + 13849;
    return (uchar)(seed >> 8);
}

// 设置 RGB 值
void SetColor(uchar r, uchar g, uchar b) {
    R_val = r;
    G_val = g;
    B_val = b;
}

void main() {
    while (1) {
        KeyScan();

        switch (mode) {
            case 0: SetColor(255, 0, 0); break;     // 红
            case 1: SetColor(0, 255, 0); break;     // 绿
            case 2: SetColor(0, 0, 255); break;     // 蓝
            case 3: // 呼吸灯 红色
                if (up) breathe += 5; else breathe -= 5;
                if (breathe >= 250) up = 0;
                if (breathe <= 5) up = 1;
                SetColor(breathe, 0, 0);
                break;
            case 4: // RGB轮换(每轮切换一次)
                                    {
                                            static uchar rgb_state = 0;

                                            switch (rgb_state) {
                                                    case 0: SetColor(255, 0, 0); break;  // 红
                                                    case 1: SetColor(0, 255, 0); break;  // 绿
                                                    case 2: SetColor(0, 0, 255); break;  // 蓝
                                            }

                                            rgb_state++;
                                            if (rgb_state > 2) rgb_state = 0;

                                            Delay_ms(300);
                                    }
                                    break;
            case 5: // 渐变
                SetColor(breathe, 255 - breathe, breathe / 2);
                if (up) breathe += 3; else breathe -= 3;
                if (breathe >= 250) up = 0;
                if (breathe <= 5) up = 1;
                break;
            case 6: // 快速闪烁随机
                SetColor(random(), random(), random());
                Delay_ms(150);
                break;
            case 7: // 熄灭
                SetColor(0, 0, 0);
                break;
        }

        RGB_PWM_Output();
    }
}

代码注解:

全局变量

uchar mode = 0;  // 当前灯效模式
uchar R_val = 0, G_val = 0, B_val = 0;  // PWM值
uchar breathe = 0;  // 呼吸灯变量
bit up = 1;        // 呼吸灯方向标志
uint seed = 12345; // 随机数种子
  • mode:保存当前选择的灯光效果(0-7)
  • R_val, G_val, B_val:存储RGB三色的PWM值
  • breathe:用于呼吸灯效果和渐变效果的亮度控制变量
  • up:控制呼吸灯方向(增亮或减暗)
  • seed:用于生成伪随机数的种子

延时函数

void Delay_ms(uint ms) {
    uint i, j;
    for (i = 0; i < ms; i++)
        for (j = 0; j < 123; j++);
}
  • 实现毫秒级延时
  • 参数ms指定延时时间(毫秒)
  • 循环次数123根据单片机的晶振频率设定

按键扫描函数

void KeyScan() {
    uchar key = P3 ^ 0xFF;  // 获取按键值(P3.0~P3.7)
    uchar i; 
    for (i = 0; i < 8; i++) {
        if ((key >> i) & 0x01) {
            mode = i;  // 切换灯效
        }
    }
}
  • 检测P3口的8个按键(按键按下对应引脚为低电平)
  • 通过P3 ^ 0xFF将按下的按键位置为1
  • 循环检查每个位,如果某位为1表示对应按键按下
  • 将按键编号(0-7)赋值给mode变量

PWM输出函数

void RGB_PWM_Output() {
    uchar i; 
    for (i = 0; i < 255; i++) {
        R_LED = (i < R_val) ? 0 : 1;
        G_LED = (i < G_val) ? 0 : 1;
        B_LED = (i < B_val) ? 0 : 1;
    }
}
  • 软件实现的PWM(脉宽调制)输出
  • 通过255次循环模拟PWM周期
  • 当循环计数器i小于目标PWM值时,LED引脚输出低电平(LED亮)
  • 当i大于等于目标PWM值时,LED引脚输出高电平(LED灭)
  • 例如:R_val=255表示全亮,R_val=0表示全灭

随机数生成函数

uchar random() {
    seed = seed * 25173 + 13849;
    return (uchar)(seed >> 8);
}
  • 伪随机数生成器,使用线性同余法
  • 25173和13849是算法参数
  • 返回种子值的高8位作为随机数(0-255)

颜色设置函数

void SetColor(uchar r, uchar g, uchar b) {
    R_val = r;
    G_val = g;
    B_val = b;
}
  • 设置RGB三个通道的PWM值
  • 参数r、g、b范围为0-255(0为最暗,255为最亮)

主函数框架

void main() {
    while (1) {
        KeyScan();  // 检测按键状态
        
        // 根据mode选择不同的灯光效果
        switch (mode) {
            // 8种灯光效果实现
        }
        
        RGB_PWM_Output();  // 更新LED输出
    }
}
  • 主循环不断检测按键并更新灯光效果
  • 每次循环都会调用RGB_PWM_Output()刷新LED显示

8种灯光效果详解

静态红色 (mode 0)

SetColor(255, 0, 0);
  • 仅红色通道全亮,绿色和蓝色通道全灭
  • 显示纯红色

静态绿色 (mode 1)

SetColor(0, 255, 0);
  • 仅绿色通道全亮
  • 显示纯绿色

静态蓝色 (mode 2)

SetColor(0, 0, 255);
  • 仅蓝色通道全亮
  • 显示纯蓝色

红色呼吸灯 (mode 3)

if (up) breathe += 5; else breathe -= 5;
if (breathe >= 250) up = 0;
if (breathe <= 5) up = 1;
SetColor(breathe, 0, 0);
  • 红色亮度在5-250范围内变化
  • up变量控制亮度变化方向(增亮或减暗)
  • 亮度达到250时反向减暗,达到5时反向增亮
  • 效果:红色渐强渐弱,类似呼吸效果

RGB轮换 (mode 4)

static uchar rgb_state = 0;
switch (rgb_state) {
    case 0: SetColor(255, 0, 0); break;  // 红
    case 1: SetColor(0, 255, 0); break;  // 绿
    case 2: SetColor(0, 0, 255); break;  // 蓝
}
rgb_state++;
if (rgb_state > 2) rgb_state = 0;
Delay_ms(300);
  • 使用静态变量rgb_state保存当前颜色状态
  • 轮流显示红、绿、蓝三种基色
  • 每次切换延时300ms
  • 效果:红→绿→蓝→红…循环变化

彩色渐变 (mode 5)

SetColor(breathe, 255 - breathe, breathe / 2);
if (up) breathe += 3; else breathe -= 3;
if (breathe >= 250) up = 0;
if (breathe <= 5) up = 1;
  • 使用同一个breathe变量控制所有通道
  • 红色通道:从暗到亮(breathe)
  • 绿色通道:从亮到暗(255 – breathe)
  • 蓝色通道:半亮度(breathe / 2)
  • 效果:红绿渐变,蓝色辅助的连续变化

随机闪烁 (mode 6)

SetColor(random(), random(), random());
Delay_ms(150);
  • 调用random()生成RGB值(0-255)
  • 每次随机设置颜色后延时150ms
  • 效果:LED快速显示不同随机颜色

关闭LED (mode 7)

SetColor(0, 0, 0);
  • RGB全部设置为0(全灭)
  • LED熄灭

优化建议

  • 增加按键消抖
  • 使用硬件定时器改进PWM
    • 使用51单片机的定时器中断实现更精确的PWM
    • 避免主循环被长时间阻塞
  • 增加亮度平滑渐变
    • 在模式切换时添加过渡效果
    • 避免颜色突变造成突兀感
  • 保存最后模式
    • 在EEPROM保存最后选择的模式
    • 重启后恢复之前的灯光效果

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注