首页
|
新闻
|
新品
|
文库
|
方案
|
视频
|
下载
|
商城
|
开发板
|
数据中心
|
座谈新版
|
培训
|
工具
|
博客
|
论坛
|
百科
|
GEC
|
活动
|
主题月
|
电子展
注册
登录
论坛
博客
搜索
帮助
导航
默认风格
uchome
discuz6
GreenM
»
MCU 单片机技术
»
ARM
» NucleoF429 基础应用3:GPIO Touch Key(触摸按键)-1
返回列表
回复
发帖
发新话题
发布投票
发布悬赏
发布辩论
发布活动
发布视频
发布商品
NucleoF429 基础应用3:GPIO Touch Key(触摸按键)-1
发短消息
加为好友
look_w
当前离线
UID
1066743
帖子
8283
精华
0
积分
4142
阅读权限
90
在线时间
233 小时
注册时间
2017-6-23
最后登录
2019-5-18
论坛元老
UID
1066743
1
#
打印
字体大小:
t
T
look_w
发表于 2018-1-24 20:21
|
只看该作者
NucleoF429 基础应用3:GPIO Touch Key(触摸按键)-1
这里先不说触摸(Touch)按键的优缺点,只从GPIO实现Touch Key的方法上来讲下这个Demo。Touch Key的实现方式有多种,效果和稳定性也相差很大。有些是硬件上专门做了设计,且有不少是有专利的。记得ST有支持Touch Key的型号,也有对应的库,但没用过。进入正题-->
1、Touch Key 硬件原理:
Touch Key检测的原理网络上也有许多,方法各异,此文中的Touch Key 如下图:
实现原理是将
Touch Pad
和
人体
等效为一个电容,Touch Pad的电容固定,和一个电阻并联到GND。IO输出High后,再转为Input,Touch Pad上的电荷通过电阻放电,只要Touch Pad的等效电容和电阻阻值不变,放电时间就是固定的。当有触摸时,人体等效电容相当于并联到了Touch Pad上,总的等效电容增大,放电时间增加,通过判断这个增加的“电容”大小,就能判断是否有触摸。如下图:红色的曲线为无触摸时的放电曲线,放电时间为t0,蓝色曲线为有触摸时的放电曲线,放电时间为t1,两者的差值为Δt。由Δt的大小可判断是否有触摸。VIL是IO读到低电平的阈值
下面是实际测量的电容放电波形:
可以看到,放电时间在10us左右(330K下拉电阻,有触摸时大概增加5us左右),这还是加了示波器探头的放电时间,如果不加探头,时间大概小一半,
下图是一个简易的Touch Pad。铜箔大小越1cm2,覆盖了透明胶带。下拉330K电阻,铜箔等效电容估计个位数pF。
以上是硬件方面和检测的原理。下面来看如何检测这个电容变化量?
2、Touch Key 软件原理:
2.1、电路原理知道了,电容放电的波形也看到了,如何检测变化量呢?用ADC?有无触摸的电压变化量在mV级别,时间为us级别,用多大速度和分辨率的ADC暂且不管,主要是有很多MCU并不具备ADC模块,如果外接满足这个要求的ADC还不如用一颗触摸芯片来的简单。测量电压行不通,那就测量时间吧。(以下的方法可以等效为一个简易的ADC)
上面有提到,有无触摸,放电波形会有5us的变化量。5us对于几十MHz的MCU来说能做太多事了。我这里采用的方法并不是采用中断,因为5us的变化量测量得需要上MHz的中断且获得的数据变化也不明显,所以我采用了do while(Loop)方式,IO输出High充电完成转为Input,通过电阻放电,直到IO读到低电平,在放电期间,放一个计数器,基本是以一条指令的时间来计数的,而且获得的数据变化量够大,便于后期计算,比如10MHz主频执行单周期指令计数,1us计数10次,5us计数50次,还可以连续做多次充放电,将计数累加,有无触摸就会有上百次的计数值变化,完全可以被检测出来。这是我的计数函数,在IO设置为Input后,查询IO是否为低,并且做计数,函数中连续做了16次累加,因为整个while循环中,执行while判断的时间是最长的,所以减少while判断可以计数更多的值,我的TouchKey是在PE0上,如果为High,计数值递增为1,如果换作其他IO时,在读到值之后做相应的移位,使每次递增为1即可,
/*----------------------------------------------------------------------------*/uint16_t Get_Touch_Value(void){ //HAL_GPIO_WritePin(GPIOC,GPIO_PIN_10,GPIO_PIN_SET); Touch_Count = 0; GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); //while(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_0)) //2 while(GPIOE->IDR & GPIO_PIN_0) //1 { Touch_Count +=(GPIOE->IDR & GPIO_PIN_0); Touch_Count +=(GPIOE->IDR & GPIO_PIN_0); Touch_Count +=(GPIOE->IDR & GPIO_PIN_0); Touch_Count +=(GPIOE->IDR & GPIO_PIN_0); Touch_Count +=(GPIOE->IDR & GPIO_PIN_0); Touch_Count +=(GPIOE->IDR & GPIO_PIN_0); Touch_Count +=(GPIOE->IDR & GPIO_PIN_0); Touch_Count +=(GPIOE->IDR & GPIO_PIN_0); Touch_Count +=(GPIOE->IDR & GPIO_PIN_0); Touch_Count +=(GPIOE->IDR & GPIO_PIN_0); Touch_Count +=(GPIOE->IDR & GPIO_PIN_0); Touch_Count +=(GPIOE->IDR & GPIO_PIN_0); Touch_Count +=(GPIOE->IDR & GPIO_PIN_0); Touch_Count +=(GPIOE->IDR & GPIO_PIN_0); Touch_Count +=(GPIOE->IDR & GPIO_PIN_0); Touch_Count +=(GPIOE->IDR & GPIO_PIN_0); } GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); HAL_GPIO_WritePin(GPIOE,GPIO_PIN_0,GPIO_PIN_SET); //HAL_GPIO_WritePin(GPIOC,GPIO_PIN_10,GPIO_PIN_RESET); return Touch_Count;}
2.2、因为手指本身有干扰,并且手指与Touch Pad的接触面积也不固定,导致增量时间时刻在变化,必须要经过滤波处理,如下图中的Touch按下部分,波形有杂波,在Touch隔离物较厚时,干扰问题会更严重且数据变化量较小,不经过滤波处理,误触发的几率会很大。
收藏
分享
评分
回复
引用
订阅
TOP
返回列表
电商论坛
Pine A64
资料下载
方案分享
FAQ
行业应用
消费电子
便携式设备
医疗电子
汽车电子
工业控制
热门技术
智能可穿戴
3D打印
智能家居
综合设计
示波器技术
存储器
电子制造
计算机和外设
软件开发
分立器件
传感器技术
无源元件
资料共享
PCB综合技术
综合技术交流
EDA
MCU 单片机技术
ST MCU
Freescale MCU
NXP MCU
新唐 MCU
MIPS
X86
ARM
PowerPC
DSP技术
嵌入式技术
FPGA/CPLD可编程逻辑
模拟电路
数字电路
富士通半导体FRAM 铁电存储器“免费样片”使用心得
电源与功率管理
LED技术
测试测量
通信技术
3G
无线技术
微波在线
综合交流区
职场驿站
活动专区
在线座谈交流区
紧缺人才培训课程交流区
意见和建议