电容触摸按键原理

RC充放电电路原理

在模拟及脉冲数字电路中,经常涉及RC电路。在这些电路中,根据电阻R和电容C的取值不同、输入和输出关系以及处理的波形之间的关系,产生了具有不同功能的RC电路,常见的电路应用包括微分电路 、积分电路、耦合电路、滤波电路及脉冲分压器。RC电路在模拟电路、脉冲数字电路中得到广泛的应用。RC电路原理是模、数电的必备基础知识。

RC充放电电路如下图所示:

RC充放电电路原理讲解:

  • 图中的开关起初处于开启的状态,电容器C上没有电荷,它两端的电压等于零。
  • 当开关闭合时,压降V1通过R向电容器C充电。在电路接通的瞬间,电容器电压Vt=0,充电电流最大值等于V1/R。
  • 随着电容器两极上电荷的积累,Vt逐渐增大,电阻器R上的电压VR=V1-Vc,充电电流i=(V1-Vc)/R,且随着时间的增大而越来越小,Vt的上升也越来越慢。当Vt=V1时,i=0,充电过程结束。

电容充电时间与电容大小关系

RC电路充放电公式:

Vt = V0+(V1-V0)* [1-exp(-t/RC)]

其中:V0 为电容上的初始电压值,V1 为电容最终可充到或放到的电压值,Vt 为t时刻电容上的电压值。

如果V0为0,也就是从0V开始充电。那么公式简化为:

Vt=  V1* [1-exp(-t/RC)]

由此公式可以看出:同样的条件下,电容值C跟时间值t成正比关系,电容越大,充电到达某个临界值的时间越长。

在同一副图中画出两条RC电路曲线,已知电容CB>CA,那么充电到达同一临界值Vth所用的时间关系为:TB>TA。

电容触摸按键

电容触摸按键原理

这里是用的是检测电容充放电时间的方法来判断是否有接触,具体的原理图如下所示:

图中R是外接的电容充电电阻,Cs是没有触摸按下时TPAD与PCB之间的杂散电容。而Cx则是有手指触摸按下的时候,手指与TPAD之间形成的电容,这样的话,有手指触摸按下的时候,电容是Cx+Cs(电容并联相加)

由之前RC电路的原理讲解,不同的电容,在其他的因素都相同的情况下,充电充电到达同一临界值时需要不同的时间的。电容越大,需要的时间越长。

检测电容触摸按键过程

电容触摸按键模块中,电容放电开关,由STM32的IO口代替。具体的电路图如下:

由此可以得到检测电容触摸按键是否被按下的过程:

  • TPAD引脚设置为推挽输出,输出0,实现电容放电到0。
  • TPAD引脚设置为浮空输入(IO复位后的状态),电容开始充电。
  • 同时开启TPAD引脚的输入捕获开始捕获。
  • 等待充电完成(充电到达Vth,检测到上升沿)。
  • 计算充电时间。

输入捕获部分的内容,可以参考学习:【STM32】通用定时器的输入捕获(实例:输入捕获)。

判断依据:没有按下的时候,充电时间为T1(default)。按下TPAD,电容变大,所以充电时间为T2。我们可以通过检测充放电时间,来判断是否按下。如果T2-T1大于某个值(阈值),就可以判断有按键按下。

STM32控制电容触摸按键

硬件连接

  • 单片机:STM32F103ZET6
  • 模块:电容触摸按键模块
  • 引脚连接:TPAD:PA1
  • 硬件资源:指示灯DS0、DS1,定时器TIM5通道2

具体的硬件连接的图如下所示:

STM32控制程序

STM32控制电容触摸按键的主要步骤:

  • 初始化触摸按键:初始化定时器TIM5的输入捕获,捕获10次无触摸按下到达上升沿的时间;
  • 触摸按键扫描:捕获3次有触摸按下到达上升沿的时间,阈值判断;
