软硬件资源

  • ESP32-S3
  • ESP-IDF v4.4.1

ESP32-S3 有 14 个电容式触摸传感器,对应 14 个 GPIO 口。详细的介绍可以看这里:触摸传感器 - ESP32-S3 - — ESP-IDF 编程指南 latest 文档

触摸传感器可以由读数触发或中断触发,其中中断触发比较节省算力,但使用中断方式的 ESP32-S3 官方例程中的一些 API 在我的 ESP-IDF 开发环境下调用不了,原因未知,使用 ESP32 对应的例程又无法触发中断。因此我最终还是选择了读数触发的方式,后面有时间了再研究中断方式。

我的代码是在官方例程的基础上修改而来,代码如下,代码含义见注释:

头文件

#ifndef MONITORSYSTEM_TOUCH_BUTTON_H
#define MONITORSYSTEM_TOUCH_BUTTON_H

#include <stdbool.h>

/**
 * @brief 触摸按键初始化
 */
void touch_button_init(void);

/**
 * @brief 读取按键状态
 * @param pvParameter
 */
void ReadButton_task(void *pvParameter);

#define TOUCH_BUTTON_NUM (2)  //按键个数
#define BUTTON_SWITCH_TAB 0   //切换标签页按键对应编号
#define BUTTON_SCROLL_PAGE 1  //滚动页面按键对应编号
#define TOUCH_THRESHOLD_RATE 4//触摸传感器触发阈值倍率,决定触摸灵敏度
                              //测试时,触摸的原始数据是未触摸的6~12倍

//触摸按键标志位
extern bool button_touched[TOUCH_BUTTON_NUM];

#endif //MONITORSYSTEM_TOUCH_BUTTON_H

源文件

#include "../inc/touch_button.h"

#include "driver/touch_pad.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

//触摸按键对应IO口
static const touch_pad_t button[TOUCH_BUTTON_NUM] = {
        TOUCH_PAD_NUM5, //切换标签页按键
        TOUCH_PAD_NUM6  //滚动页面按键
};

bool button_touched[TOUCH_BUTTON_NUM] = {
        false,
        false
};

//触摸按键初始化校准值
uint32_t button_init_val[TOUCH_BUTTON_NUM] = {
        0,
        0
};

void ReadButton_task(void *pvParameter)
{
    uint32_t touch_value;

    //等待触摸传感器初始化完成
    vTaskDelay(100 / portTICK_RATE_MS);

    //初始化校准
    int test_num = 5;
    touch_pad_read_raw_data(button[BUTTON_SWITCH_TAB],&button_init_val[BUTTON_SWITCH_TAB]);
    touch_pad_read_raw_data(button[BUTTON_SCROLL_PAGE],&button_init_val[BUTTON_SCROLL_PAGE]);
    while(test_num--){
        for(int i = 0;i < TOUCH_BUTTON_NUM;i++){
            touch_pad_read_raw_data(button[i],&touch_value);
            button_init_val[i] = (button_init_val[i] + touch_value) / 2;
        }
    }

    while (1) {
        for (int i = 0; i < TOUCH_BUTTON_NUM; i++) {
            touch_pad_read_raw_data(button[i], &touch_value);
            //触摸到按键
            if(touch_value > TOUCH_THRESHOLD_RATE * button_init_val[i]){
                //等待脱离按键
                while(1){
                    vTaskDelay(50 / portTICK_PERIOD_MS);//避免一直占用核心
                    touch_pad_read_raw_data(button[i], &touch_value);
                    if(touch_value < TOUCH_THRESHOLD_RATE * button_init_val[i]){
                        button_touched[i] = true;
                        break;
                    }
                }
            }
        }
        vTaskDelay(200 / portTICK_PERIOD_MS);
    }
}

void touch_button_init(void){
    //初始化触摸传感器驱动
    touch_pad_init();
    //初始化IO
    for(int i = 0; i < TOUCH_BUTTON_NUM; i++){
        touch_pad_config(button[i]);
    }
    //设置滤波
    touch_pad_denoise_t denoise = {
            .grade = TOUCH_PAD_DENOISE_BIT4,
            .cap_level = TOUCH_PAD_DENOISE_CAP_L4,
    };
    touch_pad_denoise_set_config(&denoise);
    touch_pad_denoise_enable();
    //使能触摸传感器时钟,工作模式为定时器触发
    touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
    touch_pad_fsm_start();
}

主函数

void app_main() {
    touch_button_init();
    xTaskCreate(&ReadButton_task,"ReadButton_task",2048,NULL,5,NULL);
}
最后修改:2023 年 10 月 16 日
如果觉得我的文章对你有用,请随意赞赏