首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

NucleoF429 基础应用3:GPIO Touch Key(触摸按键)-1

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隔离物较厚时,干扰问题会更严重且数据变化量较小,不经过滤波处理,误触发的几率会很大。
返回列表