#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;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/2的数值,不正常!return 0;
}
//复位一次
void TPAD_Reset(void)
{GPIO_InitTypeDef  GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);     //使能PA端口时钟//设置GPIOA.1为推挽使出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);                         //PA.1输出0,放电delay_ms(5);TIM_SetCounter(TIM5,0);        //归0TIM_ClearITPendingBit(TIM5, TIM_IT_CC2|TIM_IT_Update); //清除中断标志//设置GPIOA.1为浮空输入GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;  //浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);}
//得到定时器捕获值
//如果超时,则直接返回定时器的计数值.
u16 TPAD_Get_Val(void)
{                  TPAD_Reset();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);
}
//读取n次,取最大值
//n:连续获取的次数
//返回值: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;
}
//扫描触摸按键
//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,可以开始检测;>0,还不能开始检测     u8 res=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))//大于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;
}
//定时器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端口时钟//设置GPIOA.1为浮空输入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;                //PA1 端口配置GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //速度50MHzGPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;    //浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);    //设置为浮空输入//初始化TIM5  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向上计数模式TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位//初始化通道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 IC2TIM_Cmd(TIM5,ENABLE );   //使能定时器5
}
 int main(void){ u8 t=0;    delay_init();            //延时函数初始化    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置NVIC中断分组2:2位抢占优先级,2位响应优先级uart_init(115200);  //串口初始化为115200LED_Init();               //LED端口初始化TPAD_Init(6);            //初始化触摸按键while(1){                                                   if(TPAD_Scan(0))   //成功捕获到了一次上升沿(此函数执行时间至少15ms){LED1=!LED1;       //LED1取反}t++;if(t==15)       {t=0;LED0=!LED0;     //LED0取反,提示程序正在运行}delay_ms(10);}}

整个程序基本只要分析一个函数:TPAD_Get_Val()函数

首先需要TPAD_Reset(),它的意义在于先设置PA1推挽输出,同时设置PA1输出低电平放电,延时等待放电完成:

 //设置GPIOA.1为推挽使出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);                         //PA.1输出0,放电delay_ms(5);

之后设置PA1浮空输入,清零TIM5的输入捕获:

 TIM_SetCounter(TIM5,0);     //归0TIM_ClearITPendingBit(TIM5, TIM_IT_CC2|TIM_IT_Update); //清除中断标志//设置GPIOA.1为浮空输入GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;  //浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);

准备工作做完了之后,就可以进行输入捕获了:

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);   

