输入设备接口

输入设备的类型

要注册一个输入设备,需要初始化一个 lv_indev_drv_t 变量。请确保在注册任何输入设备之前,至少注册一个显示设备。

/*在注册任何输入设备之前,至少注册一个显示设备*/
lv_disp_drv_register(&disp_drv);

static lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);      /*基本初始化*/
indev_drv.type =...                 /*见下文。*/
indev_drv.read_cb =...              /*见下文。*/
/*在 LVGL 中注册驱动程序,并保存创建的输入设备对象*/
lv_indev_t * my_indev = lv_indev_drv_register(&indev_drv);

type 成员可以是:

  • LV_INDEV_TYPE_POINTER 触摸板或鼠标

  • LV_INDEV_TYPE_KEYPAD 键盘或按键

  • LV_INDEV_TYPE_ENCODER 带有左右旋转和按压选项的编码器

  • LV_INDEV_TYPE_BUTTON 外部按钮,虚拟按压屏幕

read_cb 是一个函数指针,将被周期性调用以报告输入设备的当前状态。

访问 输入设备 以了解有关输入设备的更多信息。

触摸板、鼠标或任何指针设备

可以点击屏幕上的点的输入设备属于此类别。

indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = my_input_read;

...

void my_input_read(lv_indev_drv_t * drv, lv_indev_data_t*data)
{
  if(touchpad_pressed) {
    data->point.x = touchpad_x;
    data->point.y = touchpad_y;
    data->state = LV_INDEV_STATE_PRESSED;
  } else {
    data->state = LV_INDEV_STATE_RELEASED;
  }
}

要设置鼠标光标,请使用 lv_indev_set_cursor(my_indev, &img_cursor)。(my_indevlv_indev_drv_register 的返回值)

键盘或按键

全键盘(包含所有字母)或仅有几个导航按钮的简单按键属于此类别。

要使用键盘/按键:

  • 使用 LV_INDEV_TYPE_KEYPAD 类型注册一个 read_cb 函数。

  • 创建一个对象组:lv_group_t * g = lv_group_create(),并使用 lv_group_add_obj(g, obj) 将对象添加到组中。

  • 必须将创建的组分配给输入设备:lv_indev_set_group(my_indev, g)my_indevlv_indev_drv_register 的返回值)。

  • 使用 LV_KEY_... 在组中的对象之间导航。有关可用按键,请参见 lv_core/lv_group.h

indev_drv.type = LV_INDEV_TYPE_KEYPAD;
indev_drv.read_cb = keyboard_read;

...

void keyboard_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
  data->key = last_key();            /*获取最后按下或释放的按键*/

  if(key_pressed()) data->state = LV_INDEV_STATE_PRESSED;
  else data->state = LV_INDEV_STATE_RELEASED;
}

编码器

使用编码器可以执行以下操作:

  1. 按下按钮

  2. 长按按钮

  3. 向左旋转

  4. 向右旋转

简而言之,编码器输入设备的工作方式如下:

  • 通过旋转编码器,可以聚焦到下一个/上一个对象。

  • 当按下编码器上的简单对象(如按钮)时,它将被点击。

  • 如果按下编码器上的复杂对象(如列表、消息框等),对象将进入编辑模式,此时可以通过旋转编码器在对象内部导航。

  • 要退出编辑模式,请长按按钮。

要使用 编码器(与 按键 类似),需要将对象添加到组中。

indev_drv.type = LV_INDEV_TYPE_ENCODER;
indev_drv.read_cb = encoder_read;

...

void encoder_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
  data->enc_diff = enc_get_new_moves();

  if(enc_pressed()) data->state = LV_INDEV_STATE_PRESSED;
  else data->state = LV_INDEV_STATE_RELEASED;
}

使用按钮实现编码器逻辑

除了标准的编码器行为,还可以利用其逻辑通过按钮导航(聚焦)和编辑小部件。 这在只有少量按钮可用,或者希望在编码器轮之外使用其他按钮时特别有用。

需要提供 3 个按钮:

  • LV_KEY_ENTER 将模拟按下或推下编码器按钮

  • LV_KEY_LEFT 将模拟编码器向左旋转

  • LV_KEY_RIGHT 将模拟编码器向右旋转

  • 其他按键将传递给聚焦的小部件

如果按住按键,将以 indev_drv.long_press_rep_time 指定的周期模拟编码器的连续动作。

indev_drv.type = LV_INDEV_TYPE_ENCODER;
indev_drv.read_cb = encoder_with_keys_read;

...

