“电容触摸按键实验”实例解析

最新更新时间:2022-04-20来源: eefocus 手机看文章 扫描二维码
随时随地手机看文章

电容触摸按键实验

电容触摸按键的基本原理(原理图层面)

新电容的产生与作用

我们学过模电的同学知道:我们的手其实相当于一块可以存储感应电荷的金属板,当我们的手靠近屏幕时,我们的手与屏幕下的金属板Cx构成了一个平行电容板,这个电容与Cs杂散电容相并联,“并联电容C=C1+C2”。


充放电性能的变化

我们看见“VCC是一定的;电容C越大代表一定电压下,存储的电荷数量越多(Q=CU),反之,充电到U所花费的时间也更多;电阻R的值一定代表着对电荷的阻碍作用是固定的”。


充电到V=Vth,花费时间TA明显小于TB;我们真实情况下的矩形脉冲如下图所示:


脉冲如何被捕获

当电容从0充电到Vth时,就相当于一个上升沿脉冲。其实这个充放电过程很快,我们一般用的RC充放电电路是为了观察现象因此将时间常数做的很大,但是现实的话我们要快速识别必须将时间常数缩小到一定范围内才OK。


原理图层面的连接

STM_ADC其实只是这个引脚功能的其中一个,我们这里并不是用的引脚的ADC功能,以下为该引脚的复用:

我们这里使用的是PA1的TIM5_CH2功能,用于快速捕获TPAD的有效脉冲沿变化。


硬件配置的大致流程

image.png

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


电容触摸按键的基本原理(软件配置层面)

image.png

函数说明

TPAD_InitConfig()函数

void TPAD_InitConfig() // 读取默认电容充电时间  

{  

    u16 RecordChargeTime[10] = {0};  

    u8 i = 0, temp = 0;  

      

    uart_init(115200); // 初始化USART1  

    TIM_CAP_InitConfig(0xFFFF, 72-1); // 初始化TIM5_CH2的输入配置  

      

    for(; i<10; i++)  

    {  

        RecordChargeTime[i] = TPAD_GetValue(); // 连续计算10次默认充电时间  

    }  

for(i=0; i<9; i++)

{

if(RecordChargeTime[i] < RecordChargeTime[i+1]) // 冒泡排序(大->小)

{

temp = RecordChargeTime[i];

RecordChargeTime[i] = RecordChargeTime[i+1];

RecordChargeTime[i+1] = temp;

}

    for(i=1, temp=0; i<9; i++)  

    {  

        temp += RecordChargeTime[i]; // 去掉MAX与MIN求平均充电时间  

    }  

    TPAD_DefaultValue = temp/8; // 求出TPAD无动作时的默认充电时间  

    printf("Default:%dusrn",TPAD_DefaultValue); // 向串口打印未触摸时的电容充电时长  

}  

 


TPAD_Reset()函数

这里值得注意的是:PA1端口输入输出模式的变化以及TIM_ClearFlag()函数的使用。


PA1端口输入输出模式的变化:


我们会疑问“PA1端口为何要变化输入输出模式?”,在我们上述流程中提及过,我们要对电容充电所造成的上升沿重新计数就必须先将TPAD(PA1)端口置0进行充分的放电。那我们如何放电呢?

在图中,PA1与TPAD通过跳线帽连接在一起,然后为了读取TPAD中产生的上升沿,我们必须将PA1设置为TIM5_CH2的功能,此时PA1为浮空输入模式,但是我们读取完有效的脉冲沿之后,若继续读取必须先进行放电才可以。此时,我们配置PA1为推挽输出模式,放完电后再变成浮空输入模式。


TIM_ClearFlag()库函数的含义:


我们使用库函数的同学会有些疑问:TIM_ClearFlag()函数与 TIM_ClearITPendingBit()函数的区别在哪里?这里我来解说一下。


TIM_ClearFlag()函数是用于“清除标志位的”,比如:当检测到上升沿脉冲(有效的脉冲沿),相应的TIM_IT_CC2标志会出现,其实这些标志位和TIM_ClearITPendingBit ()函数中的中断标志位是一摸一样的,只不过由于未开启中断,事件一旦发生仅仅会使得标志位置1,不会触发中断。 其实如下的程序中我们就是想清除标志位,因此也可以使用TIM_ClearITPendingBit(TIM5, TIM_IT_CC2),这两个函数的功能就是去除相应的标志位,功能相同可以相互转换使用。


TIM_ClearFlag()与TIM_ClearITPendingBit()的函数体对比


TIM_ClearFlag()函数体


void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)  

