STM32电容触摸按键原理

发布者:RadiantSoul最新更新时间:2021-12-01 来源: eefocus关键字:STM32 手机看文章 扫描二维码
随时随地手机看文章

RC充放电电路原理

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 = (V1-Vc) / R

    所以随着充电时间的增加,电容C的电压增加,电阻R两端压差减小,电流降低,电子积累速度减慢,充电效率降低


RC电路充放电公式

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


V0:电容的初始电压值

V1:电容最终可以冲/放到的电压值

Vt:电容t时刻的电压值


若电容C从0V开始充电,那么V0 = 0,则公式简化为:

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


公式中V1, R均为常数,要达到相同的充电电压Vt,那么充电时间t和电容值C,成正比

RC电路电容与电阻关系

结论:

    同样条件下,电容C和充电时间t成正比

    达到相同的电压,电容越大,所需要的充电时间越长


电容触摸按键原理

电容触摸按键原理

R:外接电容充放电电阻

Cs:TPAD与PCB之间存在杂散电容

Cx:当手指按下时,手指和TPAD之间的电容


图A:

    手指未按下时的电路,TPAD与PCB之间存在电容Cs


图B:

    当手指按下时,手指与TPAD之间存在电容Cx,此时相当于Cs与Cx并联,电容总值=Cs+Cx


根据上边”RC充放电电路原理”可知:


    当R一定时,达到相同的电压,电容越大,需要的充电时间越长

    所以,我们假设未触摸时充电时间为T1,触摸时充电时间为T2(T2 > T1)


检测电容触摸按键过程

1,电容放电到0

     TPAD引脚设置为推挽输出,放电

     放电到0V后,将计数器值设置为0,充电计时使用


2,电容充电

     TPAD引脚设置为浮空输入(IO复位后的状态)


3,充电完成(Vx)进入输入捕获

     TPAD引脚开启输入捕获

     因为放完电的时候C的电压为 0,所以设置上升沿捕获


4,是否按下-计算充电时间,对比是否按下

     当未按下时,记录充电完成的时间T1(计数器频路*数值)

     检测当次充电时间T2,与T1对比,如果超过预设时间T3,说明按键按下


电容触摸按键的硬件连接

电容触摸按键的硬件连接

PA1引脚说明:

PA1引脚说明

如图:

     电容触摸按键TPAD(黄色部分),TPAD引脚与PA1项链

     使用TIM5_CH2进行输入捕获


代码实现

tpad.h声明功能函数


#ifndef __TPAD_H

#define __TPAD_H

#include "sys.h"


// 未按下电容触摸按键时的充电时间

extern vu16 tpad_default_val;     


// 复位TPAD:

// 设置推挽输出放电到0;再设置浮空输入充电,计数器CNT=0

void  TPAD_Reset(void);


// 获取一次捕获事件得到充电时间:

// 复位TPAD,等待捕获上升沿,得到计数器值,计算充电时间

u16   TPAD_Get_Val(void);


// n次调用TPAD_Get_Val取最大值

u16   TPAD_Get_MaxVal(u8 n);


// 初始化TPAD:

// 系统启动后初始化输入捕获,10次调用TPAD_Get_Val()

// 取中间n次平均值,作为未按下时的充电时间tpad_default_val

u8     TPAD_Init(u8 psc);


// 扫描TPAD:

// 调用TPAD_Get_MaxVal获取多次充电中最大充电时间

// 与tpad_default_val对比,若超过tpad_default_val+TPAD_GATE_VAL则为触摸

u8     TPAD_Scan(u8 mode);


// 输入捕获通道初始化

void  TIM5_CH2_Cap_Init(u16 arr,u16 psc);


#endif


tpad.c-tpad.h声明功能函数的实现


#include "tpad.h"

#include "delay.h"

#include "usart.h"


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


    // 初始化定时器5通道2输入捕获

    TIM5_CH2_Cap_Init(TPAD_ARR_MAX_VAL, psc-1);//以1Mhz的频率计


    // 连续读取10次TPAD_Get_Val(),间隔10ms

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

    {

        buf[i]=TPAD_Get_Val();// 10次定时器值装入数组

        delay_ms(10);

    }


    // 将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;

            }

        }

    }


    // 取第2-8次充电时间取平均值,串口打印输出

    temp=0;

    for(i=2;i<8;i++)temp+=buf[i];

    tpad_default_val=temp/6;

    printf("tpad_default_val:%drn",tpad_default_val);


    //  初始化遇到超过TPAD_ARR_MAX_VAL/2的数值,不正常

    if(tpad_default_val>TPAD_ARR_MAX_VAL/2) return 1;


    return 0;

}


// TPAD复位

void TPAD_Reset(void)

