野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 14012|回复: 29

三言两语教会你用STM32的定时器输入捕获写电容按键检测程序,保证你可以学会!

[复制链接]
发表于 2016-9-14 16:45:56 | 显示全部楼层 |阅读模式
下面的是整个配套的程序,针对霸道和指南者两个开发板。
文档: 零死角玩转STM32-电容按键检测.pdf (807.29 KB, 下载次数: 190)
霸道: 【霸道】-TIM—输入捕获之电容按键检测.zip (403.79 KB, 下载次数: 113) 指南者: 【指南者】-TIM—输入捕获之电容按键检测.zip (404.99 KB, 下载次数: 120)

1-电容按键原理图,基于野火STM32 霸道和指南者 这两个开发板。原理图中的TPAD1就是一块圆形的铜皮,铜皮的周围是一大片隔开的GND,这样就构成了一个电容。
3.jpg
2-原理简述
开发板上电之后,电容按键默认已经充满了电,要想测得电容按键的充电时间, 就必须先把电容按键的电放掉,方法为让接电容按键的IO输出低电平即可。放电完毕之后,再把连接电容按键的IO配置为输入,然后通过输入捕获的方法测量电容按键的充电时间,这个充电时间是没有手指触摸的情况下的充电时间。当有手指触摸的情况下,相当于电容变大,充电时间会变长,我们只需要对比这两个时间就可以知道电容按键是否有手指触摸。

下面的是电容按键的复位函数,就是把电容放电。
  1. /**
  2.   * @brief  复位电容按键,放电,重新充电
  3.   * @param  无
  4.   * @retval 无
  5.   * 说明:
  6.   * 开发板上电之后,电容按键默认已经充满了电,要想测得电容按键的充电时间
  7.   * 就必须先把电容按键的电放掉,方法为让接电容按键的IO输出低电平即可
  8.   * 放电完毕之后,再把连接电容按键的IO配置为输入,然后通过输入捕获的方法
  9.   * 测量电容按键的充电时间,这个充电时间是没有手指触摸的情况下的充电时间
  10.   *
  11.   * 当有手指触摸的情况下,充电时间会变长,我们只需要对比这两个时间就可以
  12.   * 知道电容按键是否有手指触摸
  13.   */
  14. void TPAD_Reset(void)
  15. {
  16.         GPIO_InitTypeDef GPIO_InitStructure;

  17.   // 输入捕获通道1 GPIO 初始化
  18.         RCC_APB2PeriphClockCmd(TPAD_TIM_CH_GPIO_CLK, ENABLE);
  19.   GPIO_InitStructure.GPIO_Pin =  TPAD_TIM_CH_PIN;
  20.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        
  21.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  22.   GPIO_Init(TPAD_TIM_CH_PORT, &GPIO_InitStructure);
  23.         
  24.         // 连接TPAD的IO配置为输出,然后输出低电平,延时一会,确保电容按键放电完毕
  25.         GPIO_ResetBits(TPAD_TIM_CH_PORT,TPAD_TIM_CH_PIN);
  26.   
  27.         // 放电是很快的,一般是us级别
  28.         SysTick_Delay_Ms( 5 );
  29.         
  30.         // 连接TPAD的IO配置为输入,用于输入捕获
  31.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  32.   GPIO_Init(TPAD_TIM_CH_PORT, &GPIO_InitStructure);
  33. }
复制代码
3-获取输入捕获的值
当电容按键复位之后,即放电结束之后,我们调用uint16_t TPAD_Get_Val(void)函数,该函数返回的值是捕获比较寄存器的值。具体的原理是:电容按键在复位放电结束之后,由上拉电阻给电容充电,当电容充电到1.8V的时候,就会被IO口捕获到,我们事先先初始化好定时器的输入捕获为上升沿捕获,当捕获到上升沿之后,当前计数器的值会被锁存到捕获寄存器,我们只需要读取捕获寄存器的值即可,当读取了捕获寄存器的值之后,捕获标志会被清0。当电容按键有被手指触摸和没有被手指触摸的情况下,捕获到的值是不一样的。在程序中,我们只需要比较这两个捕获的值就可以知道是否有手指触摸了电容按键。在指南者中,电容按键没有被手指触摸的情况下,捕获寄存器的值为71,霸道的值为218,这两个值非常稳定,因为硬件已经确定了。虽然指南者跟霸道的电容按键的面积大小差不多,但是捕获的值却相差比较大,那是因为指南者是双面板,霸道是四层板的缘故。
  1. /**
  2.   * @brief  获取定时器捕获值
  3.   * @param  无
  4.   * @retval 定时器捕获值。如果超时,则直接返回定时器的计数值。
  5.   */
  6. uint16_t TPAD_Get_Val(void)
  7. {               
  8.         // 每次捕获的时候,必须先复位放电
  9.         TPAD_Reset ();
  10.         
  11.         // 当电容按键复位放电之后,计数器清0开始计数
  12.   TIM_SetCounter (TPAD_TIM,0);
  13.         // 清除相关的标志位
  14.         TIM_ClearITPendingBit (TPAD_TIM, TPAD_TIM_IT_CCx | TIM_IT_Update );
  15.         
  16.         // 等待捕获上升沿,当电容按键充电到1.8V左右的时候,就会被认为是上升沿
  17.         while(TIM_GetFlagStatus (TPAD_TIM, TPAD_TIM_IT_CCx) == RESET)
  18.         {
  19.                 // 如果超时了,直接返回CNT的值
  20.                 if ( TIM_GetCounter (TPAD_TIM) > TPAD_TIM_Period - 500 )
  21.                 {
  22.                         return TIM_GetCounter (TPAD_TIM);
  23.                 }                        
  24.         }
  25.         
  26.         // 获取捕获比较寄存器的值
  27.         return TPAD_TIM_GetCapturex_FUN(TPAD_TIM);
  28. }
