| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480 |
- 触摸元件
- =============
- :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
|