{

    GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟


    // 设置PA1为推挽输出

    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);                    // PA1输出0,放电


    delay_ms(5);     //延迟5ms 等待放电结束,电容电压此时为0V


    TIM_SetCounter(TIM5, 0);        //定时器5计数器设置为0

    TIM_ClearITPendingBit(TIM5, TIM_IT_CC2|TIM_IT_Update); //清除中断标志


    //设置PA1为浮空输入-开始充电

    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;

    GPIO_Init(GPIOA, &GPIO_InitStructure);


}


// 获得定时器捕获值-上升沿捕获

u16 TPAD_Get_Val(void)

{

    // TPAD复位:PA1推挽输出放电到0,再设置PA1浮空输入充电,定时器=1,清除中断标志

    TPAD_Reset();


    // 等待捕获上升沿

    while(TIM_GetFlagStatus(TIM5, TIM_IT_CC2) == RESET)

    {

        // 超时,返回CNT值

        if(TIM_GetCounter(TIM5)>TPAD_ARR_MAX_VAL-500)

            return TIM_GetCounter(TIM5);

    };


    return TIM_GetCapture2(TIM5); // 返回通道2的捕获值

}


// 连续n次读取TPAD_Get_Val,返回最大值

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:可以开始检验 1: 还不能检验

    u8 res=0;             // 返回是否按下 1:按下 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))

    {

        if(keyen==0)res=1;      // keyen==0,有效,返回1

        //printf("r:%drn",rval);

        keyen=3;                // 至少再扫描3次后按键才能生效

    }

    if(keyen)keyen--;


    return res;

}


// 定时器5通道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);    // 使能定时器5时钟

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   // 使能GPIOA时钟 


    // 初始化GPIOA-浮空输入

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;               // PA1

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       // 50Mhz

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

    GPIO_Init(GPIOA, &GPIO_InitStructure);


    //定时器5初始化

    TIM_TimeBaseStructure.TIM_Period = arr;                 // 重装载值

    TIM_TimeBaseStructure.TIM_Prescaler =psc;               // 预分频器

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 设置时钟分割:TDTS = Tck_tim

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;// 向上计数

    TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);


    //初始化通道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);// 初始化定时器5 IC2


    TIM_Cmd(TIM5, ENABLE ); // 使能定时器5

}


main.c 当捕获到电容触摸按键按下(捕获上升沿),LED1反转


#include "led.h"

#include "delay.h"

#include "key.h"

#include "sys.h"

#include "usart.h"