复制代码
4-定时器输入捕获初始化
我们这里配置定时器的时钟为1M,即计数器计数一次的时间为1us,电容按键的充电时间基本都在ms以内,所以这个频率完全足够。
  1. static void TPAD_TIM_Mode_Config(void)
  2. {
  3.   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  4.         TIM_ICInitTypeDef TIM_ICInitStructure;
  5.         // 开启定时器时钟,即内部时钟CK_INT=72M
  6.         TPAD_TIM_APBxClock_FUN(TPAD_TIM_CLK,ENABLE);

  7. /*--------------------时基结构体初始化-------------------------*/        
  8.         // 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
  9.         TIM_TimeBaseStructure.TIM_Period=TPAD_TIM_Period;        
  10.         // 驱动CNT计数器的时钟 = Fck_int/(psc+1)
  11.         TIM_TimeBaseStructure.TIM_Prescaler= TPAD_TIM_Prescaler;        
  12.         // 时钟分频因子 ,配置死区时间时需要用到
  13.         TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;               
  14.         // 计数器计数模式,设置为向上计数
  15.         TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;               
  16.         // 重复计数器的值,没用到不用管
  17.         TIM_TimeBaseStructure.TIM_RepetitionCounter=0;        
  18.         // 初始化定时器
  19.         TIM_TimeBaseInit(TPAD_TIM, &TIM_TimeBaseStructure);

  20.         /*--------------------输入捕获结构体初始化-------------------*/               
  21.         // 配置输入捕获的通道,需要根据具体的GPIO来配置
  22.         TIM_ICInitStructure.TIM_Channel = TPAD_TIM_CHANNEL_x;
  23.         // 输入捕获信号的极性配置
  24.         TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  25.         // 输入通道和捕获通道的映射关系,有直连和非直连两种
  26.         TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  27.         // 输入的需要被捕获的信号的分频系数
  28.         TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  29.         // 输入的需要被捕获的信号的滤波系数
  30.         TIM_ICInitStructure.TIM_ICFilter = 0;
  31.         // 定时器输入捕获初始化
  32.         TIM_ICInit(TPAD_TIM, &TIM_ICInitStructure);
  33.         
  34.         // 使能计数器
  35.         TIM_Cmd(TPAD_TIM, ENABLE);
  36. }
复制代码
5-主函数
在主函数里面,我们调用temp = TPAD_Get_Val();函数来获取捕获值,霸道开发板中,电容按键没有触摸的情况下,捕获值是稳定在218,当有手触摸时,捕获值一直大于300,当你的手的面积大一点的情况下,会去到500,所以我们可以简单的判断只要捕获值大于300时候,就表示电容按键有被按下。我们这个程序是最简单的,非常容易懂,如果真正的项目中,我们需要读取取值然后取平均值。当然,原理我们懂了之后,后面的都是小菜一碟。
  1. int main(void)
  2. {        
  3.         uint16_t temp;
  4.         
  5.         /* led 端口配置 */
  6.         LED_GPIO_Config();
  7.         
  8.         /* 蜂鸣器初始化 */        
  9.         Beep_Init();

  10.         /* 串口初始化 */
  11.         USART_Config();
  12.         printf ( "\r\n野火STM32 输入捕获电容按键检测实验\r\n" );
  13.         printf ( "\r\n触摸电容按键,蜂鸣器则会响\r\n" );
  14.         
  15.         TPAD_TIM_Init();
  16.         temp = TPAD_Get_Val();
  17.                
  18.         // 调试的时候可以把捕获的值打印出来,看看默认的充电时间是多少
  19.         printf("电容按键默认充电时间为: %d us\n",temp);
  20.         
  21.         while(1)
  22.         {
  23.                 temp = TPAD_Get_Val();
  24.                 if( temp > 300 )
  25.                 {
  26.                         BEEP_ON();
  27.                         SysTick_Delay_Ms(10);
  28.                         BEEP_OFF();
  29.                 }
  30.         }
  31. }