void encoder_with_keys_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
  data->key = last_key();            /*获取最后按下或释放的按键*/
                                     /* 使用 LV_KEY_ENTER 模拟编码器按下 */
  if(key_pressed()) data->state = LV_INDEV_STATE_PRESSED;
  else {
      data->state = LV_INDEV_STATE_RELEASED;
      /* 如果有编码器,也可以选择使用 enc_diff */
      data->enc_diff = enc_get_new_moves();
  }
}

按钮

按钮 是指屏幕旁的外部“硬件”按钮,这些按钮被分配到屏幕的特定坐标。 如果按下按钮,它将模拟按下分配的坐标。(类似于触摸板)

要将按钮分配到坐标,请使用 lv_indev_set_button_points(my_indev, points_array)points_array 应该类似于 const lv_point_t points_array[] = { {12,30},{60,90}, ...}

``` important:: points_array 不能超出作用域。可以将其声明为全局变量或函数内的静态变量。


```c
indev_drv.type = LV_INDEV_TYPE_BUTTON;
indev_drv.read_cb = button_read;

...

void button_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
    static uint32_t last_btn = 0;   /*存储最后按下的按钮*/
    int btn_pr = my_btn_read();     /*获取按下按钮的 ID(0,1,2...)*/
    if(btn_pr >= 0) {               /*是否有按钮被按下?(例如,-1 表示没有按钮被按下)*/
       last_btn = btn_pr;           /*保存按下按钮的 ID*/
       data->state = LV_INDEV_STATE_PRESSED;  /*设置按下状态*/
    } else {
       data->state = LV_INDEV_STATE_RELEASED; /*设置释放状态*/
    }

    data->btn = last_btn;            /*保存最后的按钮*/
}

其他功能

参数

可以在 lv_indev_drv_t 中更改以下参数的默认值:

  • scroll_limit 滑动对象前的像素数。

  • scroll_throw 滑动惯性减速的百分比(%)。值越大,减速越快。

  • long_press_time 发送 LV_EVENT_LONG_PRESSED 的按压时间(以毫秒为单位)。

  • long_press_rep_time 发送 LV_EVENT_LONG_PRESSED_REPEAT 的间隔(以毫秒为单位)。

  • read_timer 指向读取输入设备的 lv_timer。其参数可以通过 lv_timer_...() 函数更改。LV_INDEV_DEF_READ_PERIODlv_conf.h 中设置默认读取周期。

反馈

除了 read_cb,还可以在 lv_indev_drv_t 中指定一个 feedback_cb 回调。 当输入设备发送任何类型的事件时(无论其类型如何),都会调用 feedback_cb。这允许为用户生成反馈,例如在 LV_EVENT_CLICKED 时播放声音。

与显示设备关联

每个输入设备都与一个显示设备相关联。默认情况下,新输入设备会添加到最后创建的显示设备或显式选择的显示设备(使用 lv_disp_set_default())。 相关联的显示设备存储在驱动程序的 disp 字段中,可以更改。

缓冲读取

默认情况下,LVGL 会周期性调用 read_cb。由于这种间歇性轮询,可能会错过一些用户手势。

为了解决这个问题,可以为输入设备编写一个事件驱动的驱动程序来缓冲测量数据。在 read_cb 中,可以报告缓冲数据,而不是直接读取输入设备。 设置 data->continue_reading 标志将告诉 LVGL 还有更多数据需要读取,它应该再次调用 read_cb

进一步阅读

API

@description Input Device HAL interface layer header file

Typedefs

typedef struct _lv_indev_drv_t lv_indev_drv_t

Initialized by the user and registered by 'lv_indev_add()'

typedef struct _lv_indev_proc_t _lv_indev_proc_t

Run time data of input devices Internally used by the library, you should not need to touch it.

typedef struct _lv_indev_t lv_indev_t

The main input device descriptor with driver, runtime data ('proc') and some additional information

Enums

enum lv_indev_type_t

Possible input device types

Values:

enumerator LV_INDEV_TYPE_NONE

Uninitialized state

enumerator LV_INDEV_TYPE_POINTER

Touch pad, mouse, external button

enumerator LV_INDEV_TYPE_KEYPAD

Keypad or keyboard

enumerator LV_INDEV_TYPE_BUTTON

External (hardware button) which is assigned to a specific point of the screen

enumerator LV_INDEV_TYPE_ENCODER

Encoder with only Left, Right turn and a Button

enum lv_indev_state_t

States for input devices

Values:

enumerator LV_INDEV_STATE_RELEASED
enumerator LV_INDEV_STATE_PRESSED

Functions

void lv_indev_drv_init(struct _lv_indev_drv_t *driver)

Initialize an input device driver with default values. It is used to surely have known values in the fields and not memory junk. After it you can set the fields.

