发作品签到
标准版

3路LED 23kHz高频PWM驱动

工程标签

1.1k
0
0
6

简介

46.875KHz 高频PWM无极调光,结构简单,不伤眼,但是有拍摄需求的请注意。

简介:46.875KHz 高频PWM无极调光,结构简单,不伤眼,但是有拍摄需求的请注意。

开源协议

GPL 3.0

(未经作者授权,禁止转载)
克隆自2路LED
创建时间:2023-08-02 05:30:57更新时间:2024-07-05 02:33:49

描述

2024年7月4日20点57分 更新

1.修复了部分型号LDO上电概率损坏的问题。

************************************************************************************

构成简单,用了两三年了,因太简单了没想着开源,不过本着能给更多人方便,现公开。


高频PWM驱动,利用STC8G1K08A(0.9元左右)单片机的硬件PWM控制,无极调光。
“根据GB/T31831-2015规范,在频率为9Hz至3125Hz时,波动深度高于f*0.08/2.5%,就可能会对人体造成影响。 而LCD显示器的LED背光的波动率一般都为100%,所以,就算在全黑环境中使用PWM调光的LCD显示器,只要显示器LED背光的PWM频率超过3125Hz,频闪就不会对身体造成任何影响,不用担心伤眼问题。”

单片机24Mhz时钟下,4分频,256位,最终调光频率 24E6/4/256 = 23KHz,超出人耳听觉范围。

可自行修改代码,实现更高频率和PWM分辨率。
请注意,本PWM虽然不伤眼,但是相机一类数码产品对闪烁敏感。
如果您有拍摄需求,请谨慎(本人小米10 LineageOS20 拍摄无闪烁)

 

3路PWM,可以控制3路灯光,注意是PWM直驱,注意电压,可以是12V,24V或者其他,但是LDO线性降压芯片 和 NMOS耐压要支持,同时直驱的LED也要相同耐压,建议使用线性灯灯条,用了两三年没有出过问题。

只适配灯条(线性灯),恒流LED不要使用!!

3路LED,每路LED 3个亮度档位,每个档位单独无极调光。

默认 1档最暗 2档中等 3档最亮。

按住调节亮度。亮度信息 总电源断电(非关闭LED) 消失,恢复默认亮度。

 

STC8G1K08A 1个  要有A  24MHz时钟

LDO线性降压 1个   注意耐压

TO-252 NMOS 3个(本工程AOD4184)

XH2.54 3套

0.1uf 10uf 各2个

1K电阻 3个

 

 

作为唯一光源时,拍摄无闪烁

 

文件列表有编译后的hex文件,直接烧录就好。

以下是源码,几年前写的,水平不行,勿喷:

 

#include                                 // 此处STC8G.h 文件可以从STC烧录软件中获得,保存在源码同目录下
#include

 

#define uchar unsigned char
#define uint unsigned int
    
#define     PWM_DUTY        255                //定义PWM的周期,数值为时钟周期数
#define     PWM_CHANGE      1                  //定义PWM一次改变的数值,暂时只能1,目前代码没有判断是否加减过头的判断,后续需要完善
#define     PWM_DUTY_MAX    PWM_DUTY-10     //限制PWM输出的最大占空比,也就是最小亮度
#define     PWM_DUTY_MIN    0                         //限制PWM输出的最小占空比,也就是最大亮度
#define     SWITCH_TIME     6000           //开关变换等待时间,用来防抖
#define     DELAY_TIME      15000           //亮度调节速度,越小越快

 

//#def ine FOSC 24000000UL
//#define BRT (65536 - FOSC / 115200 / 4) 

 

// 默认24MHz,可增加频率,如果要用串口,则需要注意
// PWM输出引脚需要设置PCA的引脚,在3.1.1 章节
// 默认 PCA_PWM0 P32  PCA_PWM1 P33  PCA_PWM2 P54

 

// 24E6/2/256 = 46.875KHz

// 24E6/4/256 = 23.437KHz(默认)

 

sbit    key_1 = P3^0;
sbit    key_2 = P3^1;
sbit    key_3 = P5^5;

