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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章