找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 910|回复: 3
打印 上一主题 下一主题
收起左侧

有兴趣的可以试写一下这个程序玩玩,可以从中学到好多东西

[复制链接]
跳转到指定楼层
楼主
ID:59341 发表于 2026-9-3 11:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
采用SOP14脚的任意一款单片机(需要带AD及PWM功能,比如FMD的FT61E132A)或是用8脚的FT61EC21A 也可以,或是STC的单片机,或是中微的,或是九齐的,功能如下:

长按3秒开机或关机,短按调档,PWM输出分别是20%、 40%、60%、80%、100%、0,采用RGB共阳发光管,PWM档位分别对应的指示灯蓝 绿 黄 橙 红 白。

1.电源电压10.6-11.4 V之间,PWM不输出,不加热,隔1秒呼吸一次,呼吸一次2.5秒,呼吸3次待机。

2. 电源电压11.5~12.9V,加热 ,每隔5s停止加热4.5秒(即2.5秒呼吸前后各加1秒灯不亮,然后持续1分钟后待机,也就是加热5S,然后PWM无输出也不亮灯1秒+2.5秒呼吸灯和PWM无输出+PWM无输出也不亮灯1秒);

3.电源电压13~13.4V,持续加热2分钟后停止加热,然后每隔1秒呼吸一次(呼吸一次2.5秒),第3分钟后待机;
4.电源电压≥13.5V开启正常持续加热。
5. 为了防止停止负载时的电压回跳而导致的状态跳变,一旦触发低电压保护就不执行回弹的电压,但可以进入更低一级的电压保护。在任一电压阶段执行待机以后,不再执行临近电压档,仅在电压高于13.5V 可自动启动,或者短按任一按键可以再启动,启动后按当下实际电压状态运行。
6.待机状态定义:灯不亮、没有输出;任一按键短按可以激活,激活后按照记忆档位、当下电压阶段运行。如果电压≥13.5V,自动激活并开始按照记忆档位运行。
7.呼吸灯频率:当下档位对应LED呼吸,呼吸一次2.5秒。
8.电压低于10.5伏不再自启动,进入低功耗保护。仅按键响应。

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:59341 发表于 2026-9-4 07:50 | 只看该作者
准备有AI试试
回复

使用道具 举报

板凳
ID:325985 发表于 2026-9-6 11:35 | 只看该作者
#include <reg52.h>
#include <intrins.h>

// 引脚定义
sbit KEY = P1^0;          // 按键输入(低电平有效)
sbit LED_R = P2^0;        // 红色LED(共阳极,低电平点亮)
sbit LED_G = P2^1;        // 绿色LED
sbit LED_B = P2^2;        // 蓝色LED
sbit HEAT = P2^3;         // 加热输出(高电平有效)

// 全局变量
volatile unsigned char pwm_cnt = 0;          // PWM计数器 0~19
volatile unsigned char pwm_thr_r = 20;       // 红色PWM阈值
volatile unsigned char pwm_thr_g = 20;
volatile unsigned char pwm_thr_b = 20;
volatile unsigned char pwm_thr_heat = 0;

volatile unsigned char breath_active = 0;    // 呼吸使能
volatile unsigned char breath_factor = 20;   // 呼吸亮度因子 0~20
volatile unsigned char breath_dir = 0;       // 方向 0:升 1:降
volatile unsigned char breath_cycle_done = 0;// 一次呼吸完成标志
volatile unsigned int breath_step_timer = 0; // 125ms步进计时

volatile unsigned int sys_tick_ms = 0;       // 系统毫秒计数器
volatile unsigned char flag_10ms = 0;        // 10ms定时标志

// 颜色目标亮度(0~20),对应蓝、绿、黄、橙、红、白
code unsigned char color_table[6][3] = {
    {0, 0, 20},   // 蓝
    {0, 20, 0},   // 绿
    {20, 20, 0},  // 黄
    {20, 10, 0},  // 橙(红多绿少)
    {20, 0, 0},   // 红
    {20, 20, 20}  // 白
};
unsigned char color_target_r, color_target_g, color_target_b;

// 档位占空比(%)
code unsigned char duty_percent[6] = {20, 40, 60, 80, 100, 0};
unsigned char duty_idx = 0;                  // 当前档位索引

