一. 电容触摸按键原理
1.电路原理介绍

上图是基于整点原子STM32F4的原理图,其中蓝色TPAD部分就是我们电容触摸按键位置,红色的TPAD是悬空的,需要我们将其与其他引脚相连接起来。在开发板上,我们需要用跳线帽将STM ADC与TAPD连接起来,这样TAPD引脚就可以与PA5连接起来了。(也可以用其他引脚)
由于要用到捕获,因为我们需要在数据手册上查看PA5可以对应哪一个定时器通道。

由上图我们选择定时器2通道1。

上图是按键按下前后对比图。R:外接电容充放电电阻。
按键按下之前,电路之中只连接了一个电容Cs(TPAD和PCB间的杂散电容),按键按下之后,与Cs并联了一个Cx(手指按下时,手指和TPAD之间的电容),电路总电容变大。其中开关部分是电容放电开关,由STM32 IO口代替。也就是对应着第一张图片的红色TAPD脚。
根据电路知识可知,电容上的充放电公式为:

V0 为电容上的初始电压值;
V1 为电容最终可充到或放到的电压值;
Vt 为t时刻电容上的电压值。
RC为充电时间常数,是电容的端电压达到最大值的0.63倍时所需要的时间,通常认为时间达到5倍的充电时间常数后就认为充满了。时间常数越大,电容充放电就越慢(大电容和小电容相比肯定是大电容充电慢;大电阻和小电阻相比,大电阻起始电流较小,因此大电阻充电时间慢)。根据这个原理我便可涉及触摸按键的使用原理了。
2. 具体原理介绍
由以上分析我们得知,在电阻相同的条件下,电容越大,充电到某一电压值的时间越长,因此我们记录触摸按键没有触摸时电容的充电时间T1,之后的检测以这个时间做标准,按下TPAD,电容变大,所以充电时间为T2。我们可以通过检测充放电时间,来判断是否按下。如果T2-T1大于某个值,就可以判断有按键按下。
3. 检测电容触摸按键的过程
①. TPAD引脚设置为推挽输出,输出0,实现电容放电到0。(相当于将红色TPAD接地)
②. TPAD引脚设置为浮空输入(IO复位后的状态),电容开始充电。(相当于将红色TAPD断开)
③. 同时开启TPAD引脚的输入捕获开始捕获。
④. 等待充电完成(充电到底Vx,检测到上升沿)。
⑤. 计算充电时间。
二. 程序设计
1.具体程序及详细说明

头文件"tpad.h"里面就是对tapd.c里面的函数内容进行申明,具体内容如下:

#ifndef __TPAD_H
#define __TPAD_H
#include "sys.h"
void TPAD_Reset(void);
u16 TPAD_Get_Val(void);
u16 TPAD_Get_MaxVal(u8 n);
u8 TPAD_Init(u32 psc);      //初始化触摸按键,记录没有按下的电容充电时间,初始化成功返回0,未成功返回1;
u8 TPAD_Scan(u8 mode);
void TIM2_CH1_Cap_Init(u32 arr,u16 psc);#endif

宏定义及头文件部分:对于代码vu16类型说明:
typedef __IO uint16_t vu16; 这是本身在stm2f4xx.h头文件里面定义了的。

#include "tpad.h"
#include "delay.h"
#include "usart.h"
#define TPAD_ARR_MAX_VAL  0XFFFFFFFF    //最大的ARR值(TIM2是32位定时器),防止捕获的时候CCRX>ARR
vu16 tpad_default_val=0;               //空载的时候(没有手按下),计数器需要的时间
#define TPAD_GATE_VAL 100                           //触摸的门限值,也就是必须tpad_default_val+TPAD_GATE_VAL,才认为是有效触摸

捕获相关程序-----TIM2_CH1_Cap_Init(),当电容开始充电并且达到能够捕获上升沿的电压时,就会捕获到一个上升沿。

