当前位置: 首页>編程日記>正文

电容触摸按键原理

电容触摸按键原理

前置技能

   
  输入按键-GPIO输入

  通用定时器原理


RC充放电电路原理

RC充放电电路

如图:电阻R和电容C串联当开关断开时,电阻R,电容0两端电压都是0,无电流当开关闭合时(瞬间),电阻R两端V1(上端)和0(下端)有电压差,产生电流此时电子通过电阻R积累在电容正极(上端),直到电容C电压为V1,充电完成此时R两端电压均为V1,无压差,不再有电流经过电容C的电压从0-V1,充电过程中,有充电时间t和电容C的电压Vt之间的关系(右图)
看以看出随充电时间越来越长,充电的效率(斜率)越来越低分析:当按键按下瞬间,电阻R两端电压V1和0,此时瞬间电流为I = V1 / R当电容C充电一段时间后,假设电容C此时的电压为Vc,那么此时电阻C两端的电压为V1和Vc,此时的瞬间电流为I = (V1-Vc) / R所以随着充电时间的增加,电容C的电压增加,电阻R两端压差减小,电流降低,电子积累速度减慢,充电效率降低

RC电路充放电公式

Vt = V0 + (V1 - V0) * [1 - exp(-t / RC)]V0:电容的初始电压值
V1:电容最终可以冲/放到的电压值
Vt:电容t时刻的电压值若电容C从0V开始充电,那么V0 = 0,则公式简化为:
Vt =V1 * [1 - exp(-t / RC)]

公式中V1, R均为常数,要达到相同的充电电压Vt,那么充电时间t和电容值C,成正比

RC电路电容与电阻关系

结论:同样条件下,电容C和充电时间t成正比达到相同的电压,电容越大,所需要的充电时间越长

电容触摸按键原理

电容触摸按键原理

R:外接电容充放电电阻
Cs:TPAD与PCB之间存在杂散电容
Cx:当手指按下时,手指和TPAD之间的电容图A:手指未按下时的电路,TPAD与PCB之间存在电容Cs图B:当手指按下时,手指与TPAD之间存在电容Cx,此时相当于Cs与Cx并联,电容总值=Cs+Cx根据上边”RC充放电电路原理”可知:当R一定时,达到相同的电压,电容越大,需要的充电时间越长所以,我们假设未触摸时充电时间为T1,触摸时充电时间为T2(T2 > T1)

检测电容触摸按键过程

1,电容放电到0TPAD引脚设置为推挽输出,放电放电到0V后,将计数器值设置为0,充电计时使用2,电容充电TPAD引脚设置为浮空输入(IO复位后的状态)3,充电完成(Vx)进入输入捕获TPAD引脚开启输入捕获因为放完电的时候C的电压为 0,所以设置上升沿捕获4,是否按下-计算充电时间,对比是否按下当未按下时,记录充电完成的时间T1(计数器频路*数值)检测当次充电时间T2,与T1对比,如果超过预设时间T3,说明按键按下

电容触摸按键的硬件连接

电容触摸按键的硬件连接

PA1引脚说明:

PA1引脚说明

如图:电容触摸按键TPAD(黄色部分),TPAD引脚与PA1项链使用TIM5_CH2进行输入捕获

代码实现

tpad.h声明功能函数

#ifndef __TPAD_H
#define __TPAD_H
#include "sys.h"// 未按下电容触摸按键时的充电时间
extern vu16 tpad_default_val;     // 复位TPAD:
// 设置推挽输出放电到0;再设置浮空输入充电,计数器CNT=0
void  TPAD_Reset(void);// 获取一次捕获事件得到充电时间:
// 复位TPAD,等待捕获上升沿,得到计数器值,计算充电时间
u16   TPAD_Get_Val(void);// n次调用TPAD_Get_Val取最大值
u16   TPAD_Get_MaxVal(u8 n);// 初始化TPAD:
// 系统启动后初始化输入捕获,10次调用TPAD_Get_Val()
// 取中间n次平均值,作为未按下时的充电时间tpad_default_val
u8     TPAD_Init(u8 psc);// 扫描TPAD:
// 调用TPAD_Get_MaxVal获取多次充电中最大充电时间
// 与tpad_default_val对比,若超过tpad_default_val+TPAD_GATE_VAL则为触摸
u8     TPAD_Scan(u8 mode);// 输入捕获通道初始化
void  TIM5_CH2_Cap_Init(u16 arr,u16 psc);#endif