// 系统状态
typedef enum {
    SYS_OFF,
    SYS_STANDBY,
    SYS_RUNNING,
    SYS_LOWPROTECT
} SysState;
SysState sys_state = SYS_OFF;

// 电压阶段
#define STAGE_LOW       0   // <10.5V
#define STAGE_106_114   1   // 10.6~11.4V
#define STAGE_115_129   2   // 11.5~12.9V
#define STAGE_130_134   3   // 13.0~13.4V
#define STAGE_135PLUS   4   // ≥13.5V
unsigned char current_stage = STAGE_LOW;

// 运行子状态
unsigned char sub_state = 0;
unsigned int sub_timer = 0;          // 子状态计时(ms)
unsigned int stage_total = 0;        // 阶段累计计时(ms)

// 按键相关
unsigned char key_press_flag = 0;
unsigned int key_press_time = 0;
unsigned char key_long_press = 0;
unsigned char key_short_press = 0;

// 功能控制标志
unsigned char heat_enable = 0;
unsigned char led_on = 0;

// 函数声明
void Timer0_Init(void);
void KeyScan(void);
void UpdatePWMThresholds(void);
void EnterStage(unsigned char stage);
void UpdateRunningSubState(void);
void EnterStandby(void);
void EnterLowProtect(void);
void Activate(void);
unsigned int GetVoltage(void);        // 返回mV,需用户实现
unsigned char GetVoltageStage(unsigned int v);

// 定时器0中断(1ms)
void Timer0_ISR() interrupt 1 {
    // 重装初值(12MHz,1ms)
    TH0 = 0xFC;
    TL0 = 0x18;

    // PWM计数器更新(周期20ms)
    pwm_cnt++;
    if (pwm_cnt >= 20) pwm_cnt = 0;

    // 输出PWM比较(共阳极:阈值越小越亮)
    LED_R = (pwm_cnt < pwm_thr_r) ? 1 : 0;
    LED_G = (pwm_cnt < pwm_thr_g) ? 1 : 0;
    LED_B = (pwm_cnt < pwm_thr_b) ? 1 : 0;
    HEAT  = (pwm_cnt < pwm_thr_heat) ? 1 : 0;

    // 呼吸步进(每125ms更新一次)
    breath_step_timer++;
    if (breath_step_timer >= 125) {
        breath_step_timer = 0;
        if (breath_active) {
            if (breath_dir == 0) {      // 上升
                breath_factor++;
                if (breath_factor >= 20) {
                    breath_factor = 20;
                    breath_dir = 1;
                }
            } else {                    // 下降
                breath_factor--;
                if (breath_factor == 0) {
                    breath_factor = 0;
                    breath_dir = 0;
                    breath_cycle_done = 1;  // 完成一个呼吸周期
                }
            }
            // 更新PWM阈值(呼吸因子变化时)
            UpdatePWMThresholds();
        }
    }

    // 系统毫秒计数
    sys_tick_ms++;
    // 10ms标志
    if (sys_tick_ms % 10 == 0) flag_10ms = 1;
}

// 更新PWM阈值
void UpdatePWMThresholds(void) {
    unsigned char factor = breath_active ? breath_factor : 20;
    if (!led_on) {
        pwm_thr_r = 20;
        pwm_thr_g = 20;
        pwm_thr_b = 20;
    } else {
        pwm_thr_r = 20 - (color_target_r * factor / 20);
        pwm_thr_g = 20 - (color_target_g * factor / 20);
        pwm_thr_b = 20 - (color_target_b * factor / 20);
    }
    // 加热阈值
    if (heat_enable) {
        unsigned char duty = duty_percent[duty_idx];
        pwm_thr_heat = duty * 20 / 100;
    } else {
        pwm_thr_heat = 0;
    }
}

// 获取电压阶段
unsigned char GetVoltageStage(unsigned int v) {
    if (v < 10500) return STAGE_LOW;
    else if (v < 11500) return STAGE_106_114;   // 10.6~11.4
    else if (v < 13000) return STAGE_115_129;   // 11.5~12.9
    else if (v < 13500) return STAGE_130_134;   // 13.0~13.4
    else return STAGE_135PLUS;
}

