STM32-11-电容触摸按键

news2024/9/24 15:28:40

STM32-01-认识单片机
STM32-02-基础知识
STM32-03-HAL库
STM32-04-时钟树
STM32-05-SYSTEM文件夹
STM32-06-GPIO
STM32-07-外部中断
STM32-08-串口
STM32-09-IWDG和WWDG
STM32-10-定时器

STM32电容触摸按键

  • 电容触摸按键原理
    在这里插入图片描述
    在这里插入图片描述

    无手指触摸:上电时,电阻作用下,电容Cs进行充电,直到电容充满,这时候会有一个充电时间Tcs.

    有手指触摸:上电时,电阻作用下,电容CsCx进行充电,电容充满时间会变长,得到充电时间Tcx.
    在这里插入图片描述
    在这里插入图片描述

  • 检测电容触摸按键过程

    1. TPAD引脚设置为推挽输出,输出低电平,实现电容放电到地
    2. TPAD引脚设置为浮空输入(IO复位后的状态),电容开始充电
    3. 同时开启TPAD引脚的输入捕获功能,开始捕获高电平
    4. 等待充电过程中,上升沿触发(充电到Vth(上升沿的电压值))
    5. 计算充电时间(定时器捕获/比较寄存器获取)
  • 硬件结构图
    在这里插入图片描述

  • 代码实现

    • TPAD初始化函数

      uint8_t tpad_init(uint16_t psc)
      {
          uint16_t buf[10];
          uint16_t temp;
          uint16_t i,j;
          
          
          tpad_timx_cap_init(0XFFFF, psc - 1);
          
          //连续读取10次
          for(i = 0; i < 10; i++)
          {
              buf[i] = tpad_get_val();
              delay_init(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];
          }
          
          g_tpad_default_val = temp / 6;
          printf("g_tpad_default_val:%d\r\n", g_tpad_default_val);
      
          if (g_tpad_default_val > 0XFFFF / 2)
          {
              return 1;                   /* 初始化遇到超过TPAD_ARR_MAX_VAL/2的数值,不正常! */
          }
          
          return 0;
      }
      
    • 触摸按键输入捕获设置

      void tpad_timx_cap_init(uint16_t arr, uint16_t psc)
      {
          GPIO_InitTypeDef gpio_init_struct;
          TIM_IC_InitTypeDef timx_ic_cap_chy;
          
          __HAL_RCC_GPIOA_CLK_ENABLE();  //初始化GPIOA时钟
          __HAL_RCC_TIM5_CLK_ENABLE();   //初始化TIM5时钟
          
          gpio_init_struct.Pin = GPIO_PIN_1;       //PA1
          gpio_init_struct.Mode = GPIO_MODE_INPUT; //输入
          gpio_init_struct.Pull = GPIO_PULLDOWN;   //下拉
          gpio_init_struct.Speed = GPIO_SPEED_FREQ_MEDIUM; //中速
          HAL_GPIO_Init(GPIOA, &gpio_init_struct);  //初始化
          
          g_timx_cap_chy_handle.Instance = TIM5;      //定时器基地址
          g_timx_cap_chy_handle.Init.Prescaler = psc; //分频系数
          g_timx_cap_chy_handle.Init.CounterMode = TIM_COUNTERMODE_UP;  //向上计数
          g_timx_cap_chy_handle.Init.Period = arr;    //自动重装载值
          g_timx_cap_chy_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;  //时钟分频因子
          HAL_TIM_IC_Init(&g_timx_cap_chy_handle);
          
          timx_ic_cap_chy.ICPolarity = TIM_ICPOLARITY_RISING;     //上升沿捕获
          timx_ic_cap_chy.ICSelection = TIM_ICSELECTION_DIRECTTI; //映射到TI1
          timx_ic_cap_chy.ICPrescaler = TIM_ICPSC_DIV1;           //输入分频设置为不分频
          timx_ic_cap_chy.ICFilter = 0;                           //输入滤波设置为不滤波
          HAL_TIM_IC_ConfigChannel(&g_timx_cap_chy_handle, &timx_ic_cap_chy, TIM_CHANNEL_2);
          
          HAL_TIM_IC_Start(&g_timx_cap_chy_handle, TIM_CHANNEL_2);  //使能输入捕获和定时器
      }
      

      输入捕获映射到TI1通道,意味着PA1引脚的信号将被定时器的第一个输入捕获通道TI1处理。代码中指定了TIM_ICSELECTION_DIRECTTI,表示直接选择输入引脚作为捕获源,而不是通过其他中间信号。

      PA1引脚的信号映射到定时器通道1(TI1)的过程是通过硬件内部的多路复用器(multiplexer,简称MUX)实现的。

    • 获取捕获值

      uint16_t tpad_get_val(void)
      {
          tpad_reset();
          
          //等待捕获上升沿,捕获结束后标志位会置1
          while(__HAL_TIM_GET_FLAG(&g_timx_cap_chy_handle, TIM_CHANNEL_2) == 0)
          {
              if(g_timx_cap_chy_handle.Instance->CNT > 0xFFFF - 500)
              {
                  return g_timx_cap_chy_handle.Instance->CNT;
              }
          }
          
          return TIM5->CCR2;
      } 
      
    • 复位TPAD

      void tpad_reset(void)
      {
          GPIO_InitTypeDef gpio_init_struct;
          
          gpio_init_struct.Pin = GPIO_PIN_1;
          gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
          gpio_init_struct.Pull = GPIO_PULLUP;
          gpio_init_struct.Speed = GPIO_SPEED_FREQ_MEDIUM;
          HAL_GPIO_Init(GPIOA, &gpio_init_struct);
          
          HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);  //TPAD引脚输出0,放电
          
          delay_ms(5);
          
          g_timx_cap_chy_handle.Instance->SR = 0;   //清除标记
          g_timx_cap_chy_handle.Instance->CNT = 0;  //归零
          
          gpio_init_struct.Pin = GPIO_PIN_1;
          gpio_init_struct.Mode = GPIO_MODE_INPUT;
          gpio_init_struct.Pull = GPIO_NOPULL;
          gpio_init_struct.Speed = GPIO_SPEED_FREQ_MEDIUM;
          HAL_GPIO_Init(GPIOA, &gpio_init_struct);
      }
      
      1. 配置PA1为推挽输出模式,并且设置为上拉电阻。这样可以确保PA1在输出状态下可以稳定的输出高低电平信号。
      2. 设置PA1引脚为低电平,相当于对TPAD引脚进行放电操作。
      3. 延时5ms,确保放电操作完成。
      4. 清除定时器状态寄存器和计数器。
      5. 配置PA1引脚为输入模式,并且设置为无上下拉电阻,这样,TPAD引脚可以正常接收外部输入信号。

      在嵌入式系统中,尤其是在涉及触摸传感器或类似的硬件操作时,先将引脚设置为推挽输出模式再进行放电是一个常见的做法。这种方法可以确保引脚能够快速且有效地放电,从而为后续的操作(例如测量或重新配置引脚为输入模式)提供一个已知的初始状态。

      为什么要先设置为推挽输出模式再进行放电?

      1. 强制性放电
      • 推挽输出模式能够提供较强的驱动能力。通过将引脚设置为推挽输出模式并输出低电平,能够确保引脚上的电容或残留电荷能够迅速放电至0。这对于某些敏感的电路来说是必要的,确保电路在重新配置为输入模式之前没有残余电荷影响测量精度。
      1. 可靠的初始状态
      • 直接将引脚设置为低电平进行放电在某些情况下可能并不能保证完全的放电,特别是在引脚上有较大的寄生电容时。推挽模式可以提供更可靠的低电平输出,确保引脚电位完全放电至0。
      1. 硬件保护
      • 通过推挽输出模式放电,可以避免因高阻抗状态导致的浮动电平问题。高阻抗状态下,外界噪声可能会干扰引脚电平,从而影响后续的测量。
    • 扫描触摸按键

      uint8_t tpad_scan(uint8_t mode)
      {
          static uint8_t keyen = 0;   /* 0, 可以开始检测;  >0, 还不能开始检测; */
          uint8_t res = 0;
          uint8_t sample = 3;         /* 默认采样次数为3次 */
          uint16_t rval;
      
          if (mode)
          {
              sample = 6;             /* 支持连按的时候,设置采样次数为6次 */
              keyen = 0;              /* 支持连按, 每次调用该函数都可以检测 */
          }
      
          rval = tpad_get_maxval(sample);
      
          if (rval > (g_tpad_default_val + 100))    /* 大于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;
      }
      
    • 读取的数据取最大值

      uint16_t tpad_get_maxval(uint8_t n)
      {
          uint16_t temp = 0;
          uint16_t maxval = 0;
      
          while (n--)
          {
              temp = tpad_get_val();  /* 得到一次值 */
      
              if (temp > maxval) maxval = temp;
          }
      
          return maxval;
      }
      
    • 主函数

      int main(void)
      {
          uint8_t t = 0;
      
          HAL_Init();                                 /* 初始化HAL库 */
          sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟, 72Mhz */
          delay_init(72);                             /* 延时初始化 */
          usart_init(115200);                         /* 串口初始化为115200 */
          led_init();                                 /* 初始化LED */
          tpad_init(6);
      
      
          while (1)
          {
              if (tpad_scan(0))   /* 成功捕获到了一次上升沿(此函数执行时间至少15ms) */
              {
                  LED1_TOGGLE();  /* LED1翻转 */
              }
      
              t++;
              if (t == 10)
              {
                  t = 0;
                  LED0_TOGGLE();  /* LED0翻转 */
              }
      
              delay_ms(200);
          }
      }
      
  • 程序运行流程
    在这里插入图片描述

