簡介
用來偵測到手指的有效觸摸,通過觸摸電容屏幕達到類似觸摸按鍵的作用,相對於傳統的機械按鍵有壽命長、佔用空間少、易於操作等諸多優點。
原理
觸摸按鍵原理
未觸摸時,觸摸系統內僅有一個電容,對其先放電再充電,通過輸入捕獲(或其它方法)測出充電所需時間T1,當觸摸時,觸摸系統相當於並聯多一個電容,總電容增大,充電時間延長,通過測量此時充電所需時間T2,如果T2>T1,則已觸摸。(時間測量放在while(1)裏,即時刻測量,當測到T2,即已觸摸時,進行相應函數)
即系統檢測電容充放電時間的方法來判斷是否有觸摸 :
檢測過程
1.TPAD引腳(即觸摸按鍵 )設置爲推輓輸出,輸出0,使電容放電到0;
2.TPAD引腳設置爲浮空輸入(即IO口復位後的狀態),使電容開始充電;同時開啓TPAD引腳的輸入捕獲;
3.等待充電完成(充電到相應界限使得檢測到上升沿)
4.記錄充電時間。
程序思路
圖片源自正點原子視頻:
代碼相關
代碼實現
1.復位TPAD
1.獲取電容沒有被觸摸時從無電到充電至觸發輸入捕獲的平均時間tpad_default_val
u8 TPAD_Init(u8 psc)
{
u16 buf[10];//讀取10次
u16 temp;//取平均值
u8 j,i;
TIM5_CH2_Cap_Init(TPAD_ARR_MAX_VAL,psc-1);//以1Mhz的頻率計數
for(i=0;i<10;i++)//連續讀取10次
{
buf[i]=TPAD_Get_Val();//得到定時器捕獲值
delay_ms(10);
}
for(i=0;i<9;i++)//排序
{
for(j=i+1;j<10;j++)
{
if(buf[i]>buf[j])//升序排列
{
temp=buf[i];
buf[i]=buf[j];
buf[j]=temp;
}
}
}
temp=0;
for(i=2;i<8;i++)temp+=buf[i];//取中間的6個數據進行平均
tpad_default_val=temp/6;
printf("tpad_default_val:%d\r\n",tpad_default_val);
if(tpad_default_val>TPAD_ARR_MAX_VAL/2)return 1;//初始化遇到超過TPAD_ARR_MAX_VAL(ARR最大的值)/2的數值,不正常!
return 0;
2.得到定時器捕獲值(如果超時,則直接返回定時器的計數值.)
u16 TPAD_Get_Val(void)
{
TPAD_Reset();//計數器歸0
while(TIM_GetFlagStatus(TIM5, TIM_IT_CC2) == RESET)//等待捕獲上升沿
{
if(TIM_GetCounter(TIM5)>TPAD_ARR_MAX_VAL-500)return TIM_GetCounter(TIM5);//超時了,直接返回CNT的值
};
return TIM_GetCapture2(TIM5);
}
3.返回n次讀數裏面讀到的最大讀數值,如果這個值比平均值大,則按下
u16 TPAD_Get_MaxVal(u8 n)//
{
u16 temp=0;
u16 res=0;
while(n--)
{
temp=TPAD_Get_Val();//得到一次值
if(temp>res)res=temp;
};
return res;
}
4.設置掃描觸摸按鍵
u8 TPAD_Scan()
{
static u8 keyen=0; //0,可以開始檢測;>0,還不能開始檢測
u8 res=0;
u8 sample=3; //默認採樣次數爲3次
u16 rval;
rval=TPAD_Get_MaxVal(sample);
if(rval>(tpad_default_val+TPAD_GATE_VAL))//大於tpad_default_val+TPAD_GATE_VAL,有效
{
if(keyen==0)res=1; //keyen==0,有效
//printf("r:%d\r\n",rval);
keyen=3; //至少要再過3次之後才能按鍵有效
}
if(keyen)keyen--;
return res;
}
5.以定時器2通道2爲例配置輸入捕獲
void TIM5_CH2_Cap_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM5_ICInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //使能TIM5時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口時鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //PA1 端口配置
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //浮空輸入
GPIO_Init(GPIOA, &GPIO_InitStructure); //設置爲浮空輸入
TIM_TimeBaseStructure.TIM_Period = arr; //設定計數器自動重裝值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //預分頻器
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設置時鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //初始化TIM5
//初始化通道2
TIM5_ICInitStructure.TIM_Channel = TIM_Channel_2; //CC1S=01 選擇輸入端 IC2映射到TI5上
TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲
TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置輸入分頻,不分頻
TIM5_ICInitStructure.TIM_ICFilter = 0x03;//IC2F=0011 配置輸入濾波器 8個定時器時鐘週期濾波
TIM_ICInit(TIM5, &TIM5_ICInitStructure);//初始化I5 IC2
TIM_Cmd(TIM5,ENABLE ); //使能定時器5
}
之後,在主函數先初始化TPAD_Init(6);
通過對函數TPAD_Scan(0)
的判斷確定是否有觸摸
調用10次:取中間6次的平均值,使取值較穩定