Parameters

driver -- pointer to driver variable to initialize

lv_indev_t *lv_indev_drv_register(struct _lv_indev_drv_t *driver)

Register an initialized input device driver.

Parameters

driver -- pointer to an initialized 'lv_indev_drv_t' variable (can be local variable)

Returns

pointer to the new input device or NULL on error

void lv_indev_drv_update(lv_indev_t *indev, struct _lv_indev_drv_t *new_drv)

Update the driver in run time.

Parameters
  • indev -- pointer to an input device. (return value of lv_indev_drv_register)

  • new_drv -- pointer to the new driver

void lv_indev_delete(lv_indev_t *indev)

Remove the provided input device. Make sure not to use the provided input device afterwards anymore.

Parameters

indev -- pointer to delete

lv_indev_t *lv_indev_get_next(lv_indev_t *indev)

Get the next input device.

Parameters

indev -- pointer to the current input device. NULL to initialize.

Returns

the next input device or NULL if there are no more. Provide the first input device when the parameter is NULL

void _lv_indev_read(lv_indev_t *indev, lv_indev_data_t *data)

Read data from an input device.

Parameters
  • indev -- pointer to an input device

  • data -- input device will write its data here

struct lv_indev_data_t
#include <lv_hal_indev.h>

Data structure passed to an input driver to fill

Public Members

lv_point_t point

For LV_INDEV_TYPE_POINTER the currently pressed point

uint32_t key

For LV_INDEV_TYPE_KEYPAD the currently pressed key

uint32_t btn_id

For LV_INDEV_TYPE_BUTTON the currently pressed button

int16_t enc_diff

For LV_INDEV_TYPE_ENCODER number of steps since the previous read

lv_indev_state_t state

LV_INDEV_STATE_REL or LV_INDEV_STATE_PR

bool continue_reading

If set to true, the read callback is invoked again

struct _lv_indev_drv_t
#include <lv_hal_indev.h>

Initialized by the user and registered by 'lv_indev_add()'

Public Members

lv_indev_type_t type

< Input device type Function pointer to read input device data.

void (*read_cb)(struct _lv_indev_drv_t *indev_drv, lv_indev_data_t *data)
void (*feedback_cb)(struct _lv_indev_drv_t*, uint8_t)

Called when an action happened on the input device. The second parameter is the event from lv_event_t

void *user_data
struct _lv_disp_t *disp

< Pointer to the assigned display Timer to periodically read the input device

lv_timer_t *read_timer

Number of pixels to slide before actually drag the object

uint8_t scroll_limit

Drag throw slow-down in [%]. Greater value means faster slow-down

uint8_t scroll_throw

At least this difference should be between two points to evaluate as gesture

uint8_t gesture_min_velocity

At least this difference should be to send a gesture

uint8_t gesture_limit

Long press time in milliseconds

uint16_t long_press_time

Repeated trigger period in long press [ms]

uint16_t long_press_repeat_time
struct _lv_indev_proc_t
#include <lv_hal_indev.h>

Run time data of input devices Internally used by the library, you should not need to touch it.

Public Members

lv_indev_state_t state

Current state of the input device.

uint8_t long_pr_sent
uint8_t reset_query
uint8_t disabled
uint8_t wait_until_release
lv_point_t act_point

Current point of input device.

lv_point_t last_point

Last point of input device.

lv_point_t last_raw_point

Last point read from read_cb.

lv_point_t vect

Difference between act_point and last_point.

lv_point_t scroll_sum
lv_point_t scroll_throw_vect
lv_point_t scroll_throw_vect_ori
struct _lv_obj_t *act_obj
struct _lv_obj_t *last_obj
struct _lv_obj_t *scroll_obj
struct _lv_obj_t *last_pressed
lv_area_t scroll_area
lv_point_t gesture_sum
lv_dir_t scroll_dir
lv_dir_t gesture_dir
uint8_t gesture_sent
struct _lv_indev_proc_t pointer
lv_indev_state_t last_state
uint32_t last_key
struct _lv_indev_proc_t keypad
union _lv_indev_proc_t types
uint32_t pr_timestamp

Pressed time stamp

uint32_t longpr_rep_timestamp

Long press repeat time stamp

struct _lv_indev_t
#include <lv_hal_indev.h>

The main input device descriptor with driver, runtime data ('proc') and some additional information

Public Members

struct _lv_indev_drv_t *driver
_lv_indev_proc_t proc
struct _lv_obj_t *cursor

Cursor for LV_INPUT_TYPE_POINTER

struct _lv_group_t *group

Keypad destination group

const lv_point_t *btn_points

Array points assigned to the button ()screen will be pressed here by the buttons