复制代码








回复

使用道具 举报

发表于 2016-9-14 16:50:20 | 显示全部楼层
学习下。。。。。
回复

使用道具 举报

发表于 2016-9-14 16:55:14 | 显示全部楼层
学习学习~~~~~~~~~~~~~~~
回复

使用道具 举报

发表于 2016-9-14 16:55:16 | 显示全部楼层
火哥把这些总结写进书里面多好啊
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-9-14 17:03:48 | 显示全部楼层
SUNboy 发表于 2016-9-14 16:55
火哥把这些总结写进书里面多好啊

书里面写的更详细                       
回复 支持 反对

使用道具 举报

发表于 2016-9-14 17:04:20 | 显示全部楼层
来 支持一下
回复 支持 反对

使用道具 举报

发表于 2016-9-14 17:07:49 | 显示全部楼层
学习火哥!!!
回复

使用道具 举报

发表于 2016-9-14 17:11:07 | 显示全部楼层
正在苦苦寻找。。。。
回复 支持 反对

使用道具 举报

发表于 2016-9-14 17:14:59 | 显示全部楼层
火哥推荐的,一定得收藏
回复 支持 反对

使用道具 举报

发表于 2016-9-14 18:05:44 | 显示全部楼层
kk                     
回复 支持 反对

使用道具 举报

发表于 2016-9-14 18:10:54 | 显示全部楼层
牛                 
回复 支持 反对

使用道具 举报

发表于 2016-9-14 21:54:17 | 显示全部楼层
回复
可见
回复

使用道具 举报

发表于 2016-9-14 22:33:45 | 显示全部楼层
                             
回复 支持 反对

使用道具 举报

发表于 2016-9-15 08:55:16 | 显示全部楼层
学习一下,~~~~
回复

使用道具 举报

发表于 2016-9-15 14:10:49 | 显示全部楼层
          哇               
回复 支持 反对

使用道具 举报

发表于 2016-9-15 21:01:02 | 显示全部楼层
好好学习天天向上
回复 支持 反对

使用道具 举报

发表于 2016-9-16 21:30:22 | 显示全部楼层
电容按键      看看
回复 支持 反对

使用道具 举报

发表于 2016-9-20 09:28:23 | 显示全部楼层
重复计数器的值,这是是啥意思呢,我一直把他和自动重载值弄不清楚
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-9-20 09:32:31 | 显示全部楼层
没有伞的孩子 发表于 2016-9-20 09:28
重复计数器的值,这是是啥意思呢,我一直把他和自动重载值弄不清楚

计数器计数到自动重装载寄存器值的时候,重复计数器就加1,重复计数器记录的是计数器需要计数多少次到自动重装载寄存器。只有高级定时器才有这个寄存器。
回复 支持 反对

使用道具 举报

发表于 2016-9-20 10:18:04 | 显示全部楼层
学习                                                                  
回复 支持 反对

使用道具 举报

发表于 2016-9-20 10:32:04 | 显示全部楼层
新出的视屏真心不错,给满分
回复 支持 反对

使用道具 举报

发表于 2016-9-20 11:47:37 | 显示全部楼层
看看到底是怎么补货的
回复 支持 反对

使用道具 举报

发表于 2016-9-20 13:20:16 | 显示全部楼层
kankankanaknakan
回复 支持 反对

使用道具 举报

发表于 2016-9-20 15:28:52 | 显示全部楼层
fire 发表于 2016-9-20 09:32
计数器计数到自动重装载寄存器值的时候,重复计数器就加1,重复计数器记录的是计数器需要计数多少次到自 ...

"重复计数器记录的是计数器需要计数多少次到自动重装载寄存器"那这个寄存器具体有啥用呢
回复 支持 反对

使用道具 举报

发表于 2016-9-20 15:45:44 | 显示全部楼层
很牛。。。。。。。
回复

使用道具 举报

发表于 2016-9-22 09:05:30 | 显示全部楼层
好东西,学习学习
回复 支持 反对

使用道具 举报

发表于 2016-9-22 10:10:06 | 显示全部楼层
隐藏内容看起来!
回复 支持 反对

使用道具 举报

发表于 2016-9-22 10:22:58 | 显示全部楼层
看看                           
回复 支持 反对

使用道具 举报

发表于 2016-9-27 17:56:08 | 显示全部楼层
一个按键很简单,多个按键的时候,就得防误触摸,状态机了。
回复 支持 反对

使用道具 举报

发表于 2017-2-9 15:20:55 | 显示全部楼层
多谢火哥的分享。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-3-29 05:11 , Processed in 0.053169 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表