// 进入运行阶段(重置计时,初始化子状态)
void EnterStage(unsigned char stage) {
    current_stage = stage;
    sub_timer = 0;
    stage_total = 0;
    // 先关闭所有
    heat_enable = 0;
    led_on = 0;
    breath_active = 0;
    breath_cycle_done = 0;
    breath_factor = 20;
    breath_dir = 0;

    switch(stage) {
        case STAGE_106_114:
            heat_enable = 0;
            led_on = 1;
            breath_active = 1;
            breath_factor = 0;   // 从暗开始
            breath_dir = 0;
            sub_state = 0;       // 0:呼吸, 1:等待
            break;
        case STAGE_115_129:
            heat_enable = 1;
            led_on = 1;
            breath_active = 0;
            sub_state = 0;       // 0:加热, 1:灭灯1, 2:呼吸, 3:灭灯2
            break;
        case STAGE_130_134:
            heat_enable = 1;
            led_on = 1;
            breath_active = 0;
            sub_state = 0;       // 0:加热, 1:呼吸等待
            break;
        case STAGE_135PLUS:
            heat_enable = 1;
            led_on = 1;
            breath_active = 0;
            sub_state = 0;
            break;
        default:
            break;
    }
    UpdatePWMThresholds();
}

// 更新运行子状态(每10ms调用)
void UpdateRunningSubState(void) {
    static unsigned char wait_breath_sub = 0;      // 用于高阶段呼吸子状态
    static unsigned int wait_breath_timer = 0;

    switch(current_stage) {
        case STAGE_106_114:
            // 子状态0:呼吸, 1:等待
            if (sub_state == 0) {
                if (breath_cycle_done) {
                    breath_cycle_done = 0;
                    // 一次呼吸完成
                    stage_total += 2500;  // 累计呼吸时间
                    if (stage_total >= 7500) { // 3次呼吸完成(每次2.5s)
                        EnterStandby();
                        return;
                    } else {
                        // 进入等待1秒
                        sub_state = 1;
                        sub_timer = 0;
                        led_on = 0;
                        breath_active = 0;
                        UpdatePWMThresholds();
                    }
                }
            } else { // 等待
                sub_timer += 10;
                if (sub_timer >= 1000) {
                    sub_timer = 0;
                    sub_state = 0;
                    led_on = 1;
                    breath_active = 1;
                    breath_factor = 0;
                    breath_dir = 0;
                    breath_cycle_done = 0;
                    UpdatePWMThresholds();
                }
            }
            break;

        case STAGE_115_129:
            // 子状态: 0加热, 1灭灯1, 2呼吸, 3灭灯2
            sub_timer += 10;
            if (sub_state == 0) { // 加热5s
                if (sub_timer >= 5000) {
                    sub_timer = 0;
                    sub_state = 1;
                    heat_enable = 0;
                    led_on = 0;
                    breath_active = 0;
                    UpdatePWMThresholds();
                }
            } else if (sub_state == 1) { // 灭灯1s
                if (sub_timer >= 1000) {
                    sub_timer = 0;
                    sub_state = 2;
                    led_on = 1;
                    breath_active = 1;
                    breath_factor = 0;
                    breath_dir = 0;
                    breath_cycle_done = 0;
                    UpdatePWMThresholds();
                }
            } else if (sub_state == 2) { // 呼吸2.5s
                if (breath_cycle_done) {
                    breath_cycle_done = 0;
                    sub_timer = 0;
                    sub_state = 3;
                    led_on = 0;
                    breath_active = 0;
                    UpdatePWMThresholds();
                }
            } else if (sub_state == 3) { // 灭灯1s
                if (sub_timer >= 1000) {
                    sub_timer = 0;
                    stage_total += 9500; // 5+1+2.5+1 = 9.5s
                    if (stage_total >= 60000) {
                        EnterStandby();
                        return;
                    } else {
                        sub_state = 0;
                        heat_enable = 1;
                        led_on = 1;
                        breath_active = 0;
                        UpdatePWMThresholds();
                    }
                }
            }
            break;

        case STAGE_130_134:
            // 子状态: 0加热2min, 1呼吸等待(持续1min)
            sub_timer += 10;
            if (sub_state == 0) {
                if (sub_timer >= 120000) { // 2分钟
                    sub_timer = 0;
                    sub_state = 1;
                    heat_enable = 0;
                    led_on = 1;
                    breath_active = 1;
                    breath_factor = 0;
                    breath_dir = 0;
                    breath_cycle_done = 0;
                    wait_breath_sub = 0;   // 0:呼吸, 1:等待
                    wait_breath_timer = 0;
                    UpdatePWMThresholds();
                }
            } else { // 呼吸+等待循环,持续1分钟
                if (wait_breath_sub == 0) { // 呼吸
                    if (breath_cycle_done) {
                        breath_cycle_done = 0;
                        wait_breath_sub = 1;
                        wait_breath_timer = 0;
                        led_on = 0;
                        breath_active = 0;
                        UpdatePWMThresholds();
                    }
                } else { // 等待1s
                    wait_breath_timer += 10;
                    if (wait_breath_timer >= 1000) {
                        wait_breath_timer = 0;
                        stage_total += 3500; // 2.5+1
                        if (stage_total >= 60000) {
                            EnterStandby();
                            return;
                        } else {
                            wait_breath_sub = 0;
                            led_on = 1;
                            breath_active = 1;
                            breath_factor = 0;
                            breath_dir = 0;
                            breath_cycle_done = 0;
                            UpdatePWMThresholds();
                        }
                    }
                }
            }
            break;

        case STAGE_135PLUS:
            // 持续加热,无需更新
            break;
        default:
            break;
    }
}

