小安派通过PWM调节屏幕亮度

[复制链接]
查看929 | 回复17 | 2024-3-7 15:48:56 | 显示全部楼层 |阅读模式

本帖最后由 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教程是专业的

  • 设置GPIO2为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);
  • 初始化PWM
    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_slider滑动事件
   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
    ui_init(&ui);
    //初始化LCD
    lcd_bl_init();
    //注册回调事件
    ui_value_register_func(&ui, lcd_bl_update_ligth);
  • 更新PWM占空比
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>

本帖被以下淘专辑推荐:

回复

使用道具 举报

爱笑 | 2024-3-7 15:53:02 | 显示全部楼层
不错不错
用心做好保姆工作
回复

使用道具 举报

1084504793 | 2024-3-7 17:59:59 | 显示全部楼层
回复

使用道具 举报

WT_0213 | 2024-3-8 08:37:45 | 显示全部楼层
回复

使用道具 举报

lazy | 2024-3-8 09:16:59 | 显示全部楼层
回复

使用道具 举报

干簧管 | 2024-3-8 09:20:17 | 显示全部楼层
赞👍
回复

使用道具 举报

1055173307 | 2024-3-8 09:40:55 | 显示全部楼层
回复

使用道具 举报

bzhou830 | 2024-3-8 10:22:07 | 显示全部楼层
向大佬学习,细致
选择去发光,而不是被照亮
回复 支持 反对

使用道具 举报

noonezero | 2024-3-8 10:48:57 | 显示全部楼层
向大佬学习
回复 支持 反对

使用道具 举报

wukong50 | 2024-3-8 11:20:21 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则