tpad.c-tpad.h声明功能函数的实现

#include "tpad.h"
#include "delay.h"
#include "usart.h"#define TPAD_ARR_MAX_VAL 0XFFFF    // ARR最大值
vu16 tpad_default_val=0;           // 没有按下是的充电时间// 初始化触摸按键
// 获取空载时触摸按键取值
// 返回值: 0:初始化成功 1:初始化失败
u8 TPAD_Init(u8 psc)
{u16 buf[10];u16 temp;u8 j,i;// 初始化定时器5通道2输入捕获TIM5_CH2_Cap_Init(TPAD_ARR_MAX_VAL, psc-1);//以1Mhz的频率计算// 连续读取10次TPAD_Get_Val(),间隔10msfor(i=0;i<10;i++) {buf[i]=TPAD_Get_Val();// 10次定时器值装入数组delay_ms(10);}// 将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;}}}// 取第2-8次充电时间取平均值,串口打印输出temp=0;for(i=2;i<8;i++)temp+=buf[i];tpad_default_val=temp/6;printf("tpad_default_val:%d\r\n",tpad_default_val);//  初始化遇到超过TPAD_ARR_MAX_VAL/2的数值,不正常if(tpad_default_val>TPAD_ARR_MAX_VAL/2) return 1;return 0;
}// TPAD复位
void TPAD_Reset(void)
{GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟// 设置PA1为推挽输出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;             // PA1引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      // 推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_ResetBits(GPIOA, GPIO_Pin_1);                    // PA1输出0,放电delay_ms(5);     //延迟5ms 等待放电结束,电容电压此时为0VTIM_SetCounter(TIM5, 0);        //定时器5计数器设置为0TIM_ClearITPendingBit(TIM5, TIM_IT_CC2|TIM_IT_Update); //清除中断标志//设置PA1为浮空输入-开始充电GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);}// 获得定时器捕获值-上升沿捕获
u16 TPAD_Get_Val(void)
{// TPAD复位:PA1推挽输出放电到0,再设置PA1浮空输入充电,定时器=1,清除中断标志TPAD_Reset();// 等待捕获上升沿while(TIM_GetFlagStatus(TIM5, TIM_IT_CC2) == RESET){// 超时,返回CNT值if(TIM_GetCounter(TIM5)>TPAD_ARR_MAX_VAL-500)return TIM_GetCounter(TIM5);};return TIM_GetCapture2(TIM5); // 返回通道2的捕获值
}// 连续n次读取TPAD_Get_Val,返回最大值
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;
}// 扫描触摸按键
// mode:0,不支持连续,1,支持联系
// 返回值:0,没有按下;1,有按下
#define TPAD_GATE_VAL 100    //门限值:大于tpad_default_val+TPAD_GATE_VAL视为按下
u8 TPAD_Scan(u8 mode)
{static u8 keyen=0;    // 是否可检测状态位 0:可以开始检验 1: 还不能检验u8 res=0;             // 返回是否按下 1:按下 0:未按下u8 sample=3;          // 默认采样3次u16 rval;             // 捕获到上升沿的最大值// 如果支持连续触发if(mode){sample=6;         // 连续触发时,采样为6此keyen=0;          //支持连续}//取采样次数的最大值rval=TPAD_Get_MaxVal(sample);//对比是否按下了if(rval>(tpad_default_val+TPAD_GATE_VAL)){if(keyen==0)res=1;      // keyen==0,有效,返回1//printf("r:%d\r\n",rval);keyen=3;                // 至少再扫描3次后按键才能生效}if(keyen)keyen--;return res;
}// 定时器5通道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);    // 使能定时器5时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   // 使能GPIOA时钟 // 初始化GPIOA-浮空输入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;               // PA1GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       // 50MhzGPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;     // 浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);//定时器5初始化TIM_TimeBaseStructure.TIM_Period = arr;                 // 重装载值TIM_TimeBaseStructure.TIM_Prescaler =psc;               // 预分频器TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 设置时钟分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;// 向上计数TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);//初始化通道2TIM5_ICInitStructure.TIM_Channel = TIM_Channel_2; // CC1S=01 设置IC2映射到TI5TIM5_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);// 初始化定时器5 IC2TIM_Cmd(TIM5, ENABLE ); // 使能定时器5
}