void TIM2_CH1_Cap_Init(u32 arr,u16 psc)      //定时器 2 通道 1 输入捕获配置
{GPIO_InitTypeDef GPIO_InitStruct;TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_ICInitTypeDef TIM_ICInitStruct;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);         //TIM2时钟使能RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);      //GPIOA时钟使能GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;                        //GPIOA5GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF;                        //复用功能GPIO_InitStruct.GPIO_Speed=GPIO_Speed_100MHz;GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;                  //推挽复用输出GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;                    //不带上下拉GPIO_Init(GPIOA,&GPIO_InitStruct);                           //初始化PA5GPIO_PinAFConfig(GPIOA,GPIO_PinSource5,GPIO_AF_TIM2);       //将GPIO5复用映射到TIM2TIM_TimeBaseInitStruct.TIM_Prescaler=psc;                 //TIM2分频系数TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;   //TIM2向上计数模式TIM_TimeBaseInitStruct.TIM_Period=arr;                     //重载值TIM_TimeBaseInitStruct.    TIM_ClockDivision=TIM_CKD_DIV1;TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);             //初始化定时器2TIM_ICInitStruct.TIM_Channel=TIM_Channel_1;                   //TIM2的通道1TIM_ICInitStruct.TIM_ICPolarity=TIM_ICPolarity_Rising;       //上升沿捕获TIM_ICInitStruct.TIM_ICSelection=TIM_ICSelection_DirectTI;  //IC1映射到TI1上TIM_ICInitStruct.TIM_ICPrescaler=TIM_ICPSC_DIV1;                   //不分频TIM_ICInitStruct.TIM_ICFilter=0000;                               //不滤波TIM_ICInit(TIM2,&TIM_ICInitStruct);                            //初始化TIM2捕获通道1TIM_Cmd(TIM2,ENABLE);
}

TAPD_Reset(),主要作用就是让电容放电

void TPAD_Reset(void)        //复位一次,并让电容放电,清零定时计数器
{GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;             //PA5GPIO_InitStruct.GPIO_Mode=GPIO_Mode_OUT;          //普通输出模式GPIO_InitStruct.GPIO_Speed=GPIO_Speed_100MHz;      //速度100MHZGPIO_InitStruct.GPIO_OType=GPIO_OType_PP;            //推挽输出GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_DOWN;            //下拉GPIO_Init(GPIOA,&GPIO_InitStruct);                  //初始化GPIOAGPIO_ResetBits(GPIOA,GPIO_Pin_5);                 //PA5输出0,电容放电delay_ms(5);                                        //等待放电结束TIM_SetCounter(TIM2,0);                             //TIM2计数器清0GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;                //PA5GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF;               //复用功能GPIO_InitStruct.GPIO_Speed=GPIO_Speed_100MHz;        //速度100MHZGPIO_InitStruct.GPIO_OType=GPIO_OType_PP;            //推挽复用输出GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;            //既不上拉也不下拉GPIO_Init(GPIOA,&GPIO_InitStruct);                    //初始化GPIOA}

TPAD_Get_Val,这个函数作用是获取到达上升沿时的计数器里面的计数值,为计算电容充电时间提供数据。

u16 TPAD_Get_Val(void)           //得到定时器的捕获值
{TPAD_Reset();while(TIM_GetFlagStatus(TIM2, TIM_IT_CC1) == RESET)//等到电容充电到一个值后产生上升沿捕获{if(TIM_GetCounter(TIM2)>TPAD_ARR_MAX_VAL-500)        //超过正常按下时间,直接返回定时器计数值return TIM_GetCounter(TIM2);}return TIM_GetCapture1(TIM2);      //返回定时器捕获值}

TAPD_Get_MaxVal,这个函数的作用是为了后面判断按键触摸时触摸是否有效,取最大值判断更精确。

u16 TPAD_Get_MaxVal(u8 n)//n为读取的次数
{u16 temp=0,res=0;while(n--){temp=TPAD_Get_Val();if(temp>res)res=temp;}return res;
}

TAPD_InIT()

u8 TPAD_Init(u32 psc)        //初始化触摸按键,记录没有按下的电容充电时间,初始化成功返回0,未成功返回1
{u16 ChargingTimeData[10],temp;u8 i,j;TIM2_CH1_Cap_Init(TPAD_ARR_MAX_VAL,psc-1);for(i=0;i<10;i++)     //读取10次值{ChargingTimeData[i]=TPAD_Get_Val();delay_ms(10);}for(i=0;i<9;i++)           //数组升序排列{for(j=0;j<10;j++){   if(ChargingTimeData[i]>ChargingTimeData[j])temp=ChargingTimeData[i];ChargingTimeData[i]=ChargingTimeData[j];ChargingTimeData[j]=temp;}}temp=0;for(i=2;i<8;i++)     //取中间6个数据做平均值temp+=ChargingTimeData[i];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;
}

触摸按键扫描部分

u8 TPAD_Scan(u8 mode) //mode=1支持一直按下,mode=0,不支持一直按下//返回值为1有按下,返回值为0没有按下
{static u8 keyen=0; //0,可以开始检测;>0,还不能开始检测u8 res=0,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)&&rval<(10*tpad_default_val))  //大于 tpad_default_val+TPAD_GATE_VAL,且小于 10 倍 tpad_default_val,则有效{if((keyen==0)&&(rval>(tpad_default_val+TPAD_GATE_VAL)))                //大于 tpad_default_val+TPAD_GATE_VAL,有效res=1;keyen=3; //至少要再过 3 次之后才能按键有效}if(keyen)keyen--;return res;}

整体思路:

流程图:

笔记14:STM32F4之电容触摸按键相关推荐

  1. STM32学习笔记(11)电容触摸按键

    文章目录 简介 原理 触摸按键原理 检测过程 程序思路 代码相关 代码实现 简介 用来侦测到手指的有效触摸,通过触摸电容屏幕达到类似触摸按键的作用,相对于传统的机械按键有寿命长.占用空间少.易于操作等 ...

  2. 正点原子stm32f429 pcb_正点原子【STM32-F407探索者】第十六章 电容触摸按键实验

    1)资料下载:点击资料即可下载 2)对正点原子Linux感兴趣的同学可以加群讨论:935446741 3)关注正点原子公众号,获取最新资料更新 http://weixin.qq.com/r/hEhUT ...

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

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

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

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

  5. node.js学习笔记14—微型社交网站

    node.js学习笔记14-微型社交网站 1.功能分析 微博是以用户为中心,因此需要有注册和登录功能. 微博最核心的功能是信息的发表,这个功能包括许多方面,包括:数据库访问,前端显示等. 一个完整的微 ...

  6. Linux学习笔记14

    Linux学习笔记14 Linux学习笔记14 DNS服务搭建 基本介绍 使用bind搭建dns服务 增加一个域名zone 配置DNS转发 配置主从 测试主从同步 后续课程 DNS服务搭建 基本介绍 ...

  7. 【转】 C#学习笔记14——Trace、Debug和TraceSource的使用以及日志设计

    [转] C#学习笔记14--Trace.Debug和TraceSource的使用以及日志设计 Trace.Debug和TraceSource的使用以及日志设计   .NET Framework 命名空 ...

  8. 台大李宏毅Machine Learning 2017Fall学习笔记 (14)Unsupervised Learning:Linear Dimension Reduction

    台大李宏毅Machine Learning 2017Fall学习笔记 (14)Unsupervised Learning:Linear Dimension Reduction 本博客整理自: http ...

  9. stm32按键矩阵代码_STM32学习日志——电容触摸按键实验(20-06-27)

    昨天在公司值班学习的,敲完代码笔记本没电了,没更新日志,今天补更新.学习应持之以恒,谁都会有惰性,应尽力克服. 这次的代码很有意思,可以学到很多编程的思想. 首先,电容触摸按键是基于模电的RC充放电电 ...

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

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