声明:资料来源(战舰STM32F103ZET6开发板资源包)

  1. Cortex-M3权威指南(中文).pdf
  2. STM32F10xxx参考手册_V10(中文版).pdf
  3. STM32F103 战舰开发指南V1.3.pdf
  4. STM32F103ZET6(中文版).pdf
  5. 战舰V4 硬件参考手册_V1.0.pdf

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

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

相关文章

DSP开发入门

视频&#xff1a; 创龙TI 最新DSP CPU核心架构 C66x 以及 KeyStone I 架构 DSP TMS320C6655/57以及TMS320C6678视频教程全集_哔哩哔哩_bilibili 2024年硬汉科技手把手教您学DSP28335视频教程持续更新中_哔哩哔哩_bilibili DSP芯片介绍 DSP选型 TI的DSP 分为三大系列&#…

基于Android的家庭理财APP的设计与实现(论文+源码)_kaic

摘 要 随着我国居民收入和生活水平的提高&#xff0c;家庭理财成为人们热议的焦点问题。在需求分析阶段&#xff0c;系统从用户的实际需求出发&#xff0c;确定了用户账户管理、记账、数据分析和提醒功能等几个核心需求。用户账户管理包括用户注册、登录和密码找回等基本操作…

游戏私域运营指南 | 降低买量成本,精细化游戏私域运营看这篇就懂了!

