呼吸灯控制方法
指示灯枚举
typedef enum{
LED_LIGHT_WHITE_AUTO = 0,
LED_LIGHT_RED_AUTO,
}EnumLedLight;
指示灯灯效枚举
typedef enum{
LED_STATE_STABLE = 0,
LED_STATE_FLASH,//闪烁
LED_STATE_BREASH,//呼吸
LED_STATE_RES,
LED_STATE_FADE_UP,//渐亮
LED_STATE_FADE,
}EnumLedState;
灯效控制
typedef struct{
EnumLedState mode;//灯效模式
uint32_t gpio;
uint16_t pin;
uint32_t value;
uint8_t max_brightness_percent;//变化的最亮值
float brightness_percent;//亮度控制,每步只能亮这么长时间
float brightness_percent_step;//控制亮度用,亮度增加的步长
uint8_t isledOn;//拉高-1;拉低-0
uint32_t period_tick;//计时
uint32_t period_step;//改变亮度周期,计时到这个时间改brightness_percent
uint32_t period_change;//记录brightness_percent改变的时间点
uint32_t period_half;//点亮或熄灭半个周期的时长
uint32_t period_all;//点亮或熄灭整个周期的时长
uint8_t fade_end;
}LedControlInfo;
#define LIGHT_NUM_MAX 2
LedControlInfo Lights[LIGHT_NUM_MAX];
**//registerGpioLedLight在GPIO.c中完成初始化**
void registerGpioLedLight(EnumLedLight light, uint32_t gpio_periph, uint16_t pin){
if(light >= LIGHT_NUM_MAX)return;
LedControlInfo *info = lights + light; //lights表示第一个结构体,light表示结构体指针偏移
info ->gpio = gpio_periph;
info -> pin =pin;
info ->mode = LED_STATE_STABLE;
info -> value = 0;
info -> max_brightness_percent =100;
}
uint8_t isLedControlStateEnd(EnumLedLight light){
if(light < LIGHT_NUM_MAX){
LedControlInfo *info = lights + light;
if((info -> mode == LED_STATE_FADE_UP) || (info -> mode == LED_STATE_FADE)){
return info -> fade_end;
}
}
return 0;
}
/*
1.先关闭LED;
2.如果period_tick是period_step的整数倍,则赋值period_change,如果后者超过period_half,逐步降低亮度,否则增亮
3.确保来个亮度百分比在合理范围内
4.超时点亮LED
*/
**static void lightCtrl_LL(LedControlInfo *info)**
{
info -> isledOn = 0;
if((info - > period_tick % info -> period_step) == 0){
info -> period_change = info -> period_tick;
if(info -> period_change > info -> period_half){
info -> brightness_percent -= info -> brightness_percent_step;
}
else{
info -> brightness_percent += info -> brightness_percent_step;
}
if(info -> brightness_percent > info -> max_brightness_percent){
info -> brightness_percent -= info -> max_brightness_percent;
}
else if( info -> brightness_percent < 0){
info -> brightness_percent = 0;
}
}
if((info -> period_tick - info -> period_change) < info -> brightness_percent ){
info -> isledOn = 1;
}
if(info -> isledOn){
GPIO_BOP(info -> gpio) = info -> pin;
}
else{
GPIO_BC(info -> gpio) = info -> pin;
}
info -> period_tick++;
}
*//将函数放在定时器回调函数中运行即可*
void displaylight(void){
for(i= 0;i< LIGHT_NUM_MAX;i++){
LedControlInfo *info = lights +i;
switch(info -> mode){
case LED_STATE_STABLE://开关状态
if(info ->period_tick > info ->period_all){
info->period_tick = 0;
info->period_change = 0;
}
break;
case LED_STATE_FLASH://闪烁
if(info ->period_tick > info ->period_all){
info->period_tick = 0;
info->period_change = 0;
}
break;
case LED_STATE_BREATH://呼吸
if(info ->period_tick > info ->period_all){
info->period_tick = 0;
info->period_change = 0;
info->brightness_percent = 0;
}
break;
case LED_STATE_FADE_UP://渐亮
if(info ->period_tick == info ->period_all){
info->period_tick = info->period_change;
info->fade_end = 1;
}
break;
case LED_STATE_FADE://渐暗
if(info ->period_tick > info ->period_all){
info->period_tick = info->period_change;
info->fade_end = 1;
}
break;
default:
break;
}
**lightCtrl_LL(info);**
}
}
//setLedLightControlInfo函数作为外部调用接口进行调用,触发不同的灯效
void setLedLightControlInfo(EnumLedLight light,EnumLedState mode,uint32_t value,uint8_t max_value){
if(light >= LIGHT_NUM_MAX){
return;
}
LedControlInfo *info = lights + light;
info -> mode = mode;
info -> value = value;
info -> isledOn = 0;
info -> period_tick = 0;
info -> fade_end = 0;
info -> period_change = 0;
info -> period_step = 100;
switch(info -> mode){
case LED_STATE_FLASH:
info -> period_all = info->period_half * 2;
info ->period_half = info->value * 100 * 10;
if((value > 0) && (max_value <= 100)){
info -> max_brightness_percent = max_value;
info -> brightness_percent = max_value;
info -> brightness_percent_step = max_value;
}
else{
info -> max_brightness_percent = 0;
info ->brightness_percent = 0;
info ->brightness_percent_step = 0;
}
break;
case LED_STATE_STABLE:
info -> period_all =100;
info ->period_half = 100;
info -> brightness_percent_step = 0;
if((value > 0)&&(max_value <= 100)){
info -> max_brightness_percent = max_value;
info ->brightness_percent = max_value;
}
else{
info -> max_brightness_percent = 0;
info ->brightness_percent = 0;
}
break;
case LED_STATE_BREATH:
info -> period_all = info->value *100 * 10 * 2;
info ->period_half = info->period_all / 2;
if((value > 0) && (max_value <= 100)){
info -> max_brightness_percent = max_value;
info -> brightness_percent = 0;
info -> brightness_percent_step = (float)info -> max_brightness_percent *100 / info -> period_half;
}
else{
info -> max_brightness_percent = 0;
info ->brightness_percent = 0;
info ->brightness_percent_step = 0;
}
break;
case LED_STATE_FADE_UP:
info -> period_all = info->value *100 * 10;
info ->period_half = period_all ;
info -> brightness_percent_step = 0;
if((value > 0)&&(value <= 100)){
info -> max_brightness_percent = max_value;
info -> brightness_percent_step = (float)info -> max_brightness_percent *100 / info -> period_all;
info ->brightness_percent = 0;
}
else{
info -> brightness_percent_step = 0;
info -> max_brightness_percent = 0;
info -> brightness_percent = 0;
}
break;
case LED_STATE_FADE:
info -> period_all = info->value *100 * 10;
info ->period_half = 0;
info -> brightness_percent_step = 0;
if((value > 0)&&(value <= 100)){
info -> max_brightness_percent = max_value;
info -> brightness_percent_step = (float)info -> max_brightness_percent *100 / info -> period_all;
info ->brightness_percent = max_value;
}
else{
info -> brightness_percent_step = 0;
info -> max_brightness_percent = 0;
info -> brightness_percent = 0;
}
break;
default:
break;
}
}