{  

  /* Check the parameters */  

  assert_param(IS_TIM_ALL_PERIPH(TIMx));  

  assert_param(IS_TIM_IT(TIM_IT));  

  /* Clear the IT pending Bit */  

  TIMx->SR = (uint16_t)~TIM_IT;  // 操作SR寄存器

}  

 


TIM_ClearITPendingBit()的函数体


void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG)  

{    

  /* Check the parameters */  

  assert_param(IS_TIM_ALL_PERIPH(TIMx));  

  assert_param(IS_TIM_CLEAR_FLAG(TIM_FLAG));  

     

  /* Clear the flags */  

  TIMx->SR = (uint16_t)~TIM_FLAG;  // 操作SR寄存器

}  

 


我们从TIM_ClearFlag()与TIM_ClearITPendingBit()的函数体对比发现,完全一摸一样,可以互换使用。


//复位一次  

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);     //计数器的初始计数值置零

    TIM_ClearFlag(TIM5, TIM_IT_CC2);   // 清除TIM5_CH2的上升沿标志位

    //重新设置GPIOA.1为浮空输入  

    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;  //浮空输入  

    GPIO_Init(GPIOA, &GPIO_InitStructure);   

 


TPAD_GetValue()函数

u16 TPAD_GetValue() // 获取电容充电时间  

{  

    TPAD_Reset(); // 复位一次  

      

    while(TIM_GetFlagStatus(TIM5, TIM_IT_CC2) == RESET)//不断轮询等待捕获上升沿  

    {  

        if(TIM_GetCounter(TIM5)>MAX_ARR-500)  

        {  

            return TIM_GetCounter(TIM5);//超时了,直接返回CNT的值  

        }  

    };    

    return TIM_GetCapture2(TIM5);     

}  

 


这里有几行代码特别值得关注:


if(TIM_GetCounter(TIM5)>MAX_ARR-500)    

