首先,我先介绍电容触摸按键的原理。

一个电容充满电的时候是需要一定时间,当两个电容并联的时候,此时,总电容大小就变成两个电容之和。导致充电的时间变成。电容触摸实验就是基于此,来根据时间的长短变换来确定是否有按键按下,并做出相应的反应。

我们从主函数开始看

int main(void)
 {    
     u8 t=0;      
    delay_init();             //延时函数初始化      
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    uart_init(115200);     //串口初始化为115200
     LED_Init();                 //LED端口初始化
  TPAD_Init(6);            //初始化触摸按键
       while(1)
    {                                                         
         if(TPAD_Scan(0))    //成功捕获到了一次上升沿(此函数执行时间至少15ms)
        {
            LED1=!LED1;        //LED1取反
        }
        t++;
        if(t==15)         
        {
            t=0;
            LED0=!LED0;        //LED0取反,提示程序正在运行
        }
        delay_ms(10);
    }

while里面的先不看。当程序初始化好,走到TPAD_Init(6);

#define TPAD_ARR_MAX_VAL     0XFFFF    //最大的ARR值
vu16 tpad_default_val=0;
u8 TPAD_Init(u8 psc)
{
    u16 buf[10];
    u16 temp;
    u8 j,i;
    TIM5_CH2_Cap_Init(TPAD_ARR_MAX_VAL,psc-1);//以12Mhz的频率计数 
    for(i=0;i<10;i++)//连续读取10次
    {                 
        buf[i]=TPAD_Get_Val();
        delay_ms(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];//取中间的6个数据进行平均
    tpad_default_val=temp/6;
    printf("tpad_default_val:%d\r\n",tpad_default_val);    
    if(tpad_default_val>TPAD_ARR_MAX_VAL/2)return 1;//初始化遇到超过TPAD_ARR_MAX_VAL/2的数值,不正常!
    return 0;                                            
}

开始,程序创建一个数组,为了取平均值,获取没有按键按下时的准确时间;

TIM5_CH2_Cap_Init(TPAD_ARR_MAX_VAL,psc-1);//以12Mhz的频率计数 (定时器初始化),这里就不说了

这里的定时器时钟频率是72Mhz,所以计数频率是72/(psc-1+1)=12,这是计数频率 ,不是定时器周期。

buf[i]=TPAD_Get_Val();跳转定时器捕获上升沿时间

u16 TPAD_Get_Val(void)
{                   
    TPAD_Reset();
    while(TIM_GetFlagStatus(TIM5, TIM_IT_CC2) == RESET)//等待捕获上升沿
    {
        if(TIM_GetCounter(TIM5)>TPAD_ARR_MAX_VAL-500)return TIM_GetCounter(TIM5);//超时了,直接返回CNT的值
    };    
    return TIM_GetCapture2(TIM5);      
}

void TPAD_Reset(void)
{
      GPIO_InitTypeDef  GPIO_InitStructure; 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);     //使能PA端口时钟
    
    //设置GPIOA.1为推挽使出
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;                 //PA1 端口配置
     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);                         //PA.1输出0,放电

delay_ms(5);

TIM_SetCounter(TIM5,0);        //归0
    TIM_ClearITPendingBit(TIM5, TIM_IT_CC2|TIM_IT_Update); //清除中断标志
    //设置GPIOA.1为浮空输入
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;     //浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);

}

TPAD_Reset();

这个函数的目的是为了先将通过引脚输出低电平来达到电容的电放掉的目的,之后,在将引脚设为输入模式,清除中断标志位,这里不需要对中断进行初始化,因为我们用不到中断服务函数,我们只需要确定是否发生中断。

while(TIM_GetFlagStatus(TIM5, TIM_IT_CC2) == RESET)//等待捕获上升沿
    {
        if(TIM_GetCounter(TIM5)>TPAD_ARR_MAX_VAL-500)return TIM_GetCounter(TIM5);//超时了,直接返回CNT的值
    };    
    return TIM_GetCapture2(TIM5);      
}

如果一直没有捕获上升沿,则

if(TIM_GetCounter(TIM5)>TPAD_ARR_MAX_VAL-500)return TIM_GetCounter(TIM5);//超时了,直接返回CNT的值(防止非法状态,比如一直是低电平,导致死循环。)这里为什么减500,我也不知道,查资料说是平经验得到的,鬼知道是什么经验;

