eefocus_3891719 发表于 2024-11-29 10:16:17

【Avnet | NXP FRDM-MCXN947试用活动】测评7-LVGL移植触摸屏

# 背景

前面的帖子已经实现了触摸屏的触摸效果,但是没有接入到 LVGL,现在开干。

# LVGL 移植触摸屏详解

## 1. 对应的输入设备文件

LVGL 接入输入设备,可以参考其自带的示例,即 `examples/porting/lv_port_indev_template.c` 文件和对应的头文件。咱们先把这两个文件拷贝出来,放到 `bsp/lvgl_port/` 目录下,并重命名为 `lv_port_indev.c` 和 `lv_port_indev.h`。

## 2. 修改 lv_port_indev.c/.h

这两个文件都使用 `#if 0` 括了起来,需要改成 `#if 1` 使能,然后包含正确的头文件,如下图所示,仅包含 `lv_port_indev.h` 和 `touch.h` 文件即可。


!(https://www.eefocus.com/forum/data/attachment/forum/202411/29/101548odu6ptpiiuy3ipd6.png)



## 3. 关键函数 `lv_port_indev_init()`

文件 `lv_port_indev.c` 文件中的 `lv_port_indev_init()` 函数非常关键,从它注册输入设备到 LVGL。它支持的输入设备有多种类型:

- 最常见的是触摸屏 `LV_INDEV_TYPE_POINTER`
- 鼠标,对应 `LV_INDEV_TYPE_MOUSE`
- 键盘,对应 `LV_INDEV_TYPE_KEYPAD`
- 编码器,对应 `LV_INDEV_TYPE_ENCODER`
- 按键,对应 `LV_INDEV_TYPE_BUTTON`

这里只需要关注触摸屏,其他的全部用 `#if 0` 括起来。

最终 `lv_port_indev_init()` 函数简化如下:

```c
void lv_port_indev_init(void)
{
    static lv_indev_drv_t indev_drv;

    /*------------------
   * Touchpad
   * -----------------*/

    /*Initialize your touchpad if you have*/
    touchpad_init();

    /*Register a touchpad input device*/
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = touchpad_read;
    indev_touchpad = lv_indev_drv_register(&indev_drv);
}
```

从这个代码片段看出,我们只需要实现 `touchpad_init()` 和 `touchpad_read()` 函数即可。

## 4. touchpad_init()

这个函数的实现非常简单,调用我们之间写好的触摸屏初始化函数 `TP_Init()` 即可。

```c
static void touchpad_init(void)
{
    /*Your code comes here*/
    // NOTE: 触摸屏已经在别的地方初始化了
    TP_Init();
}
```

## 5. touchpad_read()

这个函数是 LVGL 提供的模版函数,我们不用做什么改动,只需要实现其中的 `touchpad_is_pressed()` 和 `touchpad_get_xy()` 即可。

从下面代码可以看出, `touchpad_is_pressed()` 只需要调用 `TP_Scan()` ,如果有触摸则发回非0值即可,如果没有触摸则返回0,最终 `touchpad_is_pressed()` 返回逻辑值。

而 `touchpad_get_xy()` 更简单,直接调用 `TP_Get_XY()` 返回最近一次触摸的坐标即可。

```c
/*Will be called by the library to read the touchpad*/
static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
        static lv_coord_t last_x = 0;
    static lv_coord_t last_y = 0;

    /*Save the pressed coordinates and the state*/
    if(touchpad_is_pressed()) {
      touchpad_get_xy(&last_x, &last_y);
      data->state = LV_INDEV_STATE_PR;
    }
    else {
      data->state = LV_INDEV_STATE_REL;
    }

    /*Set the last pressed coordinates*/
    data->point.x = last_x;
    data->point.y = last_y;
}

/*Return true is the touchpad is pressed*/
static bool touchpad_is_pressed(void)
{
        /*Your code comes here*/
        // TODO: 从这里开始一次扫描,获取触摸屏状态
        if (TP_Scan()) {
                return true;
        }

        return false;
}

/*Get the x and y coordinates if the touchpad is pressed*/
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)
{
    /*Your code comes here*/
        TP_Get_XY((uint16_t*)x, (uint16_t*)y);
}
```

# 演示

运行 LVGL 几个示例程序,比之前的屏幕模组厂商的示例程序丝滑多了。主要是LVGL刷屏采用了 DMA,比逐个打点方式快多了。

视频参见B站:

(https://www.bilibili.com/video/BV1PJBRYAEDG/?vd_source=8f2bbf56b70c541bec2ea0b9f102ebee)


页: [1]
查看完整版本: 【Avnet | NXP FRDM-MCXN947试用活动】测评7-LVGL移植触摸屏