stm32F1电容触摸按键详解

1、RC充放电电路原理:

(1)如上图所示,当开关关闭时,电容经过电阻R充电,最开始的瞬间电流为最大值V1/R,随后随着Vt越来越大,电流变小,电容充电速度变慢,当V1=Vt时,电流为0
(2)RC电路充放电公式:Vt = V0+(V1-V0)* [1-exp(-t/RC)]
V0 为电容上的初始电压值;
V1 为电容最终可充到或放到的电压值;
Vt 为t时刻电容上的电压值。
R 为充电电阻
C 为电容容值
e 为自然底数
t 为充电时间
如果V0为0,也就是从0V开始充电。那么公式简化为:Vt= V1* [1-exp(-t/RC)]
结论:同样的条件下,电容值C跟时间值t成正比关系,电容越大,充电到达某个临界值的时间越长。
2、电容触摸按键原理:


R:外接电容充放电电阻。
Cs:TPAD和PCB间的杂散电容。
Cx:手指按下时,手指和TPAD之间的电容。
开关:电容放电开关,由STM32 IO口代替。
电容触摸按键原理简而言之就是,当手指按下触摸按键的时候,相当于充电电容增大,那么所需的充电时间就变长,根据电容充电时间的差异来判断是否按下了触摸按键
上图的开关作用是,当开关闭合时,电容放电,当开关断开时,电容充电。用IO口代替的话是需要先将IO口配置成推挽输出,再将IO口置低电平0,来实现电容放电,再将IO口配置成浮空输入,相当于断开开关,此时电容开始充电
3、程序实现:

触摸按键程序与原理#define TPAD_ARR_MAX_VAL    0XFFFF  //最大的ARR值
vu16 tpad_default_val=0;//空载的时候(没有手按下),计数器需要的时间
第一步:初始化,也就是先放电后充电
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);        //归0TIM_ClearITPendingBit(TIM5, TIM_IT_CC2|TIM_IT_Update); //清除中断标志//设置GPIOA.1为浮空输入GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;  //浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);
}
第二步:输入捕获,上升沿捕获
//定时器2通道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);   //使能TIM5时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);     //使能PA端口时钟//设置GPIOA.1为浮空输入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;                //PA1 端口配置GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //速度50MHzGPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;    //浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);    //设置为浮空输入//初始化TIM5  TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值   TIM_TimeBaseStructure.TIM_Prescaler =psc;     //预分频器     TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位//初始化通道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);//初始化I5 IC2TIM_Cmd(TIM5,ENABLE );   //使能定时器5
}
第三步,捕获时间,也就是从0开始到达上升沿的时间
u16 TPAD_Get_Val(void)
{                  TPAD_Reset();while(TIM_GetFlagStatus(TIM5, TIM_IT_CC2) == RESET)//等待捕获上升沿{if(TIM_GetCounter(TIM5)>TPAD_ARR_MAX_VAL-500)return TIM_GetCounter(TIM5);//超时了,直接返回CNT的值};    return TIM_GetCapture2(TIM5);
}
第四步,获取时间最大值
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;
}
第五步,获取未按下时的0到上升沿的时间,排序取中间平均
u8 TPAD_Init(u8 psc)
{u16 buf[10];u16 temp;u8 j,i;TIM5_CH2_Cap_Init(TPAD_ARR_MAX_VAL,psc-1);//以1Mhz的频率计数 for(i=0;i<10;i++)//连续读取10次{                buf[i]=TPAD_Get_Val();delay_ms(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;}}}temp=0;for(i=2;i<8;i++)temp+=buf[i];//取中间的6个数据进行平均tpad_default_val=temp/6;if(tpad_default_val>TPAD_ARR_MAX_VAL/2)return 1;//初始化遇到超过TPAD_ARR_MAX_VAL/2的数值,不正常!return 0;
}
第六步,扫描并判断是否触摸按键
//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,可以开始检测;>0,还不能开始检测     u8 res=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))//大于tpad_default_val+TPAD_GATE_VAL,有效{                           if(keyen==0)res=1;      //keyen==0,有效 //printf("r:%d\r\n",rval);                                           keyen=3;                //至少要再过3次之后才能按键有效   } if(keyen)keyen--;                                                                            return res;
}
第七步,主函数int main(void){   u8 t=0;    delay_init();            //延时函数初始化    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置NVIC中断分组2:2位抢占优先级,2位响应优先级LED_Init();                 //LED端口初始化TPAD_Init(6);            //初始化触摸按键while(1){                                                   if(TPAD_Scan(0))   //成功捕获到了一次上升沿(此函数执行时间至少15ms){LED1=!LED1;       //LED1取反}t++;if(t==15)       {t=0;LED0=!LED0;     //LED0取反,提示程序正在运行}delay_ms(10);}}

嵌入式单片机基础篇(十一)之电容触摸按键相关推荐

  1. 嵌入式单片机基础篇(一)之stm32F1GPIO详解

    嵌入式单片机基础篇(一)之stm32F1GPIO详解 stm32F1GPIO详解 下面以stm32f103zet6以及51单片机为例,讲解单片机最基本部分IO口 第一部分:stm32 STM32 的 ...

  2. 嵌入式单片机基础篇(八)之两只看门狗

    嵌入式单片机基础篇(八)之两只看门狗 独立看门狗与窗口看门狗 第一部分:stm32 .STM32 内部自带了 2 个看门狗:独立看门狗(IWDG)和窗口看门狗(WWDG). (一)独立看门狗 STM3 ...

  3. 嵌入式单片机基础篇(二十七)之Stm32F103单片机给蓝牙模块发送AT指令程序

    Stm32F103单片机给蓝牙模块发送AT指令程序 #include "stm32f10x.h" #include "string.h" #include &q ...

  4. 嵌入式单片机基础篇(三十九)之CAN通讯以及STM32F1单片机程序

    CAN通讯以及STM32F1单片机程序 1.CAN通讯基本概念: (1)定义: CAN是Controller Area Network 的缩写(以下称为CAN),是ISO国际标准化的串行通信协议.由德 ...

  5. 嵌入式单片机基础篇(十三)之 STM32 内部温度传感器

    STM32 内部温度传感器 1. STM32 内部温度传感器简介 STM32 有一个内部的温度传感器,可以用来测量 CPU 及周围的温度(TA).该温度传感器在内部和 ADCx_IN16 输入通道相连 ...

  6. 嵌入式单片机基础篇(十)之Systick定时器原理及应用

    Systick定时器原理及应用 1.什么是Systick定时器? 回答: (1)ystick定时器,是一个简单的定时器,对于CM3,CM4内核芯片,都有Systick定时器. (2)Systick定时 ...

  7. 嵌入式单片机基础篇(三十六)之STM32F1SPI标准接口程序以及模拟SPI标准接口程序讲解

    STM32F1SPI标准接口程序以及模拟SPI标准接口程序讲解 一.SPI标准接口初始化: 1.SPI 内部结构简明图 2.上一篇文章提到,spi标准协议包含4条信号线.时钟相位.时钟极性.数据单字节 ...

  8. 嵌入式单片机基础篇(二十)之FSMC

    FSMC详解 1.FSMC简介: FSMC,即灵活的静态存储控制器,能够与同步或异步存储器和 16 位 PC 存储器卡连接,STM32 的 FSMC 接口支持包括 SRAM.NAND FLASH.NO ...

  9. 51单片机定时器中断怎么用-------51单片机基础篇

    首先,什么时定时器,简单来说可以比喻为一个闹钟,当你把他打开以后,他就会每秒动一下,+1,+1,+1,+1,如果你设置了某一个时间点闹钟会向以后,那么当闹钟的时间点+1,+1,+1,+到了你设置的时间 ...

  10. 嵌入式单片机高级篇(二)Stm32F103电阻触摸屏

    Stm32F103电阻触摸屏 1.原理: lcd屏与触摸屏中间有支撑点将两层导电涂料隔开,当某点按下时,使得两层涂料接触,平常绝缘的两层导电层在触摸点位置就有了一个接触,控制器侦测到这个接通后,其中一 ...

最新文章

  1. python使用configparser读取ini格式的配置文件
  2. 恢复VMware vSphere已孤立的虚拟机
  3. Win10任务计划+PowerShell实现Git自动推送
  4. linux top 命令可视化_Linux 使用 top 命令查看系统的运行情况
  5. th:text为null报错_为vue3.0的学习TS解读高级类型
  6. Helpful C Tools:source、executables、debugging and performance tuning
  7. Java回顾之JDBC
  8. All Reduce算法汇总
  9. 连接数据线截图/截视频
  10. esp32 -Task watchdog got triggered的处理
  11. 计算机的任务管理器不显示不出来,开机后桌面不显示图标,也调不出任务
  12. dubbokeeper-moniter部署指南
  13. (Modern Family S01E02) Part 6  JayGloria  Jay给Manny修风扇
  14. 机器人操作系统ROS 1.0 和 2.0 发展规划2018-2025(Open Robotics)译
  15. Suse linux 命令行
  16. 【毕业设计/课程设计】基于opencv的高精度人脸识别考勤系统设计与实现
  17. 贪心算法解决商场买赠问题(最简单,通俗易懂,附C++代码
  18. 今天向大家推荐一款国产良心工具包 -- Hutool,让你的java变得更甜
  19. qt获取本机IP地址、计算机名、网络连接名、MAC地址、子网掩码、广播地址
  20. transformer与视觉

热门文章

  1. 深扒Mobileye—与特斯拉分手,被英特尔收购,现在又成了蔚来的救星?
  2. WinDriver高级编程
  3. 电力拖动自动控制系统_一、自动化专业电气工程及其自动化
  4. 磁共振成像(Magnetic Resonance Imaging,MRI)学习资料汇总,包括:在线学习视频、网站、教材
  5. 我们系有个计算机中心英语,吉大自考计算机专业英语(一)
  6. 六,华为交换路由做NAT五种方法
  7. windows server2012 R2 离线中文语言包下载与安装
  8. chrome浏览器上传文件fakepath问题
  9. 由于应用程序配置不正确,应用程序未能启动 VS2008 Release /MD编译
  10. 如何查计算机的网络速度,电脑怎么查网速?教你精准测速的方法