uint    pwm_duty1[4],pwm_duty2[4],pwm_duty3[4];                               //三个占空比数组
uchar        pwm_duty1_sub = 0,pwm_duty2_sub = 0,pwm_duty3_sub = 0;    //占空比数组下标,0-2对应上面数组,3为关灯
bit            switch_sta1 = 0,switch_sta2 = 0,switch_sta3 = 0;                    //按住调节增加或者减少,0减少,1增加

//10位PWMPCA初始化
void PCA_Init()
{
        CCON=0x00;  //关闭PCA计数器,清除相关标志位
        CMOD=0x0A;  //PCA时钟源为系统时钟,0x08系统时钟,0x02系统时钟/2,0x0A /4 ( 默认 ) ,0x0C /6 , 0x0E /8 , 0x00 /12 , 0x04 定时器0溢出时间, 0x06 外部时钟
        CL  =0x00;  //计数器清零
        CH  =0x00;
/*------------------------PWM0部分-----------------------------*/
        CCAPM0 = 0x40;  //失能PCA模块0_PWM输出
        CCAP0L=0X00;    //捕获比较寄存器低8位,比较值
        CCAP0H=0X00;    //捕获比较寄存器高8位,重装值
        PCA_PWM0=0x00;  //10位PWM输出 0xC0,8位为 0x00
        CCAPM0=0x42; //使能PCA模块0_PWM输出
        
/*------------------------PWM1部分-----------------------------*/
        CCAPM1 = 0x40;  //失能PCA模块1_PWM输出
        CCAP1L=0X00;    //捕获比较寄存器低8位,比较值
        CCAP1H=0X00;    //捕获比较寄存器高8位,重装值
        PCA_PWM1=0x00; //10位PWM输出 0xC0,8位为 0x00
        CCAPM1=0x42; //使能PCA模块1_PWM输出
 
/*------------------------PWM2部分-----------------------------*/
        CCAPM2 = 0x40;  //失能PCA模块2_PWM输出
        CCAP2L=0X00;    //捕获比较寄存器低8位,比较值
        CCAP2H=0X00;    //捕获比较寄存器高8位,重装值
        PCA_PWM2=0x00; //10位PWM输出 0xC0,8位为 0x00
        CCAPM2=0x42; //使能PCA模块2_PWM输出    
                
                
        //CCON|=  1<<6;   //启动计数器
                CR = 1;         //启动计数器
}
//设置脉冲宽度,设置的是低电平宽度,比如 PWM_DUTY/4,则高电平75%低电平25%
void PWM0_Set_Duty(uint Duty)
{
        //注意:在更新 10 位 PWM 的重载值时,必须先写高两位 XCCAPnH[1:0],再写低 8 位 CCAPnH[7:0]。
                //================= 8 位 代码
                CCAP0L = Duty;
                CCAP0H = Duty;
                //================= 8 位 代码
}


//设置脉冲宽度,设置的是低电平宽度,比如 PWM_DUTY/4,则高电平75%低电平25%
void PWM1_Set_Duty(uint Duty)
{
        //注意:在更新 10 位 PWM 的重载值时,必须先写高两位 XCCAPnH[1:0],再写低 8 位 CCAPnH[7:0]。
                //================= 8 位 代码
                CCAP1L = Duty;
                CCAP1H = Duty;
                //================= 8 位 代码
        //CCAPM1   = 0x42;           //使能PCA模块0_PWM输出
}

