PWM实现线性调光

您所在的位置:网站首页 冬奥会比赛录像回放视频 PWM实现线性调光

PWM实现线性调光

#PWM实现线性调光| 来源: 网络整理| 查看: 265

1.PWM调光原理

PWM全称为脉宽调制技术,是通过高精度的计数器对方波的占空比进行编码。

就是这个东西,其实很好理解,高电平的时候才会做功,低电平的时候肯定不亮啊,PWM就是调制高电平的占比。(其实一般是低电平才有效,因为会外接一个12V的电源,这么说是方便理解)

2. 线性变化描述

举个例子,假如你洗澡要用1吨水,你不可能1秒钟把这一吨水全部倒下来把。光变化也是这样,一下子变过来你眼睛受不了。所以要在规定时间内,尽量均匀的变化,保证在规定时间内完成变化,又要保证变化的过程尽量平缓,斜率尽量固定或者变化不大。

3. 光调制原理

知道彩虹不,这世界其实只有三种颜色,红绿蓝,学美术的应该知道,这三种颜色可以组合出各种不同的颜色。所以通过控制R(红色),G(绿色),B(蓝色)(red,green,blue的缩写)这三种LED的亮度就可以产生理论上你想要的任何颜色。

有个类似这种的表,网上能查到

4. 线性变化算法描述

设置过渡时间的信号从LIN总线过来,值的范围是0~255(8位数据,相当于unsigned char),单位是20ms,我把这个值设为 time。

LIN总线上还会传入需要设置的R,G,B三种颜色的值,也是8位的,我用到的PWM寄存器的大小也是八位。设置需要变化的大小为val。分析以下几种情况:

time >val ; 也就是说单位时间变化1个值就可以在规定时间完成。多余的时间无所谓的

time < val; 就是说单位时间需要变化多个值。我们把单位时间需要变化的值叫做步径,如果变化1个值其实就是步径为1,设步径为step

2*time>val; 步径为2

。。。

step*time>val;步径为step ,这个过程可以用for循环来实现。

我们可以设置一个20ms的中断,在中断中让PWM的值增加步径,就可以完成LED灯的线性变化啦。

5. 代码 5.1 计算步径 //计算PWM步径 //捎带判断了转换时间 void PWM_Calculate_Step() { //如果 要设置的RGB和PWM的值不相等,则需要线性变为需要设置的值 //这部分根据时间设置PWM的线性变化 /* * 变化值和过渡时间都是一个八位的寄存器 * 设变化值为V * 过渡时间为T * 如果 VT 单位时间需要变化多个值,就需要算出步径 * */ //应该在中断里面设置进入 ,退出 中断的条件 也就是 要设置的PWM值和当前值 不相等 在中断服务子程序里面设置退出条件 // if((TargetTransitionTime != 0)&& ((BnIngrd)||(GrnIngrd)||(RedIngrd))) //如果转换时间不为0,且氛围灯RGB不全为0 不一定这么写啊 { if(BnIngrd != PWM22H) { uint8 B_Difference_Value; //变化值 这个是绝对值 //uint8 B_Step;//Step uint8 i_B = 0; //for循环变量,注意要从1开始 //uint8 B_Temp; //暂存变化值 //uint8 Forward_or_Back_Flag_B; //正向或逆向变化标志位 1: 正向 0:逆向 if(BnIngrd > PWM22H) //当前值 大于 前面值 要正向调整 { B_Difference_Value = BnIngrd - PWM22H; Forward_or_Back_Flag_B = 1; //正向 } else//(BnIngrd < PWM22H) { B_Difference_Value = PWM22H - BnIngrd; Forward_or_Back_Flag_B = 0; //逆向 } //B_Temp = B_Difference_Value; for(;((i_B)*(TargetTransitionTime)) < B_Difference_Value; i_B++) { B_Step = i_B; } B_Step = i_B; } if(GrnIngrd != PWM12L) { uint8 G_Difference_Value; //变化值 绝对值 //uint8 G_Step; uint8 i_G = 0; //uint8 Forward_or_Back_Flag_B; if(GrnIngrd > PWM12L) { G_Difference_Value = GrnIngrd - PWM12L; Forward_or_Back_Flag_G = 1; } else { G_Difference_Value = PWM12L - GrnIngrd; Forward_or_Back_Flag_G = 0; } for(;((TargetTransitionTime)*(i_G)) < G_Difference_Value;i_G++) { G_Step = i_G; } G_Step = i_G; } if(RedIngrd != PWM23H) { uint8 R_Difference_Value; //变化值 绝对值 //uint8 R_Step; uint8 i_R = 0; //uint8 Forward_or_Back_Flag_R; if(RedIngrd > PWM23H) { R_Difference_Value = RedIngrd - PWM23H; Forward_or_Back_Flag_R = 1; } else { R_Difference_Value = PWM23H - RedIngrd; Forward_or_Back_Flag_R = 0; } for(;((TargetTransitionTime)*(i_R)) < R_Difference_Value;i_R++) { R_Step = i_R; } R_Step = i_R; } } else { BnIngrd = PWM22H; GrnIngrd = PWM12L; RedIngrd = PWM23H; } } 5.2 中断函数 //Interrupt Function Low Enter void int_fun1() __interrupt (1) { //判断R是正步径还是负步径 ,在中断里面自增或自减 if(Forward_or_Back_Flag_R == 1) { PWM23H += R_Step; } else { PWM23H -= R_Step; } //执行G的自增或自减操作 if(Forward_or_Back_Flag_G == 1) { PWM12L += G_Step; } else { PWM12L -= G_Step; } //执行B的自增或自减操作 if(Forward_or_Back_Flag_B == 1) { PWM22H += B_Step; } else { PWM22H -= B_Step; } //如果要设置的值和寄存器里的值相同 ,则退出中断 if((BnIngrd ==PWM22H) && (GrnIngrd == PWM12L) && (RedIngrd == PWM23H)) { T0IF = 0u; //中断标志位 退出中断 } }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3