各位大佬,大家早上、中午、晚上好:
我想要一个基于T3模组通过触摸中断实现按键功能的示例代码。
目前我参考了3.12.0 SDK中 software/TuyaOS/vendor/T3/t3_os/armino/components/demos/peripheral/touch/touch_demo.c 的代码,自己实现了一套触摸扫描逻辑。该 demo 中提供的函数主要用于触摸校准,但我没有太看明白具体的中断触发机制和硬件应如何配置。
在我目前的实现中,是通过校准扫描获取一个基准值,如果该值发生变化,就认为有触摸事件发生。但这种方法只能依赖轮询方式检测,无法利用中断,导致响应速度较慢、灵敏度较低,同时在多通道的情况下也担心会出现误判或性能问题。下面是我代码中所使用的函数
Code: Select all
touch_key34_read()/touch_key32_read()/touch_key36_read()
获取校准值的变化并做相关判断。
touch_key.c
Code: Select all
#include "touch_key.h"
#include "key.h"
#include <driver/touch_types.h>
#include "tal_log.h"
// #include "touch_driver.h"
#define FILTER_LEN 10
static uint32_t cap_out_buf_6[FILTER_LEN] = {0};
static uint32_t cap_out_buf_8[FILTER_LEN] = {0};
static uint32_t cap_out_buf_10[FILTER_LEN] = {0};
static uint32_t moving_average(uint32_t *buf, uint32_t new_val)
{
for (int i = FILTER_LEN - 1; i > 0; i--)
{
buf[i] = buf[i - 1];
}
buf[0] = new_val;
uint32_t sum = 0;
for (int i = 0; i < FILTER_LEN; i++)
{
sum += buf[i];
}
return sum / FILTER_LEN;
}
void touch0_gpio12_isr_callback(void *arg)
{
TAL_PR_INFO("touch0_gpio12_isr_callback");
}
void touch6_gpio32_isr_callback(void *arg)
{
TAL_PR_INFO("touch6_gpio32_isr_callback");
}
void touch8_gpio34_isr_callback(void *arg)
{
TAL_PR_INFO("touch8_gpio34_isr_callback");
}
void touch10_gpio36_isr_callback(void *arg)
{
TAL_PR_INFO("touch8_gpio34_isr_callback");
}
// read touch key 32
KEY_RESULT_E touch_key32_read(KEY_S *key)
{
/*uint8_t channel = 0;
switch (key->pin_id)
{
case TUYA_GPIO_NUM_34:
channel = BK_TOUCH_8;
break;
case TUYA_GPIO_NUM_32:
channel = BK_TOUCH_6;
break;
case TUYA_GPIO_NUM_36:
channel = BK_TOUCH_10;
break;
default:
TAL_PR_INFO("touch key read pin_id error");
channel = 0;
return KEY_ERROR;
}*/
bk_touch_gpio_init(BK_TOUCH_6);
bk_touch_enable(BK_TOUCH_6);
#if (CONFIG_SOC_BK7236XX || CONFIG_SOC_BK7239XX || CONFIG_SOC_BK7286XX)
bk_touch_set_test_mode(0, 0);
bk_touch_set_calib_mode(0x3F, 9);
#endif
bk_touch_calibration_start();
uint32_t cap_out = bk_touch_get_calib_value();
uint32_t cap_out_filt = moving_average(cap_out_buf_6, cap_out);
// TAL_PR_INFO("key1(filtered) = %d\r\n", cap_out_filt);
if (cap_out_filt > 430)
{
TAL_PR_INFO("key1(filtered) = %d\r\n", cap_out_filt);
//key->normal_callback();
return KEY_NORMAL_PRESS;
}else{
return KEY_ERROR;
}
}
// read touch key 32
KEY_RESULT_E touch_key34_read(KEY_S *key)
{
bk_touch_gpio_init(BK_TOUCH_8);
bk_touch_enable(BK_TOUCH_8);
#if (CONFIG_SOC_BK7236XX || CONFIG_SOC_BK7239XX || CONFIG_SOC_BK7286XX)
bk_touch_set_test_mode(0, 0);
bk_touch_set_calib_mode(0x3F, 9);
#endif
bk_touch_calibration_start();
uint32_t cap_out = bk_touch_get_calib_value();
uint32_t cap_out_filt = moving_average(cap_out_buf_8, cap_out);
// TAL_PR_INFO("key1(filtered) = %d\r\n", cap_out_filt);
// TAL_PR_INFO("key3(filtered) = %d\r\n", cap_out_filt);
if (cap_out_filt > 453)
{
TAL_PR_INFO("key3(filtered) = %d\r\n", cap_out_filt);
//key->normal_callback();
return KEY_NORMAL_PRESS;
}
}
KEY_RESULT_E touch_key36_read(KEY_S *key)
{
bk_touch_gpio_init(BK_TOUCH_10);
bk_touch_enable(BK_TOUCH_10);
#if (CONFIG_SOC_BK7236XX || CONFIG_SOC_BK7239XX || CONFIG_SOC_BK7286XX)
bk_touch_set_test_mode(0, 0);
bk_touch_set_calib_mode(0x3F, 9);
#endif
bk_touch_calibration_start();
uint32_t cap_out = bk_touch_get_calib_value();
uint32_t cap_out_filt = moving_average(cap_out_buf_10, cap_out);
if (cap_out_filt > 432)
{
TAL_PR_INFO("key2(filtered) = %d\r\n", cap_out_filt);
return KEY_NORMAL_PRESS;
}
}
KEY_RESULT_E touch_key_init(KEY_S *key)
{
if (key == NULL)
{
TAL_PR_INFO("key is NULL");
return KEY_ERROR;
}
TAL_PR_INFO("touch key init pin_id:%d", key->pin_id);
uint32_t touch_channel = 0;
// 2. 配置参数
touch_config_t config;
uint32_t touch_id = 0;
uint32_t cap_out = 0;
uint32_t gain_s = 0;
switch (key->pin_id)
{
case TUYA_GPIO_NUM_12:
touch_channel = BK_TOUCH_0;
break;
case TUYA_GPIO_NUM_13:
touch_channel = BK_TOUCH_1;
break;
case TUYA_GPIO_NUM_28:
touch_channel = BK_TOUCH_2;
break;
case TUYA_GPIO_NUM_32:
// key->callback = touch6_gpio32_isr_callback;
key->get_value = touch_key32_read;
touch_channel = BK_TOUCH_6;
break;
case TUYA_GPIO_NUM_34:
// key->callback = touch8_gpio34_isr_callback;
key->get_value = touch_key34_read;
touch_channel = BK_TOUCH_8;
break;
case TUYA_GPIO_NUM_36:
// key->callback = touch10_gpio36_isr_callback;
key->get_value = touch_key36_read;
touch_channel = BK_TOUCH_10;
break;
default:
break;
}
TAL_PR_INFO("touch single channel calib mode test %d start!\r\n", touch_channel);
bk_touch_gpio_init(touch_channel);
config.sensitivity_level = TOUCH_SENSITIVITY_LEVLE_3;
config.detect_threshold = TOUCH_DETECT_THRESHOLD_7;
config.detect_range = TOUCH_DETECT_RANGE_8PF;
bk_touch_config(&config);
// bk_touch_register_touch_isr(touch_channel, key->callback, NULL);
bk_touch_int_enable(touch_channel, 1);
bk_touch_enable(touch_channel);
return KEY_SUCCESS;
}
KEY_RESULT_E touch_key_deinit(KEY_S **key)
{
}
KEY_RESULT_E touch_key_read(KEY_S *key)
{
}
KEY_RESULT_E _touch_task(void *arg)
{
}
KEY_S *touch_key_create(TUYA_GPIO_NUM_E pin_id)
{
KEY_S *key = (KEY_S *)tkl_system_malloc(sizeof(KEY_S));
if (key == NULL)
{
TAL_PR_INFO("key malloc failed");
return NULL;
}
memset(key, 0, sizeof(KEY_S));
key->init = touch_key_init;
key->deinit = touch_key_deinit;
//key->get_value = touch_key_read;
//key->normal_callback = normal_press;
//key->long_press_callback = long_press;
key->pin_id = pin_id;
// key->callback= touch_key_isr_callback;
TAL_PR_INFO("!!!!!touch key task create success pin_id:%d init:%p touch_key_init:%p", key->pin_id, key, touch_key_init);
return key;
}
key.h
Code: Select all
#ifndef _KEY_H__
#define _KEY_H__
#include "tuya_cloud_types.h"
// #include "touch_types.h"
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct key KEY_S;
// GPIO电平状态枚举
typedef enum
{
GPIO_LEVEL_LOW = 0,
GPIO_LEVEL_HIGH = 1
} GPIO_LEVEL_E;
// 操作结果枚举
typedef enum
{
KEY_SUCCESS = 0,
KEY_NORMAL_PRESS = 1,
KEY_LONG_PRESS = 2,
KEY_ERROR_INVALID_PARAM,
KEY_ERROR_HARDWARE,
KEY_ERROR_NOT_INITIALIZED,
KEY_ERROR
} KEY_RESULT_E;
// 按键初始化函数类型
typedef KEY_RESULT_E (*key_init_func)(KEY_S *key);
// 按键反初始化函数类型
typedef KEY_RESULT_E (*key_deinit_func)(KEY_S *key);
// 获取按键值函数类型
typedef KEY_RESULT_E (*key_get_value_func)(KEY_S *key);
typedef KEY_RESULT_E (*key_scan_touch_value_func)(KEY_S *key);
// 按键中断服务函数类型
typedef VOID (*key_isr_func)(VOID);
struct key
{
TUYA_GPIO_NUM_E pin_id; // 按键对应的GPIO引脚
GPIO_LEVEL_E gpio_level; // GPIO电平状态
key_init_func init; // 初始化函数指针
key_deinit_func deinit; // 反初始化函数指针
key_get_value_func get_value; // 获取按键值函数指针
key_isr_func normal_callback; // 短按回调函数指针
key_isr_func long_press_callback; // 长按回调函数指针
// key_scan_touch_value_func scan_touch_func; // 触摸按键扫描值函数指针
};
#ifdef __cplusplus
}
#endif
#endif /* _KEY_H__ */
轮询操作
Code: Select all
OPERATE_RET op_ret = OPRT_OK;
TUYA_GPIO_LEVEL_E read_level = TUYA_GPIO_LEVEL_HIGH;
UINT32_T time_start = 0, timer_end = 0;
SWITCH_S *sw1 = switch_create(TUYA_GPIO_NUM_12, TUYA_GPIO_NUM_16);
SWITCH_S *sw2 = switch_create(TUYA_GPIO_NUM_13, TUYA_GPIO_NUM_24);
SWITCH_S *sw3 = switch_create(TUYA_GPIO_NUM_17, TUYA_GPIO_NUM_15);
sw1->init(sw1);
sw2->init(sw2);
sw3->init(sw3);
KEY_S *key1 = touch_key_create(32);
KEY_S *key2 = touch_key_create(36);
KEY_S *key3 = touch_key_create(34);
// KEY_S *key2 = touch_key_create(32);
TAL_PR_INFO("key1 create success key1:%p key1->init:%p", key1, key1->init);
key1->init(key1);
TAL_PR_INFO("key2 create success key2:%p key2->init:%p", key2, key2->init);
key2->init(key2);
TAL_PR_INFO("!!!!!!!!!!key3 create success key3:%p key3->init:%p", key3, key3->init);
key3->init(key3);
for (;;)
{
if (key3->get_value(key3) == KEY_NORMAL_PRESS)
{
TAL_PR_INFO("key3 press");
tal_system_sleep(20);
// upload_device_switch_status(sw1->onoff);
if (key3->get_value(key3) != KEY_NORMAL_PRESS)
{
TAL_PR_INFO("continues");
continue;
}
time_start = tal_system_get_millisecond();
while (key3->get_value(key3) == KEY_NORMAL_PRESS)
{
tal_system_sleep(50);
timer_end = tal_system_get_millisecond();
if (timer_end - time_start >= LONE_PRESS_TIME)
{
TAL_PR_DEBUG("long press, remove device");
}
}
if (timer_end - time_start > 50)
{
TAL_PR_DEBUG("normal press");
switch_toggle(sw3);
}
}
if (key2->get_value(key2) == KEY_NORMAL_PRESS)
{
TAL_PR_INFO("key2 press");
tal_system_sleep(20);
// upload_device_switch_status(sw1->onoff);
if (key2->get_value(key2) != KEY_NORMAL_PRESS)
{
continue;
}
time_start = tal_system_get_millisecond();
while (key2->get_value(key2) == KEY_NORMAL_PRESS)
{
tal_system_sleep(50);
timer_end = tal_system_get_millisecond();
if (timer_end - time_start >= LONE_PRESS_TIME)
{
TAL_PR_DEBUG("long press, remove device");
}
}
if (timer_end - time_start > 50)
{
TAL_PR_DEBUG("normal press");
switch_toggle(sw2);
}
}
if (key1->get_value(key1) == KEY_NORMAL_PRESS)
{
TAL_PR_INFO("key1 press");
tal_system_sleep(20);
// upload_device_switch_status(sw1->onoff);
if (key1->get_value(key1) != KEY_NORMAL_PRESS)
{
continue;
}
time_start = tal_system_get_millisecond();
while (key1->get_value(key1) == KEY_NORMAL_PRESS)
{
tal_system_sleep(50);
timer_end = tal_system_get_millisecond();
if (timer_end - time_start >= LONE_PRESS_TIME)
{
TAL_PR_DEBUG("long press, remove device");
}
}
if (timer_end - time_start > 50)
{
TAL_PR_DEBUG("normal press");
switch_toggle(sw1);
}
}
}
下面时我做的开关的pcb,触摸引脚做了串联200欧电阻到触摸弹簧,弹簧后面不接东西
若有帮助,感激不尽