LVGL中實體按鍵的使用

shumei發表於2024-12-09

此篇文章在2022年3月5日被記錄

在某些螢幕上我們沒有觸控功能,則需要使用按鍵操作控制元件

lvgl總共給了我們四種裝置輸入介面,分別是

1、LV_INDEV_TYPE_POINTER 觸控板或滑鼠
2、LV_INDEV_TYPE_KEYPAD 鍵盤或小鍵盤
3、LV_INDEV_TYPE_ENCODER 編碼器,帶有左/右轉和推動選項
4、LV_INDEV_TYPE_BUTTON 外部按鈕虛擬按下螢幕

我們使用實體按鍵適用第二種或第四種輸入方式,但是第四種輸入方式侷限性較大,只能作為一個按下螢幕的虛擬的點,也就是說,我們如果有三個按鍵,只能模擬三個點在螢幕按下;所以我們使用LV_INDEV_TYPE_KEYPAD 作為輸入方式。
LV_INDEV_TYPE_KEYPAD可以傳遞以下幾種狀態,如果可能我們可以連線一個真正的鍵盤來傳遞所有的值。

LV_KEY_NEXT 聚焦到下一個物件
LV_KEY_PREV 聚焦到上一個物件
LV_KEY_ENTER 觸發 LV_EVENT_PRESSED/CLICKED/LONG_PRESSED 等事件
LV_KEY_UP 增加值或向上移動
LV_KEY_DOWN 減少值或向下移動
LV_KEY_RIGHT 增加值或向右移動
LV_KEY_LEFT 減少值或向左移動
LV_KEY_ESC 關閉或退出(例如關閉 下拉選單)
LV_KEY_DEL 刪除(例如 文字區域 中右側的字元)
LV_KEY_BACKSPACE 刪除左邊的一個字元(例如在文字區域)
LV_KEY_HOME 跳到開頭/頂部(例如在 文字區域)
LV_KEY_END 跳到最後(例如在 文字區域)

如何在我們的工程中實現鍵盤功能:

1、硬體上必須要有三個按鍵,根據自己的連線方式進行初始化:

void key_init(void)
{
    gpio_pad_select_gpio(KEY1);
    gpio_pad_select_gpio(KEY2);
    gpio_pad_select_gpio(KEY3);
    gpio_pad_select_gpio(KEY4);

    gpio_pad_pullup(KEY1);
    gpio_pad_pullup(KEY2);
    gpio_pad_pullup(KEY3);
    gpio_pad_pullup(KEY4);

    gpio_set_direction(KEY1, GPIO_MODE_INPUT);
    gpio_set_direction(KEY2, GPIO_MODE_INPUT);
    gpio_set_direction(KEY3, GPIO_MODE_INPUT);
    gpio_set_direction(KEY4, GPIO_MODE_INPUT);

}

2、設定按鍵讀取函式,返回值與上述鍵值相對應:

int read_key(void)
{
    if(gpio_get_level(KEY1)==0)
    {
        return LV_KEY_PREV;
    }
    else if (gpio_get_level(KEY2)==0)
    {
        return LV_KEY_NEXT;  
    }
     else if (gpio_get_level(KEY4)==0)
    {
        return LV_KEY_ENTER; 
    }
    else
    {
        return -1;
        }
}

3、在初始化函式中配置註冊裝置:

lv_indev_t *mydev=NULL; //這個與後續的group相繫結
lv_indev_drv_t indev_drv_key;
lv_indev_drv_init(&indev_drv_key);
indev_drv_key.read_cb = button_read;
indev_drv_key.type = LV_INDEV_TYPE_KEYPAD;
mydev=lv_indev_drv_register(&indev_drv_key);

4、裝置回撥函式:

void button_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
    static uint32_t last_btn = 0;   /*Store the last pressed button*/
    int btn_pr = read_key();     /*Get the ID (0,1,2...) of the pressed button*/
    if(btn_pr >= 0) {     /*Is there a button press? (E.g. -1 indicated no button was pressed)*/
       last_btn = btn_pr;   /*Save the ID of the pressed button*/
       data->state = LV_INDEV_STATE_PRESSED;  /*Set the pressed state*/

    } else {
       data->state = LV_INDEV_STATE_RELEASED; /*Set the released state*/
    }

    data->key = last_btn;            /*Save the last button*/
}

5、新增了裝置還要與group相繫結,不然無法起到作用,新建三個物件用來做演示:

extern lv_indev_t *mydev;
static void btn_event_handler(lv_event_t * e)//按鍵回撥函式
{
    lv_event_code_t code = lv_event_get_code(e);

    if(code == LV_EVENT_CLICKED) {
        LV_LOG_USER("Clicked");
    }
    else if(code == LV_EVENT_VALUE_CHANGED) {
        LV_LOG_USER("Toggled");
    }
}
static void event_handler(lv_event_t * e)//滑塊回撥函式
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * obj = lv_event_get_target(e);


    static int i = 0;
	if(code == LV_EVENT_CLICKED){
		printf("\r\nclick = %d",code);
		if(i++ >12)
			i=0;
		lv_roller_set_selected(obj, i, LV_ANIM_ON);
	}

}
void lv_example(void)
{
    lv_obj_t *scr = lv_scr_act();
    lv_group_t *group = lv_group_create();
    lv_group_set_default(group);
    lv_indev_set_group(mydev, group);
    lv_group_focus_obj(group);          //分組聚焦到物件
    lv_group_set_editing(group, true);   //編輯模式

    lv_obj_t * label;
    lv_obj_t * btn1 = lv_btn_create(lv_scr_act());
    lv_obj_add_event_cb(btn1, btn_event_handler, LV_EVENT_ALL, NULL);
    lv_obj_align(btn1, LV_ALIGN_CENTER, -50, -40);

    label = lv_label_create(btn1);
    lv_label_set_text(label, "Button");
    lv_obj_center(label);

    lv_obj_t * btn2 = lv_btn_create(lv_scr_act());
    lv_obj_add_event_cb(btn2, btn_event_handler, LV_EVENT_ALL, NULL);
    lv_obj_align(btn2, LV_ALIGN_CENTER, -50, 40);
    lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE);
    lv_obj_set_height(btn2, LV_SIZE_CONTENT);

    label = lv_label_create(btn2);
    lv_label_set_text(label, "Toggle");
    lv_obj_center(label);

    lv_obj_t *roller1 = lv_roller_create(scr);
    lv_roller_set_options(roller1,
                        "January\n"
                        "February\n"
                        "March\n"
                        "April\n"
                        "May\n"
                        "June\n"
                        "July\n"
                        "August\n"
                        "September\n"
                        "October\n"
                        "November\n"
                        "December",
                        LV_ROLLER_MODE_INFINITE);

    lv_roller_set_visible_row_count(roller1, 4);
    lv_obj_set_pos(roller1,150,100);
    lv_obj_add_event_cb(roller1, event_handler, LV_EVENT_ALL, NULL);

	lv_group_add_obj(group ,btn1);
	lv_group_add_obj(group ,btn2);
	lv_group_add_obj(group ,roller1);
}

最終效果:

img

相關文章