esp-idf/docs/zh_CN/api-reference/peripherals/touch_element.rst

481 lines
18 KiB
ReStructuredText
Raw Normal View History

触摸元件
=============
:link_to_translation:`en:[English]`
概述
--------
触摸元件库是基于触摸传感器驱动设计的高度抽象的元件库,该库提供了统一且友好的软件接口,可以快速构建电容式触摸传感器的应用。有关触摸传感器驱动 API 的更多信息,请参阅 :doc:`../peripherals/touch_pad`
架构
^^^^^^^^^^^^
触摸元件库通过触摸传感器驱动程序配置触摸传感器外设。使用时,部分必要的硬件参数需要传递给函数 :cpp:func:`touch_element_install`,但只有在调用 :cpp:func:`touch_element_start` 函数后,才会自动配置这些参数。这些参数配置会对实时系统产生很大的影响,因此步骤顺序很重要,必须在调用启动函数之后进行配置,确保系统正常运行。
上述参数包括触摸通道阈值、防水屏蔽传感器驱动级别等。触摸元件库会设置触摸传感器中断和 esp_timer 例程,并在触摸传感器中断服务例程中获取触摸传感器的硬件信息(通道状态、通道编号)。当特定通道事件发生时,硬件信息将传递给 esp_timer 回调例程esp_timer 回调例程将触摸传感器通道信息分配给触摸元件(例如按键、滑条等)。随后,触摸元件库运行特定算法,更新触摸元件状态或计算其位置,并将结果分派给相应的处理程序。
因此,在使用触摸元件库时,你无需关注触摸传感器外设的工作细节,该库会处理大部分硬件信息,并将更有意义的信息传递给事件处理程序。
下图展示了触摸元件库的工作流程。
.. figure:: /../_static/touch_element/te_architecture.svg
:scale: 100 %
:align: center
触摸元件库架构
下表展示了 {IDF_TARGET_NAME} 中与触摸元件库有关的功能。
.. list-table::
:header-rows: 1
:widths: 70 30
:align: center
* - 功能
- ESP32S2
* - 防水
-
* - 按键
-
* - 触摸滑条
-
* - 矩阵按键
-
外设
^^^^^^^^^^
{IDF_TARGET_NAME} 集成了一个触摸传感器外设,具有多个物理通道。
.. only:: esp32s2 or esp32s3
- 14 个物理电容触摸通道
- 定时器或软件 FSM 触发模式
- 高达 5 种中断(高阈值和低阈值中断、测量单通道完成和测量所有通道完成中断、测量超时中断)
- 睡眠模式唤醒源
- 硬件内置降噪
- 硬件滤波器
- 硬件防水传感器
- 硬件近场感应传感器
这些通道的具体位置如下:
.. list-table::
:header-rows: 1
:widths: 50 50
:align: center
* - 通道
- {IDF_TARGET_NAME}
* - **通道 0**
- **GPIO 0保留**
* - **通道 1**
- **GPIO 1**
* - **通道 2**
- **GPIO 2**
* - **通道 3**
- **GPIO 3**
* - **通道 4**
- **GPIO 4**
* - **通道 5**
- **GPIO 5**
* - **通道 6**
- **GPIO 6**
* - **通道 7**
- **GPIO 7**
* - **通道 8**
- **GPIO 8**
* - **通道 9**
- **GPIO 9**
* - **通道 10**
- **GPIO 10**
* - **通道 11**
- **GPIO 11**
* - **通道 12**
- **GPIO 12**
* - **通道 13**
- **GPIO 13**
* - **通道 14**
- **GPIO 14**
.. only:: esp32
- 10 个物理电容触摸通道
- 定时器或软件 FSM 触发模式
- 2 种中断(超过阈值和低于阈值中断)
- 睡眠模式唤醒源
这些通道的具体位置如下:
.. list-table::
:header-rows: 1
:widths: 50 50
:align: center
* - 通道
- {IDF_TARGET_NAME}
* - **通道 0**
- **GPIO 0有效**
* - **通道 1**
- **GPIO 1**
* - **通道 2**
- **GPIO 2**
* - **通道 3**
- **GPIO 3**
* - **通道 4**
- **GPIO 4**
* - **通道 5**
- **GPIO 5**
* - **通道 6**
- **GPIO 6**
* - **通道 7**
- **GPIO 7**
* - **通道 8**
- **GPIO 8**
* - **通道 9**
- **GPIO 9**
术语
-----------
触摸元件库的有关术语如下:
.. list-table::
:header-rows: 1
:widths: 50 50
:align: center
* - 术语
- 定义
* - **触摸传感器 (touch sensor)**
- 芯片内部的触摸传感器外设
* - **触摸通道 (touch channel)**
- 触摸传感器外设内的触摸通道
* - **触摸焊盘 (touch pad)**
- 外部物理触摸焊盘,通常位于 PCB 内部
* - **降噪通道 (de-noise channel)**
- 内部降噪通道,始终为通道 0 且已预留
* - **屏蔽传感器 (shield sensor)**
- 防水传感器之一,用于小面积的水滴检测,并补偿水滴对读数的影响
* - **防护传感器 (guard sensor)**
- 防水传感器之一,用于大面积的涉水检测,并临时禁用触摸传感器
* - **屏蔽通道 (shield channel)**
- 防水屏蔽传感器连接的通道,始终为通道 14
* - **防护通道 (guard channel)**
- 防水防护传感器连接的通道
* - **屏蔽焊盘 (shield pad)**
- 外部物理屏蔽焊盘,通常是网格状,与防水传感器相连
* - **防护焊盘 (guard pad)**
- 外部物理防护焊盘,通常是环状,与防护传感器相连
.. figure:: /../_static/touch_element/te_component.svg
:scale: 100 %
:align: center
触摸传感器应用程序系统组件
触摸传感器信号
^^^^^^^^^^^^^^^^^^^
触摸传感器可提供以下信号:
- 原始信号:从触摸传感器获取、未经滤波的信号。
- 平滑信号:原始信号通过内部硬件滤波器滤波后的信号。
- 基准信号:经过滤波的信号,已过滤极低频噪声。
以上信号均可通过触摸传感器驱动程序 API 获取。
.. figure:: /../_static/touch_element/te_signal.png
:scale: 40 %
:align: center
触摸传感器信号
触摸传感器信号阈值
^^^^^^^^^^^^^^^^^^^^^^
触摸传感器阈值支持重新配置,可用于确定触摸传感器状态。当平滑信号和基准信号间的差值大于阈值,即 ``(平滑信号 - 基准信号)> 信号阈值`` 时,触摸通道状态改变,并触发触摸中断。
.. figure:: /../_static/touch_element/te_threshold.svg
:scale: 40 %
:align: center
触摸传感器信号阈值
灵敏度
^^^^^^^^^^^^^^^^
触摸传感器的一个重要性能参数,该值越大,表明触摸传感器越灵敏。可以通过以下公式计算:
.. math::
Sensitivity = \frac{Signal_{press} - Signal_{release}}{Signal_{release}} = \frac{Signal_{delta}}{Signal_{benchmark}}
防水性能
^^^^^^^^^^^^^^^^^^
防水性能是触摸传感器的硬件功能,包括防护传感器和屏蔽传感器(始终连接到通道 14可以抵御一定程度的水滴影响并检测水流。
触摸按键
^^^^^^^^^^^^^^^^^^
触摸按键占用触摸传感器的一个通道,外观如下图所示:
.. figure:: /../_static/touch_element/te_button.svg
:scale: 100 %
:align: center
触摸按键
触摸滑条
^^^^^^^^^^^^^^^^^^
触摸滑条占用触摸传感器的多个通道(至少三个),占用的通道越多,滑条的采样分辨率和准确度越高。触摸滑条外观如下图所示:
.. figure:: /../_static/touch_element/te_slider.svg
:scale: 100 %
:align: center
触摸滑条
触摸矩阵
^^^^^^^^^^^^^^^^^^
触摸矩阵按键占用触摸传感器的多个通道(至少 2 + 2 = 4 个通道),它支持通过较少通道获取更多按键。{IDF_TARGET_NAME} 最多支持 49 个按键。触摸矩阵按键外观如下图所示:
.. figure:: /../_static/touch_element/te_matrix.svg
:scale: 100 %
:align: center
触摸矩阵
使用触摸元件库
--------------
使用触摸元件库时,请遵循以下初始化流程:
1. 调用 :cpp:func:`touch_element_install`,初始化触摸元件库。
2. 调用 :cpp:func:`touch_xxxx_install`,初始化触摸元件(按键、滑条等)。
3. 调用 :cpp:func:`touch_xxxx_create`,创建新元件实例。
4. 调用 :cpp:func:`touch_xxxx_subscribe_event`,订阅事件通知。
5. 调用 :cpp:func:`touch_xxxx_set_dispatch_method`,选择事件通知的传递方式。
6. 选择使用回调函数传递事件通知时,调用 :cpp:func:`touch_xxxx_set_callback`,设置事件处理函数。
7. 调用 :cpp:func:`touch_element_start`,启用触摸元件库。
8. 选择使用回调函数传递事件通知时,若事件发生,驱动核心会调用回调函数,你无需做任何处理;选择使用事件任务传递事件通知时,你需要创建一个事件任务,并调用 :cpp:func:`touch_element_message_receive`,循环获取信息。
9. (可选)如果要暂停触摸元件的实时系统,或因某种原因无法获取触摸元件信息,应调用 :cpp:func:`touch_element_stop`,暂停触摸元件系统,然后再次调用 :cpp:func:`touch_element_start` 恢复系统。
上述流程代码如下所示:
.. code-block:: c
static touch_xxx_handle_t element_handle; //声明一个触摸元件句柄
//定义订阅的事件处理函数
void event_handler(touch_xxx_handle_t out_handle, touch_xxx_message_t out_message, void *arg)
{
//事件处理逻辑
}
void app_main()
{
//使用默认初始化器配置触摸元件库
touch_elem_global_config_t global_config = TOUCH_ELEM_GLOBAL_DEFAULT_CONFIG();
touch_element_install(&global_config);
//使用默认初始化器配置触摸元件
touch_xxx_global_config_t elem_global_config = TOUCH_XXXX_GLOBAL_DEFAULT_CONFIG();
touch_xxx_install(&elem_global_config);
//创建新的实例
touch_xxx_config_t element_config = {
...
...
};
touch_xxx_create(&element_config, &element_handle);
//通过事件掩码订阅特定事件
touch_xxx_subscribe_event(element_handle, TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE, NULL);
//选择使用回调函数传递事件通知
touch_xxx_set_dispatch_method(element_handle, TOUCH_ELEM_DISP_CALLBACK);
//注册回调函数
touch_xxx_set_callback(element_handle, event_handler);
//启用触摸元件库处理
touch_element_start();
}
初始化
^^^^^^^^^^^^^^
1. 要初始化触摸元件库,请调用 :cpp:func:`touch_element_install` 函数,并传递一个 :cpp:type:`touch_elem_global_config_t` 类型的实例作为参数,以配置触摸传感器外设和触摸元件库。默认初始化器位于 :cpp:func:`TOUCH_ELEM_GLOBAL_DEFAULT_CONFIG` 中,此默认配置适用于多数常见应用场景。建议在充分了解触摸传感器外设前,不要更改默认配置,以免影响系统。
2. 要初始化特定的触摸元件,需要调用其构造函数 :cpp:func:`touch_xxxx_install`。在调用此构造函数前,所有触摸元件都不会工作,以节省内存。因此,若要设置所需元件,需要为每个要使用的触摸元件分别调用构造函数。
启动触摸元件实例
^^^^^^^^^^^^^^^^
1. 要创建新的触摸元件实例,请调用 :cpp:func:`touch_xxxx_create`,选择一个通道,并将其 `灵敏度`_ 传递给新的元件实例。
2. 要订阅事件通知,请调用 :cpp:func:`touch_xxxx_subscribe_event`。触摸元件库提供了多个事件,事件掩码存放在 :idf_file:`components/touch_element/include/touch_element/touch_element.h` 中。通过使用这些事件掩码,可以订阅单个特定事件,或将单个事件组合在一起,订阅多个事件。
3. 要配置传递事件通知的方式,请调用 :cpp:func:`touch_xxxx_subscribe_event`。触摸元件库提供了两种方式: :cpp:enumerator:`TOUCH_ELEM_DISP_EVENT`:cpp:enumerator:`TOUCH_ELEM_DISP_CALLBACK`,支持以不同方式获取并处理触摸元件信息。
事件处理
^^^^^^^^^^^^^^^^^
如果配置的是 :cpp:enumerator:`TOUCH_ELEM_DISP_EVENT`,需要启用一个事件处理任务获取触摸元件信息。调用 :cpp:func:`touch_element_message_receive` 可以获取所有元件的原始信息,随后通过调用相应的信息解码器 :cpp:func:`touch_xxxx_get_message`,提取特定类型元件的信息,获取有关触摸操作的详细数据。如果配置的是 :cpp:enumerator:`TOUCH_ELEM_DISP_CALLBACK`,在触摸元件开始工作之前,需要调用 :cpp:func:`touch_xxxx_set_callback`,传递一个事件处理函数,有关触摸操作的详细数据都会传递到该事件处理函数。
.. warning::
由于事件处理函数在元件库的核心运行,即在 esp-timer 回调中运行,请避免执行可能导致阻塞或延迟的操作,如调用 :cpp:func:`vTaskDelay`
事件处理过程代码如下所示:
.. code-block:: c
/* ---------------------------------------------- TOUCH_ELEM_DISP_EVENT ----------------------------------------------- */
void element_handler_task(void *arg)
{
touch_elem_message_t element_message;
while(1) {
if (touch_element_message_receive(&element_message, Timeout) == ESP_OK) {
const touch_xxxx_message_t *extracted_message = touch_xxxx_get_message(&element_message); //信息解码
... //事件处理逻辑
}
}
}
void app_main()
{
...
touch_xxxx_set_dispatch_method(element_handle, TOUCH_ELEM_DISP_EVENT); //设置以 TOUCH_ELEM_DISP_EVENT 传递事件通知
xTaskCreate(&element_handler_task, "element_handler_task", 2048, NULL, 5, NULL); //创建一个事件处理任务
...
}
/* -------------------------------------------------------------------------------------------------------------- */
...
/* ---------------------------------------------- TOUCH_ELEM_DISP_CALLBACK ----------------------------------------------- */
void element_handler(touch_xxxx_handle_t out_handle, touch_xxxx_message_t out_message, void *arg)
{
//事件处理逻辑
}
void app_main()
{
...
touch_xxxx_set_dispatch_method(element_handle, TOUCH_ELEM_DISP_CALLBACK); //设置以 ``TOUCH_ELEM_DISP_CALLBACK`` 传递事件通知
touch_xxxx_set_callback(element_handle, element_handler); //注册事件处理函数
...
}
/* -------------------------------------------------------------------------------------------------------------- */
使用防水功能
^^^^^^^^^^^^^^^^
1. 一旦初始化触摸元件的防水功能,防水屏蔽传感器会始终处于开启状态。防水屏蔽传感器为可选项,如果不需要,可以通过配置结构体,将 ``TOUCH_WATERPROOF_GUARD_NOUSE`` 传递给 :cpp:func:`touch_element_waterproof_install`
2. 要关联触摸元件与防护传感器,请调用 :cpp:func:`touch_element_waterproof_add`,将触摸元件句柄添加到触摸元件防水功能的掩码列表中。触摸元件与防护传感器关联后,水流触发防护传感器时会关闭触摸元件,为其提供保护。
查看使用触摸元件防水功能的示例代码,请前往 ESP-IDF 示例的 :example:`peripherals/touch_sensor/touch_element/touch_element_waterproof` 目录。
配置防水功能的代码如下所示:
.. code-block:: c
void app_main()
{
...
touch_xxxx_install(); //初始化实例(按键、滑条等)
touch_xxxx_create(&element_handle); //创建新的触摸元件
...
touch_element_waterproof_install(); //初始化触摸元件防水功能
touch_element_waterproof_add(element_handle); //关联触摸元件与防护传感器
...
}
从 Light/Deep-sleep 模式唤醒
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
仅触摸按键可配置为唤醒源。
使用触摸传感器,可以唤醒从 Light-sleep 或 Deep-sleep 模式中唤醒芯片。在 Light-sleep 模式下,任何已安装的触摸按键都可以唤醒芯片。但在 Deep-sleep 模式下,只有睡眠按键可以唤醒芯片,触摸传感器还会立即进行校准。如果手指没有及时离开,可能导致校准参考值出错。尽管在手指离开后,校准参考值会自行恢复,不会影响驱动逻辑,但如果你不想在从 Deep-sleep 模式唤醒时看到错误的校准参考值,可以调用 :cpp:func:`touch_element_sleep_enable_wakeup_calibration`,禁用唤醒校准功能。
查看使用触摸元件唤醒芯片的示例代码,请前往 ESP-IDF 示例的 :example:`system/light_sleep` 目录。
.. code-block:: c
void app_main()
{
...
touch_element_install();
touch_button_install(); //初始化触摸按键
touch_button_create(&element_handle); //创建新的触摸元件
...
// ESP_ERROR_CHECK(touch_element_enable_light_sleep(&sleep_config));
ESP_ERROR_CHECK(touch_element_enable_deep_sleep(button_handle[0], &sleep_config));
// ESP_ERROR_CHECK(touch_element_sleep_enable_wakeup_calibration(button_handle[0], false)); //(可选)禁用唤醒校准,防止基准值更新为错误值
touch_element_start();
...
}
应用示例
-------------------
查看使用触摸元件库的示例代码,请前往 ESP-IDF 示例的 :example:`peripherals/touch_sensor/touch_element` 目录。
API 参考 - 触摸元件核心
----------------------------------
.. include-build-file:: inc/touch_element.inc
API 参考 - 触摸按键
----------------------------------
.. include-build-file:: inc/touch_button.inc
API 参考 - 触摸滑条
----------------------------------
.. include-build-file:: inc/touch_slider.inc
API 参考 - 触摸矩阵
----------------------------------
.. include-build-file:: inc/touch_matrix.inc