{    

    return TIM_GetCounter(TIM5);//超时了,直接返回CNT的值    

   


这里的提出了一个“检查错误”的概念,我们可以在检查是否有上升沿脉冲触发的同时检测“电容充电时间是否过长”,如果充电时间过长直接return值结束轮询(while(1)),此时我们认为有效脉冲沿持续时间为此时的计数器的值。


TPAD_GetMaxValue()函数

u16 TPAD_GetMaxValue(u8 SampleNumber) // 捕获4次取MAX  

{  

    u8 temp = TPAD_GetValue();  

      

    while(1)  

    {  

        temp = temp>TPAD_GetValue()?temp:TPAD_GetValue();  

        if(--SampleNumber) break;  

    }  

      

    return temp; // 求出TPAD无动作时的默认充电时间  

}  

 


TPAD_Scan()

u8 TPAD_Scan() // 扫描TPAD状态且不支持连续按

{  

    u16 TPAD_MaxValue = TPAD_GetMaxValue(3); // 连续采集3次  

    static u8 PressedFlag = 1;  

      

    uart_init(115200); // 初始化USART1  

      

    printf("Moment:%dusrn",TPAD_MaxValue); // 向串口打印当前充电时长  

      

    if((TPAD_MaxValue >= TPAD_Threshold + TPAD_DefaultValue)&&PressedFlag)  

    {  

        PressedFlag = 0;  

        return 1;  

    }  

    else if(TPAD_MaxValue < TPAD_Threshold + TPAD_DefaultValue)  

    {  

        PressedFlag = 1;  

        return 0;  

    }  

    else  

    {  

        return 0;  

    }  

}  

 


不支持连续按的精髓代码:


    if((TPAD_MaxValue >= TPAD_Threshold + TPAD_DefaultValue)&&PressedFlag)  

    {  

        PressedFlag = 0;  

        return 1;  

    }  

    else if(TPAD_MaxValue < TPAD_Threshold + TPAD_DefaultValue)  

    {  

        PressedFlag = 1;  

        return 0;  

    }  

    else  

    {  

        return 0;  

    }  

// 希望大家理解代码执行的逻辑,我在这里就不仔细讲解了。

 


我们要清楚的一点是:我们前面编写的所有函数都是为了编写TPAD_Scan()做准备,我们真正在main函数中使用的只有TPAD_Scan()函数。我们在编写函数时的好习惯是:注意哪些是辅助函数,哪些是要在main函数中使用得到的函数,函数的功能一定不要过于集中也不要过于分散。


程序示例

Main.c

#include "tpad.h"  

#include "led.h"  

#include "timer.h"  

#include "stm32f10x.h"  

#include "delay.h"  

#include "usart.h"  

  

int main()  

{  

    extern u16 TPAD_DefaultValue; // TPAD的默认充电时间  

    u8 TPAD_Status = 0, temp = 0;  

      

    delay_init(); // systick时钟初始化  

    LED_InitConfig(); // 初始化LED1&LED0  

    TPAD_InitConfig(); // 计算TPAD_DefaultValue  

    uart_init(115200); // 初始化USART1  

      

    while(1)  

    {  

        TPAD_Status = TPAD_Scan(); // 实时捕获TPAD的动作  

          

        if(TPAD_Status == 1)  

        {  

            LED1 = !LED1; // 触摸按键动作触发LED1状态翻转  

        }  

        temp++;  

        if(temp == 15)  

        {  

            LED0 = !LED0; // LED0作为状态灯使用  

        }  

  

    }  

}  

 


Led.c

#include "led.h"  

#include "stm32f10x.h"  

  

void LED_InitConfig()  

{  

    GPIO_InitTypeDef GPIO_InitStructure;  

      

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); // 使能LED1,LED0的时钟  

      

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;  

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  

[1] [2]
编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic567318.html

上一篇:STM32输入捕获实验示例详解
下一篇:OLED自定义显示图像实验(基础->进阶)

推荐阅读

电容触摸按键实验”实例解析
电容触摸按键实验电容触摸按键的基本原理(原理图层面)新电容的产生与作用我们学过模电的同学知道:我们的手其实相当于一块可以存储感应电荷的金属板,当我们的手靠近屏幕时,我们的手与屏幕下的金属板Cx构成了一个平行电容板,这个电容与Cs杂散电容相并联,“并联电容C=C1+C2”。充放电性能的变化我们看见“VCC是一定的;电容C越大代表一定电压下,存储的电荷数量越多(Q=CU),反之,充电到U所花费的时间也更多;电阻R的值一定代表着对电荷的阻碍作用是固定的”。充电到V=Vth,花费时间TA明显小于TB;我们真实情况下的矩形脉冲如下图所示:脉冲如何被捕获当电容从0充电到Vth时,就相当于一个上升沿脉冲。其实这个充放电过程很快,我们一般用的RC充
发表于 2022-03-28
“<font color='red'>电容</font><font color='red'>触摸按键</font>实验”实例解析
STM32电容触摸按键原理
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
发表于 2021-12-01
STM32<font color='red'>电容</font><font color='red'>触摸按键</font>原理
基于STM32的电容触摸按键的原理解析
原理:R:外接电容充放电电阻。Cs:TPAD和PCB间的杂散电容。Cx:手指按下时,手指和TPAD之间的电容。开关:电容放电开关,由STM32IO口代替。没有按下的时候,充电时间为T1(default)。按下TPAD,电容变大,所以充电时间为T2。我们可以通过检测充放电时间,来判断是否按下。如果T2-T1大于某个值,就可以判断有按键按下。检测电容触摸按键过程:①TPAD引脚设置为推挽输出,输出0,实现电容放电到0。②TPAD引脚设置为浮空输入(IO复位后的状态),电容开始充电。③同时开启TPAD引脚的输入捕获开始捕获。④等待充电完成(充电到底Vx,检测到上升沿)。⑤计算充电时间。
发表于 2021-04-23
基于STM32的<font color='red'>电容</font><font color='red'>触摸按键</font>的原理解析
电磁炉应用中的电容触摸按键解决方案
  1 引言  相较于机械式按键和电阻式触摸按键,电容式触摸按键不仅耐用,造价低廉,机构简单易于安装,防水防污,而且还能提供如滚轮、滑动条的功能。但是电容式触摸按键也存在很多的问题,因为没有机械构造,所有的检测都是电量的微小变化,所以对各种干扰敏感得多。ST针对家电应用特别是电磁炉应用,推出了一个基于STM8系列8位通用微控制器平台的电容式触摸感应方案,无需增加专用触摸芯片,仅用简单的外围电路即可实现电容式触摸感应功能,方便客户二次开发。  2 方案介绍  ST的电容式触摸按键方案通过一个电阻和感应电极的电容CX构成的阻容网络的充电/放电时间来检测人体触摸所带来的电容变化。如图1所示,当人手按下时相当于感应电极上并联了一个电容CT,
发表于 2020-08-12
电磁炉应用中的<font color='red'>电容</font>式<font color='red'>触摸按键</font>解决方案
解密中科蓝讯 电容触摸按键读取电路
深圳市中科蓝讯科技有限公司创立于2016年,是一家专注于智能应用处理器SoC、高性能模拟器件和无线互联芯片的设计厂商。同时还为软件开发提供一站式的应用解决方案。该公司的产品和解决方案主要应用于:高性能耳机、音箱、AI智能、万物互联等领域。其部分品牌服务的客户有:Newmine纽曼、QCY、Toshiba、Sony、Lenovo、KitSound、iHip等。公司成立至今,已有多颗芯片量产,并获得优异的市场成绩。而最新曝光的一项专利显示,中科蓝讯发明了一种电容式触摸按键读取电路以及方法。现有电容式触摸按键的读取电路一般分为两种,一种是基于振荡器型的结构,另一种是基于电荷分享型的充放电结构。基于振荡器型的触摸按键读取电路主要通过振荡器产
发表于 2020-08-04
解密中科蓝讯 <font color='red'>电容</font>式<font color='red'>触摸按键</font>读取电路
瑞萨电子主流MCU RX系列产品亮点:电容触摸按键和更高安全
日前,在瑞萨电子天津产品研讨会期间,瑞萨电子中国通用解决方案中心市场部霍笋介绍了瑞萨电子RX系列产品。霍笋表示,瑞萨电子经历了公司整合之后,保留了三条自有内核的微控制器产品线,分别为RX系列微控制器、RL78系列微控制器以及RH850系列车用微控制器。其中RX系列微控制器的中高端产品采用40nm制程,内置FPU、DSC等功能模块,具有先进的性能;而低端系列则采用130nm工艺,具有极佳的低功耗特性。瑞萨处理器演进历史RX系列家族产品组合高性价比的RX100/200系列目前,RX系列产品依据主频和外设共分四大系列,分别为RX100、RX200、RX600和RX700。其中RX100/200系列是中低端MCU,主要应用在工业/消费/办公
发表于 2018-12-28
瑞萨电子主流MCU RX系列产品亮点:<font color='red'>电容</font><font color='red'>触摸按键</font>和更高安全

推荐帖子

WLAN中的MIMO OFDM技术
WLAN中的MIMOOFDM技术文章介绍了多输入多输出(MIMO)与正交频分复用(OFDM)技术以及他们各自的特点,给出了在无线局域网中应用的MIMOOFDM技术的实现方案,探讨了实现MIMOOFDM技术的关键,并展望了MIMOOFDM技术的发展前景。关键词:正交频分复用/多输入多输出/无线局域网/IEEE802.11n协议WLAN中的MIMOOFDM技术
mdreamj 单片机
读好书《运算放大器参数解析与LTspice应用仿真》读书笔记
本帖最后由ksniper于2021-6-2116:15编辑 很高兴能读到郑荟民老师的《运算放大器参数解析与LTspice应用仿真》一书的实体版本。同是副高职称,却一直未能有所建树,实在是惭愧不已。关于本书的其他部分已经有不少坛友的帖子明珠在前,就不赘述了。只好结合工作需要用到的高速运放做点读书笔记。高速运放顾名思义最紧要的参数首先是实际工作带宽,带宽达不到的话一切免谈。我们都知道增益带宽积等于设计增益x工作带宽,但是——&ldqu
ksniper 模拟电子
用于停车场照明的微波感应模块
GH-719微波感应位移模块是利用多普勒雷达(DopplerRadar)原理设计的微波移动物体探测器,微波频率10.525GH,直接加直流6-20V电源即可工作。 GH-719微波感应位移模块信号处理采用单片机程序分析,可靠性高。电路板上有16级灵敏度调整,感应距离在0.3-10米内可调。4种触发模式选择,信号输出时间:2秒,3秒,10秒,30秒,加光敏电阻可抑制白天触发,主要应用于自动门控制开关、工业自动化控制,室内外安全防范系统、ATM自动提款机的自动录像控制系统、野外安全警示等场所。
珊珊 汽车电子
自制2440底板插上核心板之后无法启动
买的TQ2440的开发板把linux系统都移植好了,自己做了一个底板,插上核心板后通电,系统无法启动,串口无数据输出,底板包括基本的3.3v电路、JTAG电路、Flash启动选择开关、复位电路都有。有没有哪位有这方面的经验可以指导下,不胜感激 自制2440底板插上核心板之后无法启动
tyjlwj PCB设计
WINCE触摸屏校准问题
我在WINCE5.0下使用电容屏,由于使用的是RAM注册表,无法保存触摸屏校准后的参数,于是先通过校准并读取校准后的[HKEY_LOCAL_MACHINE/HARDWARE/DEVICEMAP/TOUCH]下的CalibrationData键值,将该值写入内核,但是问题是:校准后不重启,点击实际屏幕响应位置与实际位置对应;但是将CalibrationData写入内核后重启,屏幕上的响应位置比实际点击位置向左偏移了,不知道哪位大侠知道是什么问题!有没有可能是触摸屏起点与屏幕起点不重叠导致的?然后
h6003113 嵌入式系统
电子板在波峰焊接时出现的问题与解决办法
无铅波峰焊机Q:无铅波峰焊机升温要几小时?A:这个看你的锡炉功率了,一般来讲快的3个小时。慢的要4-5个小时。 Q:与浸焊机相比,波峰焊机具有哪些优点A:交流点焊机和直流点焊机的比较优缺点1)直流焊机好;焊接时溅弧小焊接质量可靠;2)比较小的那种,俗称‘书包焊机’,功率一般只有5-6个千瓦以下,便于携带。3)体积比较小的电焊机,要直流的可能比较少有,因为直流的要考虑整流装置,比较占空间,又要考虑散热。 Q:一般工厂用的回流焊机、双波峰焊机、浸焊机和切角机的功率是多少??A:这些设
xylianguang 工控电子
小广播
实战 培训 开发板 精华推荐

何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2022 EEWORLD.com.cn, Inc. All rights reserved