输入设备接口¶
输入设备的类型¶
要注册一个输入设备,需要初始化一个 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_indev 是 lv_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_indev是lv_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;
}
编码器¶
使用编码器可以执行以下操作:
按下按钮
长按按钮
向左旋转
向右旋转
简而言之,编码器输入设备的工作方式如下:
通过旋转编码器,可以聚焦到下一个/上一个对象。
当按下编码器上的简单对象(如按钮)时,它将被点击。
如果按下编码器上的复杂对象(如列表、消息框等),对象将进入编辑模式,此时可以通过旋转编码器在对象内部导航。
要退出编辑模式,请长按按钮。
要使用 编码器(与 按键 类似),需要将对象添加到组中。
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_PERIOD在lv_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。
进一步阅读¶
lv_port_indev_template.c 提供了一个用于自定义驱动程序的模板。
输入设备功能 了解更多高级输入设备功能。
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
-
enumerator
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
-
lv_point_t
-
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¶
-
lv_indev_type_t
-
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_pointandlast_point.
-
lv_point_t
scroll_sum¶
-
lv_point_t
scroll_throw_vect¶
-
lv_point_t
scroll_throw_vect_ori¶
-
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
-
lv_indev_state_t
-
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_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
-
struct _lv_indev_drv_t *