【常用模块】电容触摸按键模块(原理讲解、STM32实例操作)相关推荐

  1. Fluent 嵌套网格(overset)功能讲解与实例操作

    作者 | 张杨 在流体仿真中,我们经常会遇到边界运动的问题,如: 生物医疗行业中血管的运动 航空航天行业中飞行器的分离 容积泵中齿轮的相对运动 在ANSYS Fluent 17.0之前的版本中,我们通 ...

  2. STM32精英版(正点原子STM32F103ZET6开发板)学习篇12——电容触摸按键实验

    电容触摸按键原理 RC充放电电路原理:   RC充放电原理,其实就是电(R)和电容(C)组成的串联电路.   按键开关未按下时,电路两端电压都是0V,无法形成电势差,也就无法形成电流.但当按键开关按下 ...

  3. IoT物联网嵌入式设备中30种常见传感器模块简介及原理讲解

    IoT物联网嵌入式设备中30种常见传感器模块简介及原理讲解 0.前言 一.光学传感器模块: 1. 光敏传感器模块: 2. 红外避障模块 3. 循迹传感器模块 4. U型光电传感器模块 5. 红外接收模 ...

  4. 光立方原理讲解_一分钟讲解光模块原理与结构

    文章导览 光模块简介 光模块的主要参数及意义 光模块的内部结构 光模块的发展趋势 有首歌这样唱: 如果你愿意一层一层 一层地剥开我的心 你会发现 你会讶异... 然而,最后流着泪发现洋葱是没有心的. ...

  5. android stm32 wifi模块,STM32F1模块篇ESP8266WIFI模块工作原理

    ESP8266 WIFI 模块工作原理 ESP8266概述 ESP8266是一个完整且自成体系的Wi-Fi网络解决方案,能够搭载软件应用,或通过另一个应用处理器卸载所有Wi-Fi网络功能. ESP82 ...

  6. HC-05蓝牙模块,主从一体机原理总结

    HC-05蓝牙模块,主从一体机原理总结 原理就是:手机通过蓝牙传输到HC-05上,再通过串口通信和STM32通信:而之前一般都是电脑上通过USB线转串口的方式,通过串口和STM32通信.本质上没有区别 ...

  7. python常用模块之shelve模块

    python常用模块之shelve模块 shelve模块是一个简单的k,v将内存中的数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据类型 我们在上面讲json.pickle ...

  8. python shelve模块_python常用模块之shelve模块

    python常用模块之shelve模块 shelve模块是一个简单的k,v将内存中的数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据类型 我们在上面讲json.pickle ...

  9. 判断按键值_「正点原子NANO STM32开发板资料连载」第十六章电容触摸按键实验...

    1)实验平台:ALIENTEK NANO STM32F411 V1开发板2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第十六章电容 ...

  10. STM32学习心得十九:电容触摸按键实验及相关代码解读

    记录一下,方便以后翻阅~ 主要内容 1) 电容触摸按键原理: 2)部分实验代码解读. 实验内容 手触摸按键后,LED1灯翻转. 硬件原理图 上图,TPAD与STM_ADC用跳线帽相连,即TPAD与PA ...

最新文章

  1. 算力觉醒后,智慧距离勃发就只差一个想法
  2. python小游戏系列井字棋,儿时的回忆
  3. uva 558 Wormholes
  4. python连接clickhouse
  5. !!统计字符(处理字符串)(getline函数使用)
  6. PaddlePaddle Transformer encoder 源码解析 v1.7
  7. vue axios ts 封装流文件下载方法
  8. viper4android哪个版本好,ViPER4Android FX蝰蛇音效下载-ViPER4Android FX蝰蛇音效 v2.7.0.0_手机乐园...
  9. Worktile Teambition 与Tower 使用对比
  10. PowerShell中使用WMI或CIM
  11. 因特尔显卡自定义分辨率_为什么从最新的英特尔显卡控制面板中移除了自定义分辨率?...
  12. 区块链 交易和区块数据存在哪儿
  13. android恢复短信中心号码,短信中心号码设置解决安卓手机不能发短信问题,教你设置解决异地发不了短信问题...
  14. 现汇买入价/现钞买入价/卖出价/基准价/中行折算价的概念
  15. 热重启golang服务器(graceful restart golang http server)
  16. 计算机专业毕业文案,毕业微信朋友圈说说 2020毕业文案经典个性
  17. vue3 ts 挂载全局vscode volar使用飘红
  18. 垃圾大学,想自学 Java 可以吗?难吗?毕业后能找到一份 6k左右的工作吗?
  19. 大数据的数据科学与关键技术是什么?
  20. Elasticsearch解决只能查询10000条数据以及查询的total为10000条的解决方案

热门文章

  1. 为什么学习嵌入式会搞单片机以及如何学习C51单片机
  2. stm32神舟I号开发板下的六子棋开发
  3. 工单管理软件,免费工单管理系统
  4. MDM页面UI升级介绍
  5. 百度 李彦宏 2008年在北大毕业典礼的演讲稿
  6. ACdream - 1073 雷霆战机
  7. django 转发_Django开发常用30个软件包
  8. linux网络操作系统项目教程课本,Linux网络操作系统项目式教程(CentOS7.6)-课后练习题.docx...
  9. 通达OA2019安装教程
  10. 错误:“应用程序无法启动,因为应用程序的并行配置不正确。请参阅应用程序事件日志,或使用命令行sxstrace.exe工具” 的解决