最新文章

  1. Uva1595 对称轴
  2. MapReduce输入输出的处理流程及combiner
  3. vue中img标签onerror事件
  4. 规则引擎Easy-rules
  5. 官宣,11月8号,.NET6+64位VS璀璨面世!
  6. 确认!别再相信Python了! 程序员:就你敢说...
  7. HTML和CSS进阶
  8. vba 定义类_工作表中如何响应自定义事件
  9. springMVC环境搭建
  10. win32 sdk C语言菜单,win32 sdk 设定/获取checkbox控件状态
  11. 【转】如何打包发布基于Qt4 Windows的软件
  12. 漫画:趣解鸿蒙 OS 如何实现跨平台?
  13. 晶闸管的原理及伏安特性
  14. 基于STM32F407的ESP8266WIFI模块联控
  15. 2022-2028年中国光电广告产业竞争现状及发展趋势分析报告
  16. [Java 内存]Java内存组成
  17. 当贝X3 Pro与极米H5哪个画质好,哪一款更值得购买?
  18. 软件测试技术之iOS 单元测试—逻辑测试
  19. NKOI 1349 工作安排
  20. 找出并打印1至1000以内的质数

热门文章

  1. OPNET出错集锦:)
  2. element-ui对话框fullscreen.lock使用
  3. 中国北斗卫星导航系统
  4. 投影仪与计算机连接方式,投影仪怎么连接电脑 电脑与投影仪的连接方法
  5. 11-新闻发布系统数据库-新闻数据操作
  6. v8引擎编译全记录2020-10-17(保姆级教程)
  7. NetBean将IDE设置导出为Zip存档
  8. 高德地图通过经纬度获取地区城市
  9. TranslateAnimation 使用详解
  10. c语言课程火车售票报告,C语言课程设计报告书火车票务管理系统.doc