#include "tpad.h"


 int main(void)

 {

    u8 t=0;                      // 计数器

    delay_init();                // 延时函数初始化

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 中断优先级分组配置

    uart_init(115200);           // 串口初始化 115200

    LED_Init();                  // LED初始化

    TPAD_Init(6);                // TPAD初始化


    while(1)

    {

        if(TPAD_Scan(0))        // 捕获到上升沿(此函数执行至少15ms)

        {

            LED1=!LED1;          // LED1取反

        }


        t++;

        if(t==15)

        {

            t=0;

            LED0=!LED0;          // LED0闪烁,标志程序正在运行

[1] [2]
关键字:STM32 引用地址:STM32电容触摸按键原理

上一篇:通用定时器-输入捕获实验
下一篇:STM32定时器中断实验

推荐阅读最新更新时间:2024-11-19 23:49

stm32的3种下载程序方式
个人记录: 了解这些,自己多多总结,也算是对开发板硬件接口的了解。 没总结完,     【1】ISP下载   这里类似51. boot1拨到0, 就行了 下载需要来回拨动拨码开关   【2】J-LINK 可下载 可仿真 (分为SW和JTAG模式) JTAG 或 SW 方式,在KEI的编程选项里面设定,选择好仿真器后,在相关的SETTINGS设置项里面会有 JTAG和SWD方式的选择。 只需要修改KEI环境配置,和硬件设置,这个SWD只需要5个,一个电源,一个地 和仅需要三根调试线SWDO(可选的跟踪),SWDIO(data I/O),SWDCLK(时钟针) 如果用jt
[单片机]
stm32HAL库之can操作
基于STM32CubeMx的CAN配置信息 volatile 1.系统时钟APB1=36MHZ 2.CAN计算通信率计算公式,参考数据手册, CAN bit timing register (CAN_BTR) 寄存器 NominalBitTime计算公式: NominalBitTime =1 t × q + tBS1 + tBS2 3.STM32CubeMx设置的Prescaler为8- 对应BRP=7,TimeSeg1=6- 对应TS1=5,TimeSeg2=2- 对应TB2=2,STM32F103ZE对应APB1设置为36M,即Time for one Bit的时间为(1 + TimeSeg1+ TimeSeg2)
[单片机]
stm32HAL库之can操作
stm32学习之七
USART串口学习: 本篇主要是stm32板子与PC机器的连接,由于是初学,花了很长的时间思考的实验,才成功的配置成功串口的通信,煞费脑筋,所以自成一篇博客。 其实在买板子的时候,应该想到有能实现通信功能的连接线,但是主要是笔记本电脑,为了稳妥起见,不敢夸张的实验。 步骤: 1、有一个USB转(串口线)com(不专业的说法,但是清晰的可以看到板子上面有com1,就这样称呼)连接线,然后就有一根连接开发板的com线,这样可以实现PC机器和stm32的连接。如果电脑上显示驱动没有安装成功,那么这个时候就要想到驱动的安装问题了。可以网上找,或者......你知道的。 2、打开设备管理器,可以看到电脑上
[单片机]
<font color='red'>stm32</font>学习之七
基于STM32、FreeRTOS实现硬件看门狗+软件看门狗监测多任务的方法
我们都知道硬件看门狗的目的:是用来监测系统,防止系统死机,并在死机的情况下使系统复位重启。 在RTOS操作系统中,如果任务(线程)较多,出现高优先级任务长时间占用CPU资源,低优先级任务长时间得不到执行这种想象,那么我们的系统就是具有Bug的系统。 如上描述,假如我们的线程没有死机,只是长时间得不到执行。在这种异常情况下,我们又不希望系统复位,只希望执行特定代码,那我们该如何来避免这种问题呢? Ⅰ 关于看门狗 硬件看门狗:利用一个定时器计数电路,其定时输出连接到电路的复位端,程序在一定时间范围内对定时“喂狗”。 因此程序正常工作时,定时器总不能溢出,也就不能产生复位信号。如果程序出现故障,不在定时周期内
[单片机]
基于<font color='red'>STM32</font>、FreeRTOS实现硬件看门狗+软件看门狗监测多任务的方法
STM32 PWM问题
本文不提供完整程序,仅点出要点 1:时钟配置。因为PWM输出属于复用功能,所以时钟使能必须使能RCC_APB2Periph_AFIO ; 2:IO口使能。因为PWM属于复用功能,所以IO输出设置要配置成GPIO_Mode_AF_PP;而不能配置成普通输出IO的GPIO_Mode_OUT_PP模式; 3:PWM初始化代码如下,本程序只用通道3输出,所以pwm输出只配置了通道3,TIM_OC3Init(TIM3, &TIM_OCInitStructure);需要多通道输出PWM则需要配置多个PWM输出通道,通过改变TIM_Pulse 的值可以改变pwm的占空比(可以通过直接操作寄存器TIM3- CCR3=2400来实现)。 /* Ti
[单片机]
stm32与HC-SR04超声波传感器测距
首先,先来看一下这个模块的基本功能和原理。 HC-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能,测距精度可达高到3mm;模块包括超声波发射器、接收器与控制电路。像智能小车的测距以及转向,或是一些项目中,常常会用到。智能小车测距可以及时发现前方的障碍物,使智能小车可以及时转向,避开障碍物。 注意是5v输入,但是我用stm32 的3.3v输入也是没有问题的。 二.工作原理 1.给超声波模块接入电源和地。 2.给脉冲触发引脚(trig)输入一个长为20us的高电平方波 3.输入方波后,模块会自动发射8个40KHz的声波,与此同时回波引脚(echo)端的电平会由0变为1;(此时应该启动
[单片机]
STM32学习记录之GPIO篇
本篇学习目的: 一、学会对STM32芯片GPIO的基本操作 二、对GPIO的相关函数进行二次封装,以便于后期开发 开发板GPIO原理图如下 由图可知LED接在GPIOC的PC0-PC7 STM的GPIO有如下8中模式 GPIO相关库函数 GPIO模式配置函数:GPIO_Init(GPIO_TypeDef *GPIOx,GPIO_InitTypeDef *GPIO_InitStruct); 第一个参数用来指定GPIO口,取值范围GPIOA—GPIOG 第二个参数用来初始化参数结构体指针,参数结构体定义如下: typedef struct{ uint16_t GPIO_Pin; //选择要设置的Pin口 GPIOSpe
[单片机]
使用stm32的HAL库完成pwm输入模式测量频率和占空比的详细教程
STM32定时器具有PWM的输入捕获模式。 PWM输入捕获是定时器输入捕获的一个特例,单通道的输入捕获只能获取波形的频率,但是PWM输入捕获可以获取到频率和占空比,对应的高低电平宽度也就能获取到。 它的时序如下图所示: 使用cubemx配置方法: 就是使用TIM2的ch1和ch2来捕获一个pwm信号。 这里只测试了update event,我测试55khz使用该分频与计数值可以正常工作,不过第一次捕获的数据是随机数,需要丢弃。另外这里分频值我改成89的时候不太正常,捕获到的占空比出现错误,更改为0之后正常。这里需要注意的是F429的TIM2是在APB1下,时钟频率90Mhz。而TIM1/TIM8则是在AP
[单片机]
使用<font color='red'>stm32</font>的HAL库完成pwm输入模式测量频率和占空比的详细教程
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved