本帖最后由 lovzx 于 2024-3-7 16:12 编辑
小安派PWM调节LCD背光
注意看这个开发版就是大名鼎鼎的小安派S1,它竟然可以做到控制显示屏的亮度。
发明小安派的人真是个天才,它内部集成了 DVP、MJPEG、Dispaly、AudioCodec、USB2.0、SDU、以太网 (EMAC)、SD/MMC(SDH)、SPI、UART、I2C、I2S、PWM、GPDAC、GPADC、ACOMP 和 GPIO 等模块。可别小瞧了这个简简单单的PWM,通过调节PWM占空比就可以实现调节LCD的背光亮度,不同于以往的DC直接调节输出功率来调节亮度,PWM可以做到省电发热低等优点。
PWM调光原理
通过快速设置输出的调低电平,输出高电平LED就边亮,输出低电平LED就不亮,PWM切换的频率远超过人眼识别范围,通过调节高低电平的占比,最后看到的效果就是显示不同的亮度。
这东西有个专业的理论叫做面积等效原理详情可以看其他大佬的文章!PWM原理
小安派PWM控制屏幕背光
通过看原理图知道小安派S1的屏幕背光在GPIO2引脚上
BL_A就是LCD控制背光的引脚
GPIO2在还收到受到S2的控制,此外改引脚还是boot引脚,通过usb下载固件会用到此引脚,开关S2另一端接到3.3v电压上,这也就是为什么按下S2屏幕会变暗的原理,如果手速够快不停的按下松开应该也可以达到pwm效果
找到了控制背光的输入端剩下的就是设置PWM了
设置GPIO2的PWM输出
小泽老师的PWM教程是专业的
gpio = bflb_device_get_by_name("gpio");
bflb_gpio_init(gpio, LCD_BL_PIN,
GPIO_PULLUP | GPIO_OUTPUT | GPIO_FUNC_PWM0
| GPIO_ALTERNATE | GPIO_SMT_EN | GPIO_DRV_1);
bflb_gpio_set(gpio, LCD_BL_PIN);
struct bflb_pwm_v2_config_s config = {
.clk_source = BFLB_SYSTEM_XCLK,
.clk_div = 40,
.period = pwm_period,
};
pwm = bflb_device_get_by_name("pwm_v2_0");
bflb_pwm_v2_init(pwm, &config);
struct bflb_pwm_v2_channel_config_s cconfig =
{
.positive_polarity = PWM_POLARITY_ACTIVE_LOW,
.negative_polarity = PWM_POLARITY_ACTIVE_LOW,
.positive_stop_state = PWM_STATE_INACTIVE,
.negative_stop_state = PWM_STATE_ACTIVE,
.positive_brake_state = PWM_STATE_INACTIVE,
.negative_brake_state = PWM_STATE_INACTIVE,
.dead_time = 0,
};
bflb_pwm_v2_start(pwm);
bflb_pwm_v2_channel_init(pwm, PWM_CH2, &cconfig);
bflb_pwm_v2_channel_negative_start(pwm, PWM_CH2);
bflb_pwm_v2_channel_positive_start(pwm, PWM_CH2);
bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH2, 0, pwm_period);
- UI部分通过lvgl的lv_slider组件实现滑动控制
//滑动回调
typedef void(*value_func)(uint32_t value);
typedef struct
{
lv_obj_t* root;
lv_obj_t* slider;
lv_obj_t* label;
value_func func;
}ui_t;
lv_event_code_t code = lv_event_get_code(evnet);
if (code == LV_EVENT_VALUE_CHANGED)
{
lv_obj_t* slider = lv_event_get_target(evnet);
uint32_t value = lv_slider_get_value(slider);
ui_t* ui = (ui_t*)lv_event_get_user_data(evnet);
update_value_label(ui->label, value);
if (ui->func)
{
ui->func(value);
}
}
//初始化UI
ui_init(&ui);
//初始化LCD
lcd_bl_init();
//注册回调事件
ui_value_register_func(&ui, lcd_bl_update_ligth);
void lcd_bl_update_ligth(uint32_t value)
{
uint32_t low, hig;
hig = value * pwm_period / 100;
low = pwm_period - hig;
bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH2, low, hig);
printf("low: %d,hig: %d,b: %d\n", low, hig, value);
}
效果如下
源码放在gitee上了 Robot/bl616_pwm_lcd (gitee.com)
<iframe src="https://player.bilibili.com/player.html?aid=1351335773&bvid=BV1pz421975v&cid=1461925469&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>