STM32学习和实践笔记(32):电容触摸按键实验

1.电容触摸按键原理介绍

  触摸按键与传统的机械按键相比,不仅美观而且耐用、寿命长,它颠覆了传统意义上的机械按键控制,只要轻轻触摸,就可以实现按键开关的控制、量化调节甚至方向控制。触摸按键已广泛应用于手机、DVD、洗衣机等消费类电子产品中。本章我们就介绍一种简单的触摸按键:电容式触摸按键。

我们PZ6806D开发板上的电容触摸按键其实就是一小块覆铜区域,也称之为触摸感应区。

  通常我们会将四周的铜片与电路板地信号连通,触摸感应区设计成方便手指触摸大小,并将其连接在输入捕获通道上。  

触摸感应区与四周的铜片区域就形成了一个电容,通过检测电容充放

电时间即可判断是否有触摸。实现原理

电容充放电公式:Vc=V0*(1-e^(-t/RC))

在上图中,R是外接电阻,开关就是STM32管脚的内部开关。CS是触摸感应区与电路板GND之间的杂散电容。当手指按到触摸区时,等于增加了一个CX电容并到CS上,所以电源通过RC对电容的充电时间就会变长。

本实验中,使用TIM5的通道2(PA1管脚)来检测触摸按键是否按下。具体步骤是:

1)在每次检测前,我们需要先将电容Cs(或 Cs+Cx)放电,即配置PA1引脚为推挽输出模式,输出一个低电平,才能使电容放电。这等效于上图中的开关闭合。

2)然后配置PA1 为浮空输入模式,利用外部上拉电阻给电容 Cs(Cs+Cx)充电,同时开启TIM5_CH2的输入捕获,配置极性为上升沿,当检测到上升沿的时候,就认为电容充电完

成了,完成一次捕获检测  每次系统重启时,我们执行一次捕获检测(可认为没有触摸),记录此时捕获到上升沿时,需要多少时间即TCS的值。

3)在后续的捕获检测中,即不断重复上面的第1步和第2步,我们就可以通过与记录的值进行对比,判断是否发生触摸。很明显,如果没有发生触摸,每次捕获发生的时间是基本上相等的,如果有触摸,那么时间必然明显延长。这样,就知道了是否发生触摸了

这就是电容触摸工作的原理!搞清楚了就很简单。

2.编写电容触摸按键控制程序

  本实验所要实现的功能是:通过TIM5的通道2(PA1)捕获电容触摸按键输入信号的高电平脉宽,根据捕获到的高电平时间长短,来判断是否有按键按下,如果有按下,则翻转D2指示灯的状态以提示检测到了一次按下。同时D1指示灯不断闪烁表示系统正常运行。程序框架如下:

(1)初始化PA1管脚为TIM5通道2输入捕获功能,设置上升沿捕获等

(2)读取一次捕获高电平的值

(3)电容触摸按键初始化

(4)检测电容触摸按键是否按下

(5)编写主函数

main.c

#include "system.h"
#include "led.h"
#include "SysTick.h"
#include "usart.h"
#include "input.h"
#include "touch_key.h"int main()
{u8 i=0;SysTick_Init(72);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组LED_Init();USART1_Init(9600);Touch_Key_Init(6);//72M 6分频后12Mwhile(1){if((Touch_Key_Scan(0)==1))//判断触摸是否有效{led2=led2;//有效则翻转指示灯}i++;if(i%20 ==0){led1=!led1;//LED1闪,用来指示主程序循环是否运行}delay_ms(50);}
}

touch_key.c