// 进入待机
void EnterStandby(void) {
    sys_state = SYS_STANDBY;
    heat_enable = 0;
    led_on = 0;
    breath_active = 0;
    UpdatePWMThresholds();
}

// 进入低电压保护
void EnterLowProtect(void) {
    sys_state = SYS_LOWPROTECT;
    heat_enable = 0;
    led_on = 0;
    breath_active = 0;
    UpdatePWMThresholds();
}

// 激活(待机或低保护->运行)
void Activate(void) {
    unsigned int v = GetVoltage();
    unsigned char stage = GetVoltageStage(v);
    if (stage == STAGE_LOW) {
        // 低于10.5V不允许激活
        return;
    }
    sys_state = SYS_RUNNING;
    EnterStage(stage);
}

// 按键扫描(10ms调用)
void KeyScan(void) {
    static unsigned char last_key = 1;
    static unsigned int press_cnt = 0;
    unsigned char cur_key = KEY;

    if (cur_key == 0 && last_key == 1) { // 按下
        press_cnt = 0;
        key_press_flag = 1;
    } else if (cur_key == 0 && key_press_flag) {
        press_cnt++;
        if (press_cnt >= 300) { // 3秒(10ms*300)
            key_long_press = 1;
            key_press_flag = 0; // 防止重复触发
        }
    } else if (cur_key == 1 && last_key == 0) { // 释放
        if (key_press_flag && press_cnt < 300 && press_cnt > 5) {
            key_short_press = 1;
        }
        key_press_flag = 0;
        press_cnt = 0;
    }
    last_key = cur_key;
}