私域是什么&#xff1f;这个概念在零售行业已经盛行多年&#xff0c;但在游戏行业提及得并不多&#xff0c;从业者们可能更熟悉的 近似概念是“社区运营”。 那么首先&#xff0c;让我们明确定义&#xff1a;相对于社交媒体、搜索引擎、电商平台等需要通过付费投放来进行高效流…

webshell工具-冰蝎流量特征和加密方式

一、冰蝎原理 1.1 简介 冰蝎是一款基于Java开发的动态加密通信流量的新型Webshell客户端&#xff0c;由于通信流量被加密&#xff0c;传统的WAF、IDS 设备难以检测&#xff0c;给威胁狩猎带来较大挑战。冰蝎其最大特点就是对交互流量进行对称加密&#xff0c;且加密密钥是由随…

【前端常见面试题整理】

开放性的题目 自我介绍 突出学习能力 我想换工作的主要原因是 介绍项目 平时是如何学习前端开发的 主要就是两个途径&#xff0c;一个是查阅官方文档&#xff0c;然后就是在网上查找技术资料或者视频去学习。平时没事的时候也会看看github&#xff0c;同时关注一些社区和IT网…

浅说线性DP(上)

前言 在说线性dp之前&#xff0c;我们先来聊一聊动态规划是啥&#xff1f; 动态规划到底是啥&#xff1f; 动态规划是普及组内容中最难的一个部分&#xff0c;也是每年几乎必考的内容。它对思维的要求极高&#xff0c;它和图论、数据结构不同的地方在于它没有一个标准的数学…

Rust最新版安装(v1.78.0+)

系统&#xff1a;Windows 11 专业版 23H2rustc&#xff1a;1.78.0 配置环境变量和设置配置文件 新建文件夹“C:\Rust\Rustup”和“C:\Rust\Cargo”。【以管理员身份运行】打开CMD 设置系统环境变量&#xff0c;如下设置RUSTUP_DIST_SERVER&#xff0c;其余同理 C:\Windows\S…

中国教育 AI 产品正在成为百万美国学生的辅导老师;李飞飞:大模型不存在主观感觉能力丨 RTE 开发者日报 Vol.213

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。 我们的社区编辑团队会整理分享 RTE&#xff08;Real-Time Engagement&#xff09; 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、…

编程5年的老哥说:我代码里从来不用锁,谁爱...

技多不压身&#xff01; 大家好&#xff0c;我是 javapub。 今天一个朋友找我吐槽&#xff0c;说自己平时在工作中几乎用不到需要上锁的场景&#xff0c;就算有也只是并发很小、或者直接从有业务设计上就规避掉了。但一到面试&#xff0c;都是各种锁题&#xff0c;很头疼。 面…

