Page 1 of 1

求一个t3超低功耗模组的触摸代码

Posted: 2025年 Sep 19日 17:34
by a93749

各位大佬,大家早上、中午、晚上好:

我想要一个基于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欧电阻到触摸弹簧,弹簧后面不接东西Image

若有帮助,感激不尽