#include "touch_key.h"
#include "SysTick.h"
#include "usart.h"#define Touch_ARR_MAX_Value 0xffff
u16 touch_default_value =0;void TIM5_CH2_Input_Init(u16 period,u16 prescaler)
{GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//结构体变量声明TIM_ICInitTypeDef TIM_ICInitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);//使能TIM5时钟GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;	//GPIO_Init(GPIOA,&GPIO_InitStructure);TIM_TimeBaseInitStructure.TIM_Period=period;   //装入函数传过来的自动装载值TIM_TimeBaseInitStructure.TIM_Prescaler=prescaler; //装入函数传过来的分频系数TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//1分频(没有分频)TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式:从0开始计数到自动重载值后溢出产生中断TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);//初始化TIM5各参数:自动重装值、分频系统、计数方式等TIM_ICInitStructure.TIM_Channel=TIM_Channel_2; //通道2TIM_ICInitStructure.TIM_ICFilter=0x00; //无滤波TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;//捕获极性设为上升沿TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1; //分频系数TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;//直接映射到TI1TIM_ICInit(TIM5,&TIM_ICInitStructure);TIM_Cmd(TIM5,ENABLE );//使能定时器}void Touch_Reset()
{GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1; 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);//将IO口输出低电平以将触摸按键的电容放电delay_ms(5);TIM_ClearFlag(TIM5,TIM_FLAG_Update|TIM_FLAG_CC2);//清除定时器的状态标志TIM_SetCounter(TIM5,0); //设定定时器初值为0以重新计数GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//重新改为浮空模式以对电容充电GPIO_Init(GPIOA,&GPIO_InitStructure);}u16 Touch_Get_Value()
{Touch_Reset();while(TIM_GetFlagStatus(TIM5,TIM_FLAG_CC2)==0)//{if(TIM_GetCounter(TIM5)>Touch_ARR_MAX_Value-500){return TIM_GetCounter(TIM5);//如果没有发生捕获事件,计数器计到最大值-500后返回当前计数器的值}}return TIM_GetCapture2(TIM5);//如果发生了捕获事件,则返回捕获发生时的计数器值}u8 Touch_Key_Init(u8 psc)
{u8 i,j;u16 buf[10];u16 temp;TIM5_CH2_Input_Init(Touch_ARR_MAX_Value,psc);//定时器5通道2输入捕获初始化for (i=0; i<10;i++){buf[i]= Touch_Get_Value();//得到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;}}//去掉最小的两个,去掉最大的两个,余下的6个取平均值temp=0;for(i=2; i<8;i++){temp+=buf[i];}touch_default_value = temp/6;printf("touch_default_value=%d\r\n",touch_default_value);if(touch_default_value>touch_default_value/2)//这个判断条件是通过实际调试测试决定的return 1;//如果这个值大于最大值的一半,也就对应前面的没有发生捕获的情况,那么认为初始化失败//返回1 表明初始化失败return 0; //返回0表示初始化成功,得到了没有触摸时的缺省充电时间}u16 Touch_Get_MaxVal(u8 n)//得到n次捕获中的最大值
{u16 temp=0;u16 max=0;while(n--){temp=Touch_Get_Value();if(temp>max)max=temp;}return max;}//mode =0 单次扫描,mode =1,连续扫描
//返回Touch_Status,其值为1则表示触摸有效
#define TOUCH_GATE_VAL 100
u8 Touch_Key_Scan(u8 mode)
{u8 Touch_Status;u8 sample =3;u16 MaxVal =0;static u8 keyen =0;if(mode)//mode如为1,则表示连续扫描,因此,每次调用Touch_Key_Scan时都将keyen=0,所以每次都能得到触摸值{				//反之,因为keyen后续=3,所以需要三次之后,才能降为0,才能得到触摸值sample =6;keyen=0;}MaxVal=Touch_Get_MaxVal(sample);//得到三次采样中的最大值if(MaxVal>(touch_default_value+TOUCH_GATE_VAL)&&MaxVal<(10*touch_default_value)){if((keyen==0)&&(touch_default_value+TOUCH_GATE_VAL)){Touch_Status=1;}}printf("触摸后捕获高电平值为:%d\r\n",MaxVal);keyen=3;if(keyen) keyen--;return Touch_Status;}

   touch_key.h

#ifndef _touch_key_H
#define _touch_key_H#include "system.h"void TIM5_CH2_Input_Init(u16 period,u16 prescaler);
u8 Touch_Key_Init(u8 psc);
u8 Touch_Key_Scan(u8 mode);#endif

这个程序因为只能在PZ6806D开发板上才可以运行,而我手上的是PZ6806L,所以没有实际烧录测试,但原理我是完全理解的。

因此,如果在PZ6806L上接出一块小的触摸板,这实验是可以做成功的,这没有什么疑问。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/20004.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

宿舍管理系统带文档java项目基于springboot+vue的宿舍管理系统

文章目录 宿舍管理系统一、项目演示二、项目介绍三、八千字项目文档四、部分功能截图五、部分代码展示六、底部获取项目源码和8000字论文参考&#xff08;9.9&#xffe5;带走&#xff09; 宿舍管理系统 一、项目演示 宿舍管理系统 二、项目介绍 基于springbootvue的前后端分…

MVC、MVP 和 MVVM 架构总结

MVC、MVP 和 MVVM 是常见的软件架构模式&#xff0c;主要用于组织应用程序的结构&#xff0c;特别是在用户界面和业务逻辑之间进行分离。以下是对它们的详细解释&#xff0c;包括它们的差异、优缺点。 MVC&#xff08;Model-View-Controller&#xff09; 结构 Model&#xf…

在长窗口时代,RAG技术是否仍然必要?

自从谷歌推出 Gemini 1.5 Pro&#xff0c;行业内部对于 RAG 的讨论就不绝于耳。 Gemini 1.5 Pro 的性能确实令人瞩目。根据谷歌公布的技术文档&#xff0c;该系统能够稳定处理长达 100 token 的内容&#xff0c;相当于一小时的视频、十一小时的音频、超过三万行的代码或七十万…

【VTKExamples::Utilities】第十七期 ZBuffer

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享VTK样例ZBuffer,并解析接口vtkWindowToImageFilter,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ…

C语言文件操作:打开关闭,读写

程序文件 源程序文件&#xff08;后缀为.c&#xff09; 目标文件&#xff08;Windows环境后缀为.obj&#xff09; 可执行文件&#xff08;Windows环境后缀为.exe&#xff09; fputc FILE* pf fopen("test.txt","w");if (pf NULL){printf("%s\n"…

深入理解Qt计算器应用的构建过程

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、数字按钮的信号与槽函数连接 二、运算符按钮的信号与槽函数连接 三、特殊按钮的信号与…

红外超声波雷达测距(water)

文章目录 一 RS-232二 RS485三 Modbus四 stm32多路超声波测距4.1 设计方案4.2 代码 参考资料总结 实验要求 一. 采用stm32F103和HC-SR04超声波模块&#xff0c; 使用标准库或HAL库 定时器中断&#xff0c;完成1或2路的超声波障碍物测距功能。 1&#xff09;测试数据包含噪声&am…

【Linux】线程ID

大致草稿—————————— 思维导图 学习目标 一、线程ID的理解 1.1 引出对tid的理解 我们先来创建一个线程复习一下线程的函数&#xff1a; pthread_t tid; // 创建一个线程 pthread_create(&tid, nullptr, threadrun, (void*)"thread-1"); // 打印出…

怎么花草识别?方法有三种!

怎么花草识别&#xff1f;在这个五彩斑斓的世界里&#xff0c;花草是我们生活中不可或缺的一部分。它们点缀着我们的环境&#xff0c;为我们带来无尽的美丽与惊喜。然而&#xff0c;面对众多的花草种类&#xff0c;你是否曾感到困惑和迷茫&#xff0c;不知道如何识别它们&#…

VIO System 丨适用于控制器开发前期的测试系统

VIO综述 嵌入式软件的HIL测试需要复杂的测试系统及完整的ECU硬件&#xff0c;这导致通常只能在开发流程的后期阶段进行测试。全新推出的低成本解决方案VIO System&#xff0c;使得在开发前期不仅可以进行总线通讯测试&#xff0c;也可以同时进行I/O信号测试。 该系统旨在通过…

LabVIEW版本控制

LabVIEW作为一种流行的图形化编程环境&#xff0c;在软件开发中广泛应用。有效地管理版本控制对于确保软件的可靠性和可维护性至关重要。LabVIEW提供了多种方式来管理VI和应用程序的修订历史&#xff0c;以满足不同规模和复杂度的项目需求。 LabVIEW中的VI修订历史 LabVIEW内置…

docker安装Mysql5.7版本

首先Linux系统已经安装好了docker应用。 1.搜索镜像 docker search mysql 2.拉取5.7的镜像 总之,选starts最多的那个就对了。 docker pull mysql:5.7 ~ docker pull mysql:5.7 5.7: Pulling from library/mysql fc7181108d40: Downloading [============> …

mysql创建数据表----centos7.9

mysql创建数据表 查看存在的表 show tables;我这里还未创建任何表所以是这样的 如有是这样 若没有表需要先创建一个表 CREATE DATABASE tb_your_name&#xff1b;创建字段及属性 CREATE TABLE tb_laws_regulations (id INT AUTO_INCREMENT PRIMARY KEY, -- 文件唯…

柯桥外贸俄语哪里可以学,零基础俄语培训

Де́лать 做 из му́хи 从苍蝇 слона́ 大象 我觉得汉语里有一个很合适的词来形容&#xff1a; Де́лать из му́хи слона́ 就是 小题大做&#xff0c;本来是一件很小的事&#xff0c;却把它形容成天大的事一样 Хвтит де́…

【UE5.1 角色练习】10-物体抬升、抛出技能 - part2

目录 前言 效果 步骤 一、让物体缓慢的飞向手掌 二、向着鼠标方向发射物体 前言 在上一篇&#xff08;【UE5.1 角色练习】08-物体抬升、抛出技能 - part1&#xff09;的基础上继续完成角色将物体吸向手掌&#xff0c;然后通过鼠标点击的方向来发射物体的功能。 效果 步骤…

代码随想录算法训练营第三十二 | ● 122.买卖股票的最佳时机II ● 55. 跳跃游戏 ● 45.跳跃游戏II

122.买卖股票的最佳时机II 讲解链接&#xff1a;https://programmercarl.com/1005.K%E6%AC%A1%E5%8F%96%E5%8F%8D%E5%90%8E%E6%9C%80%E5%A4%A7%E5%8C%96%E7%9A%84%E6%95%B0%E7%BB%84%E5%92%8C.html 简单思路&#xff1a;逐个计算连续两天的股票差值&#xff0c;sum初始为零&…

【并查集】专题练习

题目列表 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 模板 836. 合并集合 - AcWing题库 #include<bits/stdc.h> using lllong long; //#define int ll const int N1e510,mod1e97; int n,m; int p[N],sz[N]; int find(int a) {if(p[a]!a) p[a]find(p[a]);return p[a…

第十八讲:联合和枚举

第十八讲&#xff1a;联合和枚举 1.联合体&#xff08;共用体&#xff09;1.1联合体的声明1.2联合体大小的计算1.3联合体的特点1.4联合体的使用1.4.1联合体的直接使用1.4.2联合体直接使用的优化方法1.4.3联合体成员中含有数组的使用1.4.4使用联合体判断当前机器是大端排序&…

K8s(Kubernetes)常用命令

大家好&#xff0c;当谈及容器编排工具时&#xff0c;Kubernetes&#xff08;常简称为K8s&#xff09;无疑是当今最受欢迎和广泛使用的解决方案之一。作为一个开源的容器编排平台&#xff0c;Kubernetes 提供了丰富的功能&#xff0c;可以帮助开发人员和运维团队管理、部署和扩…

电商分析@电商数据与运营优化

电商数据分析与运营优化是指通过对电商平台的各种数据进行深入分析&#xff0c;以发现潜在的问题和机会&#xff0c;并采取相应的优化措施&#xff0c;提高电商运营效率和盈利能力。 首先&#xff0c;电商数据分析需要收集和整理各类数据&#xff0c;包括销售数据、用户数据、流…