电容触摸按键实验

开发步骤

本章所要实现的功能是:通过 TIM5 的通道 2(PA1)捕获电容触摸按键输入 信号的高电平脉宽,根据捕获到高电平时间大小控制 DS1 指示灯开关,同时 DS0 指示灯不断闪烁表示系统正常运行。程序框架如下: (1)初始化 PA1 管脚为 TIM5 通道 2 输入捕获功能,设置上升沿捕获等 (2)读取一次捕获高电平的值 (3)电容触摸按键初始化 (4)检测电容触摸按键是否按下 (5)编写主函数

touch_key.h+touch_key.c

#ifndef _touch_key_H
#define _touch_key_H

#include "system.h"
void TIM5_CH2_Input_Init(u16 arr, u16 psc);
u16 Touch_Get_Val();
u8 Touch_Key_Scan(u8 mode);
u8 Touch_Key_Init(u8 psc);

#endif
#include "touch_key.h"
#include "SysTick.h"
#include "stdio.h"
#define Touch_ARR_MAX_VAL 0XFFFF //最大重装载值
u16 touch_default_val=0; //初始化默认值即没触摸时的值,进行对比,得出是否触摸的值
void TIM5_CH2_Input_Init(u16 arr, u16 psc)//自动重装载值,预分频值
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    TIM_ICInitTypeDef TIM_ICInitStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

    
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
    TIM_TimeBaseInitStructure.TIM_Period=arr;//自动重装载值(与预分频值决定计时时间)
    TIM_TimeBaseInitStructure.TIM_Prescaler=psc;//预分频值
    //72000k/预分频值+1=Nk,1k=0.5ms,Nk=1/N ms,再乘自动重装载值等于计数值
    TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//时钟分频因子
    TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//计数模式
    TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure );
    
    NVIC_InitStructure.NVIC_IRQChannel=TIM5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占式优先级,按自己需求配置
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;//响应式优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;    
    NVIC_Init(&NVIC_InitStructure);
    
    TIM_ICInitStructure.TIM_Channel=TIM_Channel_2;//通道1
    TIM_ICInitStructure.TIM_ICFilter=0x00;//ICFILTER <= 0xF//滤波
    TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;//捕获极性为上升沿
    TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;//不分频
    TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;//映射
    TIM_ICInit(TIM5, &TIM_ICInitStructure);
    
    TIM_ITConfig(TIM5, TIM_IT_Update | TIM_IT_CC1, ENABLE);//两个中断,溢出和捕获中断
    TIM_Cmd( TIM5, ENABLE);
}

void Touch_Reset()//将电容电释放掉,从零开始,检查充电时间
{
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
    GPIO_ResetBits( GPIOA, GPIO_Pin_1);//给低电平使电容放电
    delay_ms(5);//放电需要时间
    TIM_ClearFlag(TIM5, TIM_FLAG_CC2 | TIM_FLAG_Update);
    TIM_SetCounter( TIM5, 0);//设定计数器从零开始计数
    
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
}
u16 Touch_Get_Val()//捕获高电平的值
{
    Touch_Reset();
    while(TIM_GetFlagStatus(TIM5, TIM_FLAG_CC2)==0)
    {
        if(TIM_GetCounter(TIM5)>(Touch_ARR_MAX_VAL-500))
        {
            return TIM_GetCounter(TIM5);//超时,返回最大值
        }
    }
    return TIM_GetCapture2(TIM5);
}
u8 Touch_Key_Init(u8 psc)//按键程序初始化 //取得未按下触摸键时所得的标准值
{
    u8 i=0;
    u16 buf[10];
    u32 temp;
    TIM5_CH2_Input_Init(Touch_ARR_MAX_VAL,psc);
    for(i=0;i<10;i++)//循环多次取值,减小所受干扰
    {
        buf[i]=Touch_Get_Val();
        delay_ms(10);
    }
    u8 j=0;
    for(i=0;i<9;i++)//进行排序,取中间6组,进行滤波
    {
        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];
        touch_default_val=temp/6;
        printf("未触摸按键时的值=%d\r\n",touch_default_val);\
    }
    if(touch_default_val>(Touch_ARR_MAX_VAL/2))
    {
    return 1;
    }
    return 0;
}
u16 Touch_Get_MaxVal(u8 s)//取得采样最大值 即按下触摸按键后得到的最大值
{
    u16 temp=0;
    u16 res=0;
    while(s--)
    {
        temp=Touch_Get_Val();
        if(temp>res)res=temp;
    }
    
    return res;
}
#define TOUCH_GATE_VAL  200 //按下触摸后的差值(估计数)
u8 Touch_Key_Scan(u8 mode)//mode为0则单次触摸,为1则连续触摸
{
    u16 sample=3;
    u16 rval=0;
    u8 res=0;
    static u8 keyen=0;
    
    if(mode)keyen=0;
    rval=Touch_Get_MaxVal(sample);
    
    if(rval>(touch_default_val+TOUCH_GATE_VAL)&&rval<(Touch_ARR_MAX_VAL/2))
    {
        if((keyen==0)&&rval>(touch_default_val+TOUCH_GATE_VAL))
        {
            res=1;
        }
        printf("触摸后捕获高电平值为:%d\r\n",rval);
        keyen=1;
    }
    else
        keyen=0;
    return res;
}

main.c

#include "stm32f10x.h"
#include "led.h"
#include "system.h"
#include "SysTick.h"
#include "beep.h"
#include "key.h"
#include "exti.h"
#include "time.h"
#include "pwm.h"
#include "usart.h"
#include "stdio.h"
#include "iwdg.h"
#include "wwdg.h"
#include "input.h"
#include "touch_key.h"
int main()
{
    u8 i=0;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置优先级分组
  SysTick_Init(72);
    LED_Init();
    USART1_Init(115200);//波特率115200
    if(Touch_Key_Init(6-1))printf("捕获错误");//每计数一次12us
    else 
        Touch_Key_Init(6-1);
    while(1)
    {
        if(Touch_Key_Scan(0))LED2=!LED2;
    
        i++;
        if(i%20==0)LED1=!LED1;
        delay_ms(10);
    
    
    }
    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值