如果,捕获高电平则返回定时器5 的计数器值

TIM_GetCapture2(TIM5);

TIM_GetCounter(TIM5);

这两句话其实差别不大,第一句话,适当定时器5 通道处于输入模式下,CCR存放的上次捕获事件 的计数器的值返回。第二句话,是直接返回计数器值。只不过第一个数字更准确点。

通过TPAD_Init函数的第一次循环,获取十次没有按下的时间,之后,进行大小排序,去掉最大和最小,求平均,最后输出;

if(tpad_default_val>TPAD_ARR_MAX_VAL/2)return 1;//初始化遇到超过TPAD_ARR_MAX_VAL/2的数值,不正常!
    return 0;        这里是为了有需要的准备的,因为主函数没有接受,所以也没用。

tpad_default_val>TPAD_ARR_MAX_VAL/2 至于这句话怎么得到的,也是凭经验,我也查不到相关资料,只知道凭经验。

这样,就彻底得到了没有按键按下的时候的时间T1

接下来,就是获取按键按下的时间

while(1)
    {                                                         
         if(TPAD_Scan(0))    //成功捕获到了一次上升沿(此函数执行时间至少15ms)
        {
            LED1=!LED1;        //LED1取反
        }
        t++;
        if(t==15)         
        {
            t=0;
            LED0=!LED0;        //LED0取反,提示程序正在运行
        }
        delay_ms(10);
    }
 }

TPAD_Scan(0)

#define TPAD_GATE_VAL     100    //触摸的门限值,也就是必须大于tpad_default_val+TPAD_GATE_VAL,才认为是有效触摸.

这里tpad_default_val就是没有按键按下的计数器大小,上面讲过
u8 TPAD_Scan(u8 mode)
{
    static u8 keyen=0;    //0,可以开始检测;>0,还不能开始检测     
    u8 res=0;
    u8 sample=3;        //默认采样次数为3次     
    u16 rval;
    if(mode)
    {
        sample=6;        //支持连按的时候,设置采样次数为6次
        keyen=0;        //支持连按      
    }
    rval=TPAD_Get_MaxVal(sample); 
    if(rval>(tpad_default_val+TPAD_GATE_VAL))//大于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;
}

这里的mode的作用就是选择是否支持连续按。这里只讲解mode=0,及不支持连按

TPAD_Get_MaxVal(sample);

u16 TPAD_Get_MaxVal(u8 n)
{
    u16 temp=0;
    u16 res=0;
    while(n--)
    {
        temp=TPAD_Get_Val();//得到一次值
        if(temp>res)res=temp;
    };
    return res;
}

这里sample为3,及计算三次。TPAD_Get_Val();这个函数上面讲过,就是获取计数器的值,只不过这里指的是按键按下后的值;

if(temp>res)res=temp;获取3次数值中最大的,返回;

if(rval>(tpad_default_val+TPAD_GATE_VAL))//大于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;
}

如果条件成立,则进行返回1,同时也可以选择输出按键按下的时间

if(keyen)keyen--;  这句话,个人认为是进行延时

if(TPAD_Scan(0))    //成功捕获到了一次上升沿(此函数执行时间至少15ms)
        {
            LED1=!LED1;        //LED1取反
        }
        t++;
        if(t==15)         
        {
            t=0;
            LED0=!LED0;        //LED0取反,提示程序正在运行
        }
        delay_ms(10);
    }
 }
当if语句得到为1时,则可以令灯翻转,得到0,则跳动到下面语句

t++;
        if(t==15)         
        {
            t=0;
            LED0=!LED0;        //LED0取反,提示程序正在运行
        }
        delay_ms(10);
    }这语句的目的就是告诉我们程序是正在运行的,发生错误的话是TPAD_Scan(0)错误