// 主函数
void main(void) {
    // 初始化
    Timer0_Init();
    // 默认颜色(蓝)
    color_target_r = color_table[0][0];
    color_target_g = color_table[0][1];
    color_target_b = color_table[0][2];
    UpdatePWMThresholds();
    sys_state = SYS_OFF;

    while(1) {
        if (flag_10ms) {
            flag_10ms = 0;

            // 按键扫描
            KeyScan();

            // 处理按键事件
            if (key_long_press) {
                key_long_press = 0;
                if (sys_state == SYS_OFF) {
                    // 开机
                    unsigned int v = GetVoltage();
                    unsigned char stage = GetVoltageStage(v);
                    if (stage != STAGE_LOW) {
                        sys_state = SYS_RUNNING;
                        EnterStage(stage);
                    } else {
                        // 电压过低,不开机
                        sys_state = SYS_OFF;
                    }
                } else {
                    // 关机
                    sys_state = SYS_OFF;
                    heat_enable = 0;
                    led_on = 0;
                    breath_active = 0;
                    UpdatePWMThresholds();
                }
            }

            if (key_short_press) {
                key_short_press = 0;
                // 短按:切换档位
                duty_idx = (duty_idx + 1) % 6;
                color_target_r = color_table[duty_idx][0];
                color_target_g = color_table[duty_idx][1];
                color_target_b = color_table[duty_idx][2];
                UpdatePWMThresholds();

                // 待机状态短按激活
                if (sys_state == SYS_STANDBY) {
                    Activate();
                }
                // 低保护下短按仅调档但不激活(实际上低保护时我们不应调档,这里忽略)
                // 若处于低保护,调档无效(可恢复颜色,但无输出)
                if (sys_state == SYS_LOWPROTECT) {
                    // 不激活,但可调档(无输出)
                }
            }

            // 电压检测(每100ms测一次)
            static unsigned int vdetect_cnt = 0;
            vdetect_cnt++;
            if (vdetect_cnt >= 10) { // 100ms
                vdetect_cnt = 0;
                unsigned int v = GetVoltage();
                unsigned char new_stage = GetVoltageStage(v);

                // 状态机处理
                switch(sys_state) {
                    case SYS_OFF:
                        // 不处理
                        break;
                    case SYS_LOWPROTECT:
                        if (new_stage == STAGE_135PLUS) {
                            Activate();
                        }
                        break;
                    case SYS_STANDBY:
                        if (new_stage == STAGE_135PLUS) {
                            Activate();
                        }
                        break;
                    case SYS_RUNNING:
                        // 防回跳:只允许下降或升到13.5V以上
                        if (new_stage == STAGE_LOW) {
                            // 进入低保护
                            EnterLowProtect();
                        } else if (new_stage < current_stage) {
                            // 降到更低阶段
                            current_stage = new_stage;
                            EnterStage(new_stage);
                        } else if (new_stage > current_stage && new_stage == STAGE_135PLUS) {
                            // 升到正常阶段(13.5以上)
                            current_stage = new_stage;
                            EnterStage(new_stage);
                        }
                        // 否则保持不变,继续运行子状态
                        UpdateRunningSubState();
                        break;
                }
            }
        }
    }
}

// 定时器0初始化(1ms)
void Timer0_Init(void) {
    TMOD &= 0xF0;
    TMOD |= 0x01;      // 16位定时器
    TH0 = 0xFC;
    TL0 = 0x18;
    ET0 = 1;
    EA = 1;
    TR0 = 1;
}

// 模拟ADC读取电压(需根据实际硬件替换)
unsigned int GetVoltage(void) {
    // 此处应实现真实ADC转换,返回单位mV
    // 例:假设P1.1接电压采样,使用STC内部ADC
    // 暂时返回一个固定值用于调试(如12.0V)
    return 12000;
}
回复

使用道具 举报

地板
ID:325985 发表于 2026-9-6 18:21 | 只看该作者
发表于 2026-9-6 11:35
#include
#include

代码说明
PWM输出:使用定时器中断产生20ms周期的PWM,分辨率5%(20步),分别控制RGB三色和加热输出。呼吸灯在125ms步进内更新亮度因子,实现2.5秒一个完整呼吸周期。

电压阶段处理:

STAGE_106_114:呼吸3次,每次间隔1秒,之后待机。

STAGE_115_129:加热5秒 → 灭灯1秒 → 呼吸2.5秒 → 灭灯1秒,循环,累计1分钟后待机。

STAGE_130_134:加热2分钟 → 呼吸(呼吸2.5秒+灭灯1秒)循环,累计3分钟后待机。

STAGE_135PLUS:持续加热,无呼吸。

防回跳与自动启动:

运行中电压只能下降或升到13.5V以上,防止电压回弹引起误动作。

待机或低保护状态下,电压≥13.5V时自动激活。

待机状态下短按按键激活并切换档位;低保护状态下短按仅调档但不激活。

按键逻辑:长按3秒开关机,短按切换档位(待机时先激活再调档)。

待机与低保护:关闭所有输出,仅保留按键响应(低保护下按键可调档但不激活)。

使用注意事项
请根据实际硬件实现 GetVoltage() 函数,读取ADC值并转换为毫伏单位。

若使用STC12/15系列,可启用内部ADC;若为普通51,可外接ADC芯片。

引脚定义、晶振频率需与代码匹配(本代码默认12MHz)。

代码中档位颜色为预设值,可根据需要调整 color_table。

该代码结构清晰,易于移植和调试,能够完整实现题目要求的所有功能。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表