一 背景
最近接触到了RGB彩灯,这种灯的驱动方式一般有两种,一种是使用专门的驱动IC,可能是I2C接口也可能是SPI接口,发送一些指令来实现驱动的目的,另外一种是直接使用PWM方式驱动,根据三路PWM设置的DUTY比例来实现显示不同的颜色,我们可以设置最大DUTY为255,颜色可以参考标准的24位RGB定义。
二 实现三种不同的显示效果
2.1 显示指定颜色长亮
在三个PWM值都为0时灯是灭的状态
我们可以写一个接口函数,输入参数是颜色值
void drv_rgbled_setcolor(uint32_t set_val)
{
rgbled_r_pwmset((uint8_t)(set_val > >16));
rgbled_g_pwmset((uint8_t)(set_val > >8));
rgbled_b_pwmset((uint8_t)(set_val));
}
2.2 实现闪烁效果
在pwm关闭的时候灯也是灭的状态,我们可以通过使能PWM的方式来完成闪烁功能,我们也可以记录下当前灯的颜色,在关闭时设置为0,在非0时保存颜色值,打开时使用之前的颜色值即可,做一个接口来实现开关RGB灯条
static uint32_t s_current_rgbled_color = 0;
void drv_rgbled_setcolor(uint32_t set_val)
{
rgbled_r_pwmset((uint8_t)(set_val > >16));
rgbled_g_pwmset((uint8_t)(set_val > >8));
rgbled_b_pwmset((uint8_t)(set_val));
if (set_val)
{
s_current_rgbled_color = set_val;
}
}
void drv_rgbled_enbale(uint8_t set_en)
{
if (!set_en)
{
drv_rgbled_setcolor(0);
}
else
{
drv_rgbled_setcolor(s_current_rgbled_color);
}
2.3 实现呼吸效果
如果要实现一个蓝色呼吸灯的效果,我们首先知道的是蓝色灯100%亮度的值是0x0000FF,如果要实现50%蓝色灯的效果就需要对三个颜色分量乘以等比例系数0.5,我们可以实现一个设置亮度的接口函数
void drv_rgbled_brightness(uint8_t set_val,uint8_t max_val)
{
uint32_t get_color = s_current_rgbled_color;
uint8_t get_r = (uint8_t)(get_color > >16);
uint8_t get_g = (uint8_t)(get_color > >8);
uint8_t get_b = (uint8_t)(get_color);
uint8_t set_val_r = get_r*set_val/max_val;
uint8_t set_val_g = get_g*set_val/max_val;
uint8_t set_val_b = get_b*set_val/max_val;
rgbled_r_pwmset(set_val_r);
rgbled_g_pwmset(set_val_g);
rgbled_b_pwmset(set_val_b);
}
2.4 应用层
在任务中需要对闪烁时间进行计数,控制呼吸灯的状态
#define CONFIG_RGBLED_FLASH_IVT_MS 500
#define CONFIG_RGBLED_BREATH_BRIGHTNESS_MAX 100
#define CONFIG_RGBLED_BREATH_CHANGE_MS 1500
#define CONFIG_RGBLED_BREATH_IVT_MS (CONFIG_RGBLED_BREATH_CHANGE_MS/CONFIG_RGBLED_BREATH_BRIGHTNESS_MAX)
#define CONFIG_TASK_IVT_MS 15
typedef enum
{
S_RGBLED_OFF,
S_RGBLED_ON,
S_RGBLED_FLASH,
S_RGBLED_BREATH
}rgbled_workstatus_t;
typedef enum
{
BRS_RGBLED_REDUCE,
BRS_RGBLED_INCREASE,
}rgbled_breathstatus_t;
uint32_t rgbled_workstatus = S_RGBLED_OFF;
uint32_t rgbled_flash_ivt_count_ms = 0;
uint32_t rgbled_flash_status = 0;
uint32_t rgbled_breath_ivt_count_ms = 0;
uint32_t rgbled_breath_status = 0;
uint32_t rgbled_breath_brightness = CONFIG_RGBLED_BREATH_BRIGHTNESS_MAX;
void task_entry_main(void *parameter)
{
while(1)
{
if (S_RGBLED_FLASH == rgbled_workstatus)
{
rgbled_flash_ivt_count_ms++;
if (rgbled_flash_ivt_count_ms >= CONFIG_RGBLED_FLASH_IVT_MS)
{
rgbled_flash_ivt_count_ms = 0;
rgbled_flash_status = !rgbled_flash_status;
drv_rgbled_enbale(rgbled_flash_status);
}
}
else if (S_RGBLED_BREATH == rgbled_workstatus)
{
rgbled_breath_ivt_count_ms++;
if (rgbled_breath_ivt_count_ms >= (CONFIG_RGBLED_BREATH_IVT_MS/CONFIG_TASK_IVT_MS))
{
rgbled_breath_ivt_count_ms = 0;
if (BRS_RGBLED_REDUCE == rgbled_breath_status)
{
if (rgbled_breath_brightness > 0)
{
rgbled_breath_brightness--;
}
else
{
rgbled_breath_brightness = 0;
rgbled_breath_status = BRSBRS_RGBLED_INCREASE;
}
}
else if (BRSBRS_RGBLED_INCREASE == rgbled_breath_status)
{
if (rgbled_breath_brightness < CONFIG_RGBLED_BREATH_BRIGHTNESS_MAX)
{
rgbled_breath_brightness++;
}
else
{
rgbled_breath_brightness = CONFIG_RGBLED_BREATH_BRIGHTNESS_MAX;
rgbled_breath_status = BRS_RGBLED_REDUCE;
}
}
drv_rgbled_brightness(rgbled_breath_brightness,CONFIG_RGBLED_BREATH_BRIGHTNESS_MAX);
}
}
task_mdelay(CONFIG_TASK_IVT_MS);
}
}
评论
查看更多