基于stm32f10x(原子)的电容触摸实验的个人解读 (16)相关推荐

  1. i.MX6ULL终结者电容触摸实验程序设计

    本实验的源码工程在开发板光盘资料的:i.MX6UL终结者光盘资料\04_裸机例程源码\17_touchscreen 目录下.我们在Ubuntu系统下使用命令"mkdir 17_touchsc ...

  2. 最简单DIY基于STM32的远程控制电脑系统①(电容触摸+按键控制)

    STM32库函数开发系列文章目录 第一篇:STM32F103ZET6单片机双串口互发程序设计与实现 第二篇:最简单DIY基于STM32单片机的蓝牙智能小车设计方案 第三篇:最简单DIY基于STM32F ...

  3. 判断按键值_「正点原子NANO STM32开发板资料连载」第十六章电容触摸按键实验...

    1)实验平台:ALIENTEK NANO STM32F411 V1开发板2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第十六章电容 ...

  4. STM32精英版(正点原子STM32F103ZET6开发板)学习篇12——电容触摸按键实验

    电容触摸按键原理 RC充放电电路原理:   RC充放电原理,其实就是电(R)和电容(C)组成的串联电路.   按键开关未按下时,电路两端电压都是0V,无法形成电势差,也就无法形成电流.但当按键开关按下 ...

  5. 【正点原子Linux连载】第六十四章 Linux 多点电容触摸屏实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...

  6. 基于正点原子STM32F103精英板IIC实验的MS5611气压计的使用

    MS5611是一款气压计,能够提供高精度的气压值与温度值,这次做项目正好需要用到这款传感器,包括之前也没好好学习用过IIC,所以写下博客记录一下. 如果有需要使用的朋友可以去https://downl ...

  7. Mixly(米思齐)的安装以及基于Arduino开发板实现电容触摸控制灯

    Mixly(米思齐)的安装以及基于Arduino开发板实现电容触摸控制灯 1.Mixly下载 http://mixly.org/bnu-maker/mixly-arduino-win Mixly软件安 ...

  8. linux 正点原子ov5640_【正点原子FPGA连载】第二十六章基于OV5640的二值化实验-摘自【正点原子】领航者 ZYNQ 之嵌入式开发指南 (amobbs.com 阿莫电子论坛)...

    本帖最后由 正点原子 于 2020-10-26 16:21 编辑 QQ群头像.png (1.78 KB) 2020-10-24 10:50 上传5)关注正点原子公众号,获取最新资料 100846rel ...

  9. 基于正点原子电机实验的pid调试助手代码解析(速度环控制)

    这里写目录标题 下位机与PID调试助手传输的原理 代码讲解(基于正点原子) 解析数据接受和数据发送的底层函数 数据接受 数据帧格式 环形数组以及怎么找到它的帧头位置 crc校验 数据发送 数据上传函数 ...

最新文章

  1. shell 实现ip字符串与整形互转
  2. 算法工程师和算法框架开发,谁会代表未来?
  3. 数据结构算法题整理5
  4. 【ICML2019】Set Transformer:置换不变的注意力神经网络框架
  5. 独家CleanMyMac使用教程
  6. 密码(图解密码技术)_第二章_Enigma密码机
  7. 平面设计中有趣的词云图如何设计
  8. TA入门笔记(十五)
  9. 武汉适合几月份去旅游 武汉必去景点
  10. QtDesigner视频手把手教程制作一个弹性,自适应大小的页面布局
  11. 手机开机启动慢是什么原因_手机开机慢,详细教您手机开机慢怎么办
  12. 通讯录管理系统C语言课程设计
  13. 如何用python写游戏脚本?
  14. AutoService+javaPoet+maven+注解自动生成java代码
  15. 1. 用U盘安装Centos6.5 + Win7 双系统
  16. 4种整流5种滤波电路总结
  17. 初识Spring Cloud 之 五大神兽
  18. python字典遍历的几种方法(for in 用法)
  19. 榛子云短信验证平台与springboot集成的短信验证
  20. 博图V14完美程序案例;整套完整程序,硬件包含:变频器、ET 200、交换机、RFID、PN、HMI等硬件

热门文章

  1. jeecg-boot 隐藏菜单操作步骤
  2. 【modlearts】华为人工智能平台_modelarts平台系列教程3_预置算法_图像识别1
  3. Windows搭建局域网Git服务器
  4. IE浏览器如何实现断点续传
  5. MacbookPro下载word文件显示dms怎么办
  6. dell加装固态硬盘_[图解]戴尔灵越15R 5537怎么更换加装固态硬盘?
  7. Mr. Kitayuta vs. Bamboos
  8. 常见二维码上那些奇怪的图案是什么
  9. java语言实现视频音频采集_详解js的视频和音频采集
  10. 孟岩:我反对将Token翻译成“代币”