main.c 当捕获到电容触摸按键按下(捕获上升沿),LED1反转

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "tpad.h"int main(void){u8 t=0;                      // 计数器delay_init();                // 延时函数初始化NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 中断优先级分组配置uart_init(115200);           // 串口初始化 115200LED_Init();                  // LED初始化TPAD_Init(6);                // TPAD初始化while(1){if(TPAD_Scan(0))        // 捕获到上升沿(此函数执行至少15ms){LED1=!LED1;          // LED1取反}t++;if(t==15){t=0;LED0=!LED0;          // LED0闪烁,标志程序正在运行}delay_ms(10);            // 延时10ms}}

实验结果

LED0每间隔一段时间闪烁,标志程序正在运行中
当手指按下电容触摸按键时,LED1取反


https://www.fengoutiyan.com/post/15299.html

相关文章:

  • 电容触摸与手指示意图
  • 亚克力触摸按键原理
  • 电容触摸滑条原理图解
  • 模拟电容触摸按键怎么用
  • 感应电容原理
  • 电容式感应触摸开关原理
  • 屏幕按键电路原理图
  • 短接模拟电容按键点击
  • 鏡像模式如何設置在哪,圖片鏡像操作
  • 什么軟件可以把圖片鏡像翻轉,C#圖片處理 解決左右鏡像相反(旋轉圖片)
  • 手機照片鏡像翻轉,C#圖像鏡像
  • 視頻鏡像翻轉軟件,python圖片鏡像翻轉_python中鏡像實現方法
  • 什么軟件可以把圖片鏡像翻轉,利用PS實現圖片的鏡像處理
  • 照片鏡像翻轉app,java實現圖片鏡像翻轉
  • 什么軟件可以把圖片鏡像翻轉,python圖片鏡像翻轉_python圖像處理之鏡像實現方法
  • matlab下載,matlab如何鏡像處理圖片,matlab實現圖像鏡像
  • 圖片鏡像翻轉,MATLAB:鏡像圖片
  • 鏡像翻轉圖片的軟件,圖像處理:實現圖片鏡像(基于python)
  • canvas可畫,JavaScript - canvas - 鏡像圖片
  • 圖片鏡像翻轉,UGUI優化:使用鏡像圖片
  • Codeforces,CodeForces 1253C
  • MySQL下載安裝,Mysql ERROR: 1253 解決方法
  • 勝利大逃亡英雄逃亡方案,HDU - 1253 勝利大逃亡 BFS
  • 大一c語言期末考試試題及答案匯總,電大計算機C語言1253,1253《C語言程序設計》電大期末精彩試題及其問題詳解
  • lu求解線性方程組,P1253 [yLOI2018] 扶蘇的問題 (線段樹)
  • c語言程序設計基礎題庫,1253號C語言程序設計試題,2016年1月試卷號1253C語言程序設計A.pdf
  • 信奧賽一本通官網,【信奧賽一本通】1253:抓住那頭牛(詳細代碼)
  • c語言程序設計1253,1253c語言程序設計a(2010年1月)
  • 勝利大逃亡英雄逃亡方案,BFS——1253 勝利大逃亡
  • 直流電壓測量模塊,IM1253B交直流電能計量模塊(艾銳達光電)
  • c語言程序設計第三版課后答案,【渝粵題庫】國家開放大學2021春1253C語言程序設計答案
  • 18轉換為二進制,1253. 將數字轉換為16進制
  • light-emitting diode,LightOJ-1253 Misere Nim
  • masterroyale魔改版,1253 Dungeon Master
  • codeformer官網中文版,codeforces.1253 B
  • c語言程序設計考研真題及答案,2020C語言程序設計1253,1253計算機科學與技術專業C語言程序設計A科目2020年09月國家開 放大學(中央廣播電視大學)
  • c語言程序設計基礎題庫,1253本科2016c語言程序設計試題,1253電大《C語言程序設計A》試題和答案200901
  • 肇事逃逸車輛無法聯系到車主怎么辦,1253尋找肇事司機