玩转树莓派屏幕之六:定期息屏

前言

由于屏幕一直显示,尤其是在晚上,特别刺眼。需要增加个息屏,从MHS35 LCD屏幕引脚中没有发现控制LCD背光的引脚,不能通过硬件实现息屏,只能通过软件了。

解题思路

给最上层的窗口中增加一个矩阵,能够覆盖整个屏幕,矩阵背景设置成黑色,通过透明度控制是否息屏。息屏是不透明,正常工作全透明。

软件实现:

实现部分:

  1. 创建全局矩阵,父层级为lv_layer_sys,lv_layer_sys为整个屏幕的最上层,就算是右下角的监控部分也能遮盖。
  2. 创建事件,屏幕有触摸时,刷新显示和延迟等待时间
  3. while循环控制,定期去算延迟等待时间,满足后就直接continue,并且设置为不透明

还没有研究到LVGL中定时器的用法,所以定时任务没有使用定时器

这样就可以实现了屏幕显示5分钟后,自动息屏。点击屏幕后,又能重新亮起。


// 全局变量:亮度控制层
static lv_obj_t * brightness_cover = NULL;
static uint32_t time_wait_loop = 0;

void set_screen_brightness(int8_t level);

// 全局变量:亮度控制层

void event_handler(lv_event_t* e)
{
    lv_event_code_t code = lv_event_get_code(e);

    if (code == LV_EVENT_CLICKED)
    {
        time_wait_loop = 0;
        set_screen_brightness(100);
    }
}

// 初始化亮度控制层
void init_brightness_control(void) {
    // 创建一个覆盖整个屏幕的矩形
    brightness_cover = lv_obj_create(lv_layer_sys());

    // 设置大小为全屏
    lv_obj_set_size(brightness_cover, 480, 320);
    lv_obj_add_event_cb(brightness_cover, event_handler, LV_EVENT_ALL, NULL);

    // 移动到最顶层
    lv_obj_move_foreground(brightness_cover);

    // 设置背景颜色为黑色
    // lv_obj_set_style_local_bg_color(brightness_cover, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, lv_color_black());
    lv_obj_set_style_bg_color(brightness_cover, lv_color_black(), LV_PART_MAIN|LV_STATE_DEFAULT);

    // 默认亮度:100%(即覆盖层完全透明,不影响显示)
    // lv_obj_set_style_bg_opa(brightness_cover, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_0);
    lv_obj_set_style_bg_opa(brightness_cover, LV_OPA_0, LV_PART_MAIN|LV_STATE_DEFAULT);
    lv_obj_set_style_border_width(brightness_cover, 0, LV_PART_MAIN);
    lv_obj_set_style_shadow_width(brightness_cover, 0, LV_PART_MAIN);
}

// 设置亮度 (0-100),0=最暗,100=最亮
void set_screen_brightness(int8_t level) {
    if (brightness_cover == NULL) return;

    // 将亮度值 (0-100) 转换为 LVGL 的不透明度 (0-255)
    // 注意:这里反向映射,因为透明度越高,屏幕越暗
    uint8_t opa = (100 - level) * 255 / 100;  // 100% 亮度 -> 0 透明度;0% 亮度 -> 255 透明度

    // 限制范围
    if (opa > 255) opa = 255;

    // 设置覆盖层的不透明度
    lv_obj_set_style_bg_opa(brightness_cover, opa, LV_PART_MAIN | LV_STATE_DEFAULT);
}

int main()
{
    // Timer_Init();

    // 初始化LVGL
    lv_init();
    lv_display_t* disp = lv_linux_fbdev_create();
    lv_linux_fbdev_set_file(disp, "/dev/fb0");

    tsdev_init();
    lv_indev_t * indev = lv_indev_create();
    lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
    lv_indev_set_read_cb(indev, tsdev_read);
    lv_indev_set_display(indev, disp);

    // lv_example_btn_1();
    setup_ui(&guider_ui);
    UpdateScreen();
    uint32_t last_update = 0;

    init_brightness_control();

    while (true)
    {
        uint32_t start_tick = lv_tick_get();
        usleep(LVGL_TICK); /*Sleep for 5 millisecond*/
        lv_task_handler();
        lv_tick_inc(LVGL_TICK); /*Tell LVGL that 5 milliseconds were elapsed*/

        if (start_tick - last_update >= 1000) {
            last_update = start_tick;

            time_wait_loop ++;
            if (time_wait_loop > 300) {
                set_screen_brightness(0);
                continue;
            }
            // 其他逻辑

            UpdateScreen();

        }

    }
}