YYDS!哈工大博士PyTorch笔记火了!!

Pytorch是目前常用的深度学习框架之一&#xff0c;它凭借着对初学者的友好性、灵活性&#xff0c;发展迅猛&#xff0c;它深受学生党的喜爱&#xff0c;我本人也是使用的Pytorch框架。 比起 TF 的框架环境配置不兼容&#xff0c;和 Keras 由于高度封装造成的不灵活&#xff0c…

三、Ollama导入大模型(.Net8+SemanticKernel+Ollama)本地运行自己的大模型

Ollama导入大模型 一、导入Ollama大模型1、使用run命令2、使用Modelfile方式 二、导入自定义大模型&#xff08;Ollama官网以外的大模型&#xff09;三、使用OpenWebUI导入大模型 Ollama可以导入官方提供的大模型&#xff0c;也可以导入huggingface上的自定义大模型&#xff08…

以太坊现货ETF获批:引发ETH价格暴涨,市场热议达到高潮

2024年5月24日&#xff0c;北京时间&#xff0c;以太坊现货ETF正式获得美国证券交易委员会&#xff08;SEC&#xff09;的批准&#xff0c;成为继比特币之后&#xff0c;美国主权政府承认的又一加密货币基金产品。这一意外的利好消息引发了加密货币市场的狂欢&#xff0c;以太坊…

东软的第三个研发基地,为什么选择了武汉?

继沈阳、大连之后&#xff0c;东软集团在国内打造的第三个研发基地——武汉东软软件园&#xff0c;于2024年5月25日正式开园。 “占地面积158亩、建筑面积14万余平方米的武汉东软软件园&#xff0c;从开工到竣工仅仅用了18个月的时间。这样的建设速度&#xff0c;充分体现了武汉…

香橙派Kunpeng Pro性能测评:高效能小型服务器开发板的全面体验

香橙派 Kunpeng Pro 是一款面向开发者和教育市场的高性能单板计算机&#xff0c;其搭载了鲲鹏处理器&#xff0c;可提供 8TOPS INT8 计算能力&#xff0c;提供了 8GB 和 16GB 两种内存版本&#xff0c;开发板结合了鲲鹏全栈根技术&#xff0c;全面使能高校计算机系统教学和原生…

3D Web轻量化平台HOOPS Web Platform在数字工厂中的应用实例

今天我们来聊聊HOOPS工具对大型数据的处理和可视化管理。这里是一个数字工厂的仪表盘展示&#xff0c;您可以在仪表盘上看到包括工厂的能源消耗、计划产量等数据信息&#xff0c;以及各种制造机器的生产量。 HOOPS中文网http://techsoft3d.evget.com/ 我们的HOOPS工具&#xf…

window.location.search取不到值

window.location.search window.location.search没有值的原因&#xff1a; URL中使用了 hash &#xff08;指URL中带有#符号&#xff09;,导致URL后面携带的参数被location.hash截取走了&#xff0c;你再使用window.location.search得到的就是空值 打印 window.location 其实…

网络侦察技术

网络侦察技术 收集的信息网络侦察步骤搜索引擎检索命令bing搜索引擎Baidu搜索引擎Shodan钟馗之眼(zoomeye) whois数据库&#xff1a;信息宝库查询注册资料 域名系统网络拓扑社交网络跨域拓展攻击 其它侦察手段社会工程学社会工程学常见形式Web网站查询 其它非技术侦察手段总结网…

通过代码重用攻击绕过现代XSS防御

XSS已有近二十年的历史了&#xff0c;但它仍然是Web上最常见的漏洞之一。因此&#xff0c;已经发展了许多机制来减轻漏洞的影响。我经常会误以为这些机制可以作为针对XSS的保护。今天&#xff0c;我们将了解为什么情况并非如此。我们将在代码重用攻击领域探索一种相对较新的技术…

5.基于python的scRNA-seq细胞状态分析-细胞扰动

参考&#xff1a; [1] https://github.com/Starlitnightly/single_cell_tutorial [2] https://github.com/theislab/single-cell-best-practices 目录 背景识别受扰动影响最大的细胞类型预测细胞的扰动响应构建模拟数据集构建scGEN 背景 前面学习了不同处理条件下的基因差异表…

QGis3.34.5工具软件保存样式,软件无反应问题

在使用QGis软件保存SLD样式的时候&#xff0c;每次保存样式&#xff0c;软件都进入无反应状态&#xff0c;导致无法生成样式文件 百度中多次查询问题点&#xff0c;终未能在在3.34.5这个版本上解决问题。 考虑到可能是软件本身问题&#xff0c;于是删除了3.34.5这个版本&#x…