TS_Self_Cap---Key_Event_State

需求情景

这里写图片描述

如上图,单电容触摸按键,返回的是按键电容对应的一个数值。当人不触碰按键是,,计数值TSICNT大。 当人触摸按键后,TSICNT变小。

如何把具体数值的变化,变成人理解的按下 释放呢?


设计思路

状态定义:

空闲状态 IDLE(检测是否进入TOUCH状态;更新BASELINE值;)
人手按下状态 TOUCH(检测是否保持TOUCH状态,还是切到RELEASE状态)
人手释放状态 RELEASE(等待固定时间,进入IDLE状态)


区间定义:

key_baseline

在人不触碰TouchSense的情况下,采集一个基准值key_baseline

IDLE状态定义一个区间

key_baseline-key_baseline_delta ~~~key_baseline+key_baseline_delta

定义成key_idle_low ~~~key_idle_high

key_baseline_delta 取5U

key_touch_delta

定义一个人触碰下的界限值key_touch_threshold_temp =key_baseline - key_touch_delta

key_touch_delta取200U


状态转换条件:

IDLE

key_state_temp = kKey_State_Idle;
key_event = kKey_Event_Idle;

IDEL—>TOUCH

连续检测采样值小于key_touch_threshold_temp 达到MAX_TOUCH_DEBOUNCE这么多次数,可以认为肯定有人触摸按键,状态转换。
key_state_temp = kKey_State_Touched;
key_event = kKey_Event_Touch;
if (key_state_temp == kKey_State_Idle)
{
key_event = kKey_Event_Idle;

    if (TSI_sampleResult < key_touch_threshold_temp)
    {
        /* There's a finger touch */
        key_touch_debounce_temp++;
        key_release_debounce_temp = 0U;

        if (key_touch_debounce_temp > MAX_TOUCH_DEBOUNCE)
        {
            key_touch_debounce_temp = 0U;
            key_release_debounce_temp = 0U;
            key_event = kKey_Event_Touch; /* Indicates the TSI channel is touched */
            key_state_temp = kKey_State_Touched;
        }
    }
    else
    {
        key_touch_debounce_temp = 0U; //从这可以看出需要连续MAX_BASELINE_DEBOUNCE这么多次
        key_release_debounce_temp = 0U;
    }
}

TOUCH状态保持

只要TSI_sampleResult < key_touch_threshold_temp,可以肯定人手一直按着,状态不变
key_state_temp = kKey_State_Touched;
key_event = kKey_Event_Touch;

TOUCH—>RELEASE

当TSI_sampleResult > key_touch_threshold_temp,开始计次数,如果连续MAX_TOUCH_DEBOUNCE这么多次采样值都大于key_touch_threshold_temp,可以确定人手释放,状态切换。
key_event = kKey_Event_Release;
key_state_temp = kKey_State_Released;

    else if (key_state_temp == kKey_State_Touched)
    {
        key_event = kKey_Event_Touched; /* Indicates the TSI channel is touched */

        if (TSI_sampleResult < key_touch_threshold_temp)
        {
            /* Indicates the TSI channel is Stick Touched */
            key_release_debounce_temp = 0U; //这边清零了,所以是需要连续的MAX_TOUCH_DEBOUNCE次release检测
        }
        else
        {
            /* Condition: finger touch release */
            key_touch_debounce_temp = 0U;
            key_release_debounce_temp++;

            if (key_release_debounce_temp > MAX_TOUCH_DEBOUNCE)
            {
                key_release_debounce_temp = 0U;
                key_event = kKey_Event_Release;
                key_state_temp = kKey_State_Released;
            }
        }
    }

RELEASE—>IDLE

等待适合的时间,状态切换。
key_event = kKey_Event_Idle;
key_state_temp = kKey_State_Idle;


IDLE区间的实时更新:

我们想保证按键事件的准确,必须保证key_baseline_temp这个基准的准确。那怎么调整基准值,啥时调整的?