//设置脉冲宽度,设置的是低电平宽度,比如 PWM_DUTY/4,则高电平75%低电平25%
void PWM2_Set_Duty(uint Duty)
{
        //注意:在更新 10 位 PWM 的重载值时,必须先写高两位 XCCAPnH[1:0],再写低 8 位 CCAPnH[7:0]。
                //================= 8 位 代码
                CCAP2L = Duty;
                CCAP2H = Duty;
                //================= 8 位 代码
        //CCAPM2   = 0x42;           //使能PCA模块0_PWM输出
}
void main()
{
    uint wait_time11 = 0,wait_time12 = 0; // key_1 计时用
    uint wait_time21 = 0,wait_time22 = 0; // key_2 计时用
    uint wait_time31 = 0,wait_time32 = 0; // key_3 计时用
    P5M1 = 0x00;  //P5.4设置为推挽输出
  P5M0 = 0x10;
    P3M1 = 0x00;  //P3.2,P3.3 为推挽输出
    P3M0 = 0x0C;
    key_1 = 1,key_2 = 1,key_3 = 1;
    pwm_duty1[0] = PWM_DUTY_MAX,pwm_duty1[1] = PWM_DUTY/2,pwm_duty1[2] = PWM_DUTY_MIN;
    pwm_duty2[0] = PWM_DUTY_MAX,pwm_duty2[1] = PWM_DUTY/2,pwm_duty2[2] = PWM_DUTY_MIN;
    pwm_duty3[0] = PWM_DUTY_MAX,pwm_duty3[1] = PWM_DUTY/2,pwm_duty3[2] = PWM_DUTY_MIN;
    pwm_duty1_sub = 3,pwm_duty2_sub = 3,pwm_duty3_sub = 3;            //占空比数组下标,3为关
    PCA_Init();
    //PWM0_Set_Duty(pwm_duty1[0]);
    //PWM1_Set_Duty(pwm_duty2[0]);
    //PWM2_Set_Duty(pwm_duty2[0]);
    PWM0_Set_Duty(PWM_DUTY);
    CCAPM0   = 0x40;           //失能PCA模块0_PWM输出
    P32 = 0;
    PWM1_Set_Duty(PWM_DUTY);
    CCAPM1   = 0x40;           //失能PCA模块1_PWM输出
    P33 = 0;
    PWM2_Set_Duty(PWM_DUTY);
    CCAPM2   = 0x40;           //失能PCA模块2_PWM输出
    P54 = 0;
    while(1)
    {
         if(key_1 == 0)
         {
             wait_time11++;
             if(wait_time11 >= 65535)
                 wait_time12++;
             if(wait_time12 >= 5)
             {
                 uint wait_time = 0;
                 wait_time11 = 0;
                 wait_time12 = 0;
                 switch_sta1 == 1 ? (switch_sta1 = 0):(switch_sta1 = 1);
                 //+ 开始了按住
                 while(key_1 == 0 && pwm_duty1_sub < 3)
                 {
                     wait_time++;
                     if(wait_time >= DELAY_TIME)
                     {
                         wait_time = 0;
                         if(switch_sta1 == 1)//增加
                         {
                             if(pwm_duty1[pwm_duty1_sub] > 0)
                                 pwm_duty1[pwm_duty1_sub]--;
                         }else{                             //减少
                             if(pwm_duty1[pwm_duty1_sub] < PWM_DUTY_MAX)
                                 pwm_duty1[pwm_duty1_sub]++;
                         }
                         PWM0_Set_Duty(pwm_duty1[pwm_duty1_sub]);
                     }
                }
             }
         }else if(wait_time11 > SWITCH_TIME && wait_time12 < 5)
         {
             //+ 短按一次
             wait_time11 = 0;
             wait_time12 = 0;
             pwm_duty1_sub++;
             if(pwm_duty1_sub > 3)
                 pwm_duty1_sub = 0;
             if(pwm_duty1_sub < 3)
             {
                 CCAPM0   = 0x42;           //使能PCA模块0_PWM输出
                 PWM0_Set_Duty(pwm_duty1[pwm_duty1_sub]);
             }else{
                 PWM0_Set_Duty(PWM_DUTY);
                 CCAPM0   = 0x40;           //失能PCA模块0_PWM输出
                 P32 = 0;
             }
             /*
             SBUF=pwm_duty1_sub;//将接收到的数据放入到发送寄存器
             while(!TI);
             TI = 0;
             
             SBUF=pwm_duty1[pwm_duty1_sub];//将接收到的数据放入到发送寄存器
             while(!TI);
             TI = 0;
             */
         }else{
             wait_time11 = 0;
             wait_time12 = 0;
         }
        if(key_2 == 0)
         {
             wait_time21++;
             if(wait_time21 >= 65535)
                 wait_time22++;
             if(wait_time22 >= 5)
             {
                 uint wait_time = 0;
                 wait_time21 = 0;
                 wait_time22 = 0;
                 switch_sta2 == 1 ? (switch_sta2 = 0):(switch_sta2 = 1);
                 //+ 开始了按住
                 while(key_2 == 0 && pwm_duty2_sub < 3)
                 {
                     wait_time++;
                     if(wait_time >= DELAY_TIME)
                     {
                         wait_time = 0;
                         if(switch_sta2 == 1)//增加
                         {
                             if(pwm_duty2[pwm_duty2_sub] > 0)
                                 pwm_duty2[pwm_duty2_sub]--;
                         }else{                             //减少
                             if(pwm_duty2[pwm_duty2_sub] < PWM_DUTY_MAX)
                                 pwm_duty2[pwm_duty2_sub]++;
                         }
                         PWM1_Set_Duty(pwm_duty2[pwm_duty2_sub]);
                     }
                }
             }
         }else if(wait_time21 > SWITCH_TIME && wait_time22 < 5)
         {
             //+ 短按一次
             wait_time21 = 0;
             wait_time22 = 0;
             pwm_duty2_sub++;
             if(pwm_duty2_sub > 3)
                 pwm_duty2_sub = 0;
             if(pwm_duty2_sub < 3)
             {
                 CCAPM1   = 0x42;           //使能PCA模块1_PWM输出
                 PWM1_Set_Duty(pwm_duty2[pwm_duty2_sub]);
             }else{
                 PWM1_Set_Duty(PWM_DUTY);
                 CCAPM1   = 0x40;           //失能PCA模块1_PWM输出
                 P33 = 0;
             }
             /*
             SBUF=pwm_duty2_sub;//将接收到的数据放入到发送寄存器
             while(!TI);
             TI = 0;
             
             SBUF=pwm_duty1[pwm_duty2_sub];//将接收到的数据放入到发送寄存器
             while(!TI);
             TI = 0;
             */
         }else{
             wait_time21 = 0;
             wait_time22 = 0;
         }
         if(key_3 == 0)
         {
             wait_time31++;
             if(wait_time31 >= 65535)
                 wait_time32++;
             if(wait_time32 >= 5)
             {
                 uint wait_time = 0;
                 wait_time31 = 0;
                 wait_time32 = 0;
                 switch_sta3 == 1 ? (switch_sta3 = 0):(switch_sta3 = 1);
                 //+ 开始了按住
                 while(key_3 == 0 && pwm_duty3_sub < 3)
                 {
                     wait_time++;
                     if(wait_time >= DELAY_TIME)
                     {
                         wait_time = 0;
                         if(switch_sta3 == 1)//增加
                         {
                             if(pwm_duty3[pwm_duty3_sub] > 0)
                                 pwm_duty3[pwm_duty3_sub]--;
                         }else{                             //减少
                             if(pwm_duty3[pwm_duty3_sub] < PWM_DUTY_MAX)
                                 pwm_duty3[pwm_duty3_sub]++;
                         }
                         PWM2_Set_Duty(pwm_duty3[pwm_duty3_sub]);
                     }
                }
             }
         }else if(wait_time31 > SWITCH_TIME && wait_time32 < 5)
         {
             //+ 短按一次
             wait_time31 = 0;
             wait_time32 = 0;
             pwm_duty3_sub++;
             if(pwm_duty3_sub > 3)
                 pwm_duty3_sub = 0;
             if(pwm_duty3_sub < 3)
             {
                 CCAPM2   = 0x42;           //使能PCA模块2_PWM输出
                 PWM2_Set_Duty(pwm_duty3[pwm_duty3_sub]);
             }else{
                 PWM2_Set_Duty(PWM_DUTY);
                 CCAPM2   = 0x40;           //失能PCA模块2_PWM输出
                 P54 = 0;
             }
         }else{
             wait_time31 = 0;
             wait_time32 = 0;
         }
    }
}

设计图

原理图
PCB

BOM

IDNameDesignatorFootprintQuantity
10.1uFC1,C2C06032
210uFC3,C4C06032
3LED 3 mosQ1TO-252-2_L6.6-W6.1-P4.57-LS9.9-BR-CW1
4LED 2 mosQ2TO-252-2_L6.6-W6.1-P4.57-LS9.9-BR-CW1
5LED 1 mosQ3TO-252-2_L6.6-W6.1-P4.57-LS9.9-BR-CW1

附件

序号文件名称下载次数
1
3路LED.hex
17
克隆工程
添加到专辑
0
0
分享
侵权投诉

工程成员

评论

全部评论(1)
按时间排序|按热度排序
粉丝0|获赞0
相关工程
暂无相关工程

底部导航