《《《《《正文》》》》》
《硬件设计》
控制灯的IO口接芯片即可;
《软件架构》
《软件设计》
我的呼吸灯功能由2个函数实现,一个函数是IO模拟PWM产生波形;另一个函数是控制占空比的改变快慢及大小;他们之间用一个可更改的占空比变量联系;
可更改的占空比变量:
volatile uint16_t pwm_duty=0u; //占空比
1、设计IO模拟PWM波形函数
该函数需要被周期调用,这样是为了可以对时间进行精确的计时,从而实现对占空比的控制,我选择100us的调用周期。
呼吸灯PWM周期的选定,也就是频率,我选择200hz,也就是5ms的周期,可根据实际的情况改变频率,当然前提是不能太低,太低会使led出现明显的闪烁现象;
根据上面100us的函数调用时间,实现5ms的周期的话需要周期计数值为50;这个数决定了你的PWM的可以分得的档次,如果是50,就只有50挡了,相当于最小改变占空比的数值为2%;如果是100,那就有100挡,最小改变占空比为1%;
//PWM周期宏定义 跟调用周期有关
#define BREATH_LEDPWM_PERIOD 50u // 调用周期*50 = 100us*50 =5ms
具体函数:
#define BREATH_LEDPWM_PERIOD 50u
void Led_BreathFunction(void)
{
static uint16_t led_BreathPwmCnt = 0u;
led_BreathPwmCnt++;
if(led_BreathPwmCnt > pwm_duty) //占空比分界点
{
DOORLED_1;//用户实际操作IO电平
}
else
{
DOORLED_0; //用户实际操作IO电平
}
if(led_BreathPwmCnt >= BREATH_LEDPWM_PERIOD) //一个PWM周期完成
{
led_BreathPwmCnt=0u;
}
}
当pwm_duty=25时,相对于周期计数值50,就是一半,即50%的占空比;本人实际测得的波形如下图:
这里多说一句,我们会发现周期是5.013ms,多出了13us,这个就是我在《关于PWM的一些事》那篇文章说的,使用IO模拟PWM时,当高频率的时候,你不得不考虑IO操作电平时的时间,还有程序的运行时间;因此没特殊情况,不推荐使用IO口模拟PWM;本人也不推荐使用IO模拟PWM,所以我这里的程序也只是打个样,代码就不公布,需要的可以私下留言联系;后续会使用STM32的PWM模块实现呼吸灯,提供那一套代码;
2、设计改变占空比函数
决定呼吸快慢有2个因素,第一个因素是占空比改变的快慢,比如30ms或者40ms改变一次占空比;第二个因素是占空比改变的大小,比如一次改变占空比增加5%,或者10%等;
因此同样的,这个函数需要对时间的计数,也需要周期性调用;我使用2ms调用;30ms改变一次占空比,每次占空比改变2%(对应到50的PWM周期计数值,那就是1,这里50最小改变占空比大小为2%);
#define PwmChangePeriod 15 //占空比改变周期 调用周期*15 = 30ms
#define PwmChangeDuty 1 //占空比改变大小 1/BREATH_LEDPWM_PERIOD = 2%
void BreathLed_MainFunction(void)
{
static uint16_t Cnt_ = 0U; //改变占空比周期计数值
static uint8_t breathFlag =TRUE; //占空比递加减状态标志:TRUE:递加 FALSE:递减
Cnt_++;
if(Cnt_>PwmChangePeriod ) //到达改变占空比的时间,30ms
{
Cnt_ = 0U;
if(breathFlag) //占空比递加状态,就是变亮
{
pwm_duty+=PwmChangeDuty; //改变占空比
if(pwm_duty>=BREATH_LEDPWM_PERIOD) //加到最大占空比则进入递减状态
{
breathFlag=FALSE;
}
}
else//占空比递减操作 就是变暗
{
pwm_duty-=PwmChangeDuty;//改变占空比
if(pwm_duty==0U)//递减到最小占空比则进入递加状态
{
breathFlag=TRUE;
}
}
}
}
《呼吸灯效果》
效果可能不好,这跟PWM可以分的档位有关,以及占空比改变的快慢、占空比改变的大小都有关,这个自己需要根据实际调试参数;
《《《《《END》》》》》