stm32学习笔记——电容触摸按键的实现
目录
一、电容触摸按键原理
二、正点原子战舰开发板对应的硬件原理图
三、代码实现
1.定时器的初始化配置函数(此处使用通用定时器TIM5的通道2,对应的端口是)
2.电容触摸按键初始化
3、捕获一次充电时间的函数
4、按键检测函数
总结
一、电容触摸按键原理
触摸电容按键工作原理:当手按下时,形成附加电容,按下和松开两种状态的区别是电路中的电容值不同。而电容值的不同可以体现在充电时间上。所以可以利用输入捕获充电时间实现按键检测。
二、正点原子战舰开发板对应的硬件原理图
1、电容触摸按键电路是片外电路,要实现电容充放电状态切换,可以将其连接到芯片端口。通过端口状态从开漏输出或推挽输出,到浮空输入的状态转换,实现从放电到充电的状态转换。
2、补充说明:
①关于为什么开漏和推挽输出可以实现电容的放电?
对端口设置为推挽输出或者开漏输出,并将其置0,可以实现电容的放电(本质原因:无论是开漏模式还是推挽模式,置0都是将电容接到地,可以实现放电)
②关于为什么充电时端口要设置为浮空输入?
将对应的端口置为浮空输入(浮空即没有芯片内部电流影响外电路电容充电),当充电到一定值,电容上电压达到一定值,使得施密特触发器产生一定输出,也即可以检测到上升沿,可以触发输入捕获时间。
3、此处使用通用定时器TIM5的通道2,对应的端口是PA.1,将正点原子战舰开发板的P7.1和P7.2用跳线帽连接。也即实现了端口PA.1与外电路触摸电容相连,进而可以控制外电路电容充放电,并实现输入捕获充电时间。
三、代码实现
1.定时器的初始化配置函数(此处使用通用定时器TIM5的通道2,对应的端口是)
代码如下:
void TIM5_IC2Init(uint16_t pre,uint16_t reload)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_ICInitTypeDef TIM_ICInitStruct;GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_ResetBits(GPIOA,GPIO_Pin_1);delay_ms(100);//放电TIM_TimeBaseInitStruct.TIM_Prescaler = pre;TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStruct.TIM_Period = reload;TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStruct);TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;TIM_ICInitStruct.TIM_ICFilter = 0x00;//不采用滤波器TIM_ICInit(TIM5,&TIM_ICInitStruct); TIM_Cmd(TIM5,ENABLE);}
2.电容触摸按键初始化
说明:利用该函数获得未按下时的充电时间,与后面按下时的充电时间作比较,进而可以判断是否按下。
代码如下:
uint16_t TPAD_Init_val;//全局变量用于存储
未按下时的充电时间void TPAD_Init(void) {uint16_t buf[10];uint8_t i;uint8_t j;uint16_t temp;for(i=1;i<=10;i++){buf[i-1]= get_val();delay_ms(10);}for(i=0;i<9;i++){for(j=0;j<9-i;j++){if(buf[j]<buf[j+1])//从大到小排序{temp = buf[j];buf[j] = buf[j+1];buf[j+1] = temp;}}}temp = 0;for(i=2;i<8;i++){temp += buf[i];}TPAD_Init_val = temp/6;}
补充说明:为了提高可靠性,捕获10次充电时间,并去掉两个最大和最小值,再取平均值。
3、捕获一次充电时间的函数
说明:要捕获一次充电时间要经过一下几个步骤:①放电②计数器清零、标志位清零③充电④根据标志位读取定时器输入捕获的充电时间,并返回
代码如下:
uint16_t get_val(void)
{uint16_t temp;GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_ResetBits(GPIOA,GPIO_Pin_1);delay_ms(5);//放电TIM_ClearITPendingBit(TIM5,TIM_IT_CC2);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA,&GPIO_InitStructure);//充电TIM_SetCounter(TIM5,0);//计数器清零while( TIM_GetFlagStatus(TIM5,TIM_IT_CC2)!=SET){if(TIM_GetCounter(TIM5)>max_count-500)//认为已经超时了{return TIM_GetCounter(TIM5);}}temp = TIM_GetCapture2(TIM5);return temp;}
补充说明:
1、注意标志位的判断的库函数一定不要使用错误!!!要用TIM_GetFlagStatus而不能用
TIM_GetITStatus。二者的区别是,库函数FlagStatus单纯判断标志位是否置位,即当事件发生但是没有使能对应事件的中断时,标志位仍然置位,但没有发生中断。而库函数ITStatus,不仅判断了标志位还判断了使能位,只有当中断发生(事件发生+中断使能)才返回SET。
2、注意分清标志位和中断的概念区别
当某个模块(比如串口、定时器)含有状态寄存器则涉及标志位和中断之间的区别,进而有库函数FlagStatus和ITStatus的使用区别。
标志位置位,是指当某事件发生时,无论对应的中断是否使能都会使得相应的标志位置位。
而当对应的中断也使能时,可以产生中断,此时要进行中断优先级配置、初始化配置、编写中断服务函数。
而此实验中只使用了标志位,而没有使用中断,所以不用进行中断优先级配置、初始化配置、编写中断服务函数。
3、关于TIM_ClearITPendingBit(TIM5,TIM_IT_CC2);
此处虽然没有用到中断,且中断和标志位的概念不同。但是清除中断标志位和标志位都是对SR寄存器操作,故可以替代使用。
4、按键检测函数
说明:不断检测是否按下,本质是不断捕获充电时间,如果充电时间大于设置的门限值(实验确定),则认为按下。
代码如下:
uint8_t TPAD_Scan(void)
{//实现不支持连按的第一种思路(以松开的检测值作为松开标志)static uint8_t flag = 0;uint16_t temp = get_val_max(sampletime);if(temp < TPAD_Init_val+10 ){flag = 0;}if((temp>TPAD_Init_val+TPAD_gate_val)&&(!flag)){printf("get_val_max %d\r\n",temp);flag = 1;return 1;}else return 0;//实现不支持连按的第二种思路,以不满足按下条件作为松开标志//第二种思路的结果性能更稳定:可以通过改变标志变量的值改变检测按下与松开状态切换的时间间隔。//编写代码思路:从简入手,即先实现支持连按的,再加标志/*uint8_t res = 0;static uint8_t flag = 0;if(get_val_max(sampletime)>TPAD_Init_val+TPAD_gate_val)//TPAD_gate_val是宏定义的门限值(具体值通过实验确定){if(flag == 0){res = 1;}flag = 3;}if(flag){flag--;}return res;*/
}
补充说明:
1、实现按键检测思路(不支持连按)
2、一次检测涉及三次输入捕获,取最大值,提高可靠性
三次输入捕获获得最大值的代码如下:
uint16_t get_val_max(uint8_t n)
{uint16_t temp;uint16_t val_max;val_max = get_val();while(n-1){temp = get_val();printf("get_val is %d\r\n",temp);if(temp > val_max){val_max = temp;}n--;}return val_max;
}
3、如果连续三次检测不能满足按下条件则认为松开了,则改变标志变量,进而可以检测下一次按下
总结
以上就是今天要讲的内容,本文简单介绍了正点原子开发板触摸按键的使用以及代码编写过程中的注意事项。
·
希望大家多多支持,一键三连呀~~~
stm32学习笔记——电容触摸按键的实现相关推荐
- STM32学习笔记(八)丨ADC模数转换器(ADC单、双通道转换)
本篇文章包含的内容 一.ADC 模数转换器 1.1 ADC简介 1.2 逐次逼近型ADC工作原理 1.3 STM32中的ADC基本结构 1.4 STM32中ADC的输入通道 1.5 STM32中的AD ...
- STM32学习笔记:FLASH读写之一
因为关于STM32的Flash相关的知识点比较多,所以该内容的学习我们分为以下4个部分 1.RAM和ROM的一些基本概念 -- STM32学习笔记:FLASH读写之一 2.STM32的Flash寄存器 ...
- 《STM32学习笔记》2——开发环境的建立
接上文,文中的图片知识,大多数来自视频的截图(来自洋桃电子). 欢迎大家批评指正! STM32学习笔记-专栏 文章目录 一.接口定义 1 芯片引脚整体简介 2 各部分引脚介绍 二.开发板简介 三.IS ...
- stm32学习笔记----双串口同时打开时的printf()问题
stm32学习笔记----双串口同时打开时的printf()问题 最近因为要使用串口2外接PN532芯片实现通信,另一方面,要使用串口1来将一些提示信息输出到上位机,于是重定义了printf(),使其 ...
- STM32学习笔记 | 引起电源和系统异常复位的原因
关注+星标公众号,不错过精彩内容 每一块处理器都有复位的功能,不同处理器复位的类型可能有差异,引起复位的原因也可能有多种. STM32的复位功能非常强大,可通过软件.硬件和一些事件触发系统复位,而且通 ...
- 《STM32学习笔记》4——核心功能电路与编程(下)
接上文,文中的图片,大多数来自视频的截图(来自洋桃电子). 欢迎大家批评指正! STM32学习笔记-专栏 文章目录 一.蜂鸣器驱动 1.蜂鸣器介绍 2.蜂鸣器电路 3.蜂鸣器程序 二. MIDI 音乐 ...
- 【STM32学习笔记-点亮LED灯】
STM32学习笔记-点亮LED灯 文章目录 STM32学习笔记-点亮LED灯 一.原理图分析 二.代码分析 1.mian函数 2.led.c函数 3.led.h函数 4.函数文件整理 5.LED_In ...
- STM32学习笔记(四)丨TIM定时器及其应用(定时中断、内外时钟源选择)
本篇文章包含的内容 一.TIM 定时器 1.1 TIM 定时器简介 1.2 TIM 定时器类型及其工作原理简介 1.2.1 基本定时器工作原理及其结构 1.2.2 通用定时器工作原理及其结构 1.2. ...
- STM32学习笔记(六)丨TIM定时器及其应用(输入捕获丨测量PWM波形的频率和占空比)
本篇文章包含的内容 一.输入捕获 1.1 输入捕获简介 1.2 输入捕获通道的工作原理 1.3 输入捕获的主从触发模式 1.4 输入捕获和PWMI结构 二.频率的测量方法 2.1 测频法 2.2 测周 ...
- STM32学习笔记(15)——SPI协议
STM32学习笔记(15)--SPI协议 一.SPI协议简介 1. 物理层 2. 协议层 (1) 通讯的开始与停止 (2)时钟极性CPOL.时钟相位CPHA 二.STM32的SPI外设 1. 通讯引脚 ...
最新文章
- Java实用教程笔记 子类与继承2
- matlab 单元,MATLAB单元阵列
- java整合mybatis,springboot集成mybatis
- 二叉搜索树的查询操作《算法导论》12.2
- 如何在window下杀死进程?
- Java Web项目,Android和微信小程序的初始页面配置
- Docker基础入门总结
- 浅谈网络通信中的流量整形
- 人人都是产品经理1.0
- CCF NOI1012 变换密码
- 线程的三种创建方式以及区别
- UEFI的诞生与优势
- 世界记忆大师的记忆力训练方法
- .Net NPOI Word模板关键内容替换
- QQ群发消息怎么发?最全攻略分享
- 前端优化之二 图片优化——质量与性能的博弈
- 自定义view————涂鸦画板
- SHA-1和SHA-2算法有什么区别?
- 【答辩问题】计算机专业本科毕业设计答辩的问题及回答
- 蓝色天空HTML网页模板