这时候就是key_idle_low和key_idle_high这两个值登场的时候啦。key_baseline_delta 取5U,所以key_idle_low和key_idle_high相差10U。

上调

只要检测到TSI_sampleResult > key_idle_high,就计数一次。连续检测到MAX_BASELINE_DEBOUNCE这么多次,就 把基准上调1;
key_baseline_temp = key_baseline_temp + 1U;

下调

只要检测到TSI_sampleResult < key_idle_low,就计数一次。连续检测到MAX_BASELINE_DEBOUNCE这么多次,就 把基准下调1;
key_baseline_temp = key_baseline_temp - 1U;

        else if (TSI_sampleResult > key_idle_high)
        {
            key_touch_debounce_temp = 0U;
            key_base_debounce_temp++;

            if (key_base_debounce_temp > MAX_BASELINE_DEBOUNCE)
            {
                key_base_debounce_temp = 0U;
                key_baseline_temp = key_baseline_temp + 1U;
            }
        }
        else if (TSI_sampleResult < key_idle_low)
        {
            key_touch_debounce_temp = 0U;
            key_base_debounce_temp++;

            if (key_base_debounce_temp > MAX_BASELINE_DEBOUNCE)
            {
                key_base_debounce_temp = 0U;
                key_baseline_temp = key_baseline_temp - 1U;
            }
        }
        else
        {
            key_touch_debounce_temp = 0U;
            key_base_debounce_temp = 0U;//这边清零了,所以是需要连续的MAX_TOUCH_DEBOUNCE次base_debounce检测
        }


学习程序过程遇到问题

/* Key event indicates momentary actions */
typedef enum _key_event
{
    kKey_Event_Idle = 0U, /* Key is not touched */
    kKey_Event_Touch,    /* Key is touched for the first time */
    kKey_Event_Touched,  /* Key has been touched */
    kKey_Event_Stick,    /* Key has been touched for a long time */
    kKey_Event_Release,  /* Key is released for the first time */
    kKey_Event_Released, /* Key has been released */
    kKey_Event_Abnormal, /* Key is in abnormal status */
}key_event_t;
kKey_Event_Release,  /* Key is released for the first time */
kKey_Event_Released, /* Key has been released */

就是没看清这个Release 和 Released两个状态

感觉Released状态就是为了在正确检测到release之后等待一会儿,等电容值回归到正常值,再进入IDLE状态。如果直接进入IDLE状态,程序就会开始不停的进行key_baseline的调整。怎么感觉这种功能可以通过调节触发进入Release的计数次数来改变啊???

为什么要等待合适时间?其实是主程序的需求。主程序需要检测到release这个状态进行输出。

    else if (key_state_temp == kKey_State_Touched)
    {
        key_event = kKey_Event_Touched; /* Indicates the TSI channel is touched */

        if (TSI_sampleResult < key_touch_threshold_temp)
        {
            /* Indicates the TSI channel is Stick Touched */
            key_release_debounce_temp = 0U;
        }
        else
        {
            /* Condition: finger touch release */
            key_touch_debounce_temp = 0U;
            key_release_debounce_temp++;

            if (key_release_debounce_temp > MAX_TOUCH_DEBOUNCE)
            {
                key_release_debounce_temp = 0U;
                key_event = kKey_Event_Release;
                key_state_temp = kKey_State_Released;
            }
        }
    }
    else if (key_state_temp == kKey_State_Released)
    {
        /* Restore KEY_STATE_IDLE automatically */
        key_event = kKey_Event_Released;

        key_release_debounce_temp++;

        if (key_release_debounce_temp > 10U)
        {
            /* Delay to assure this key is sent */
            key_release_debounce_temp = 0U;
            key_event = kKey_Event_Idle;
            key_state_temp = kKey_State_Idle;
        }
    }
发布了51 篇原创文章 · 获赞 26 · 访问量 8万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章