软硬件资源
- 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);
}