STM8S触摸按键固件库详解

由于刚好有小项目需要用到触摸按键,stm8s可以节约一块触摸按键的片子,并且成本比较低。在某些对成本比较敏感的应用还是有价值的。现将自己网上找到的资料与自己学习的心得记下与大家分析。ST的底层库对滚动条也支持,效果还是不错的

一、原理分析

ST的电容式触摸按键方案通过一个电阻和感应电极的电容CX构成的阻容(RC)网络的充电/放电时间来检测人体触摸所带来的电容变化。


如上图所示,当人手按下时相当于感应电极上并联了一个电容Cx,增加了感应电极上的电容,感应电极进行充放电的时间会增加,从而检测到按键的状态。

先用开关将 Cs(或 Cs+Cx)上的电放尽,然后断开开关,让 R 给 Cs(或 Cs+Cx)充电,当没有手指触摸的时候, Cs 的充电曲线如图中的 A 曲线。而当有手指触摸的时候, 手指和 TPAD之间引入了新的电容 Cx,此时 Cs+Cx 的充电曲线如图中的 B 曲线。 从上图可以看出, A、 B两种情况下, Vc 达到 Vth 的时间分别为 Tcs 和 Tcs+Tcx。
其中, 除了 Cs 和 Cx 我们需要计算,其他都是已知的,

根据电容充放电公式:Vc=V0*(1-e^(-t/RC))
其中 Vc 为电容电压, V0 为充电电压, R 为充电电阻, C 为电容容值, e 为自然底数, t 为充电时间。根据这个公式,我们就可以计算出 Cs 和 Cx。 利用这个公式,我们还可以作一个简单的电容计,直接可以测电容容量了,有兴趣的朋友可以捣鼓下。

其实我们只要能够区分 Tcs 和 Tcs+Tcx,就已经可以实现触摸检测了,当充电时间在 Tcs 附近,就可以认为没有触摸,而当充电时间大于 Tcs+Tx 时,就认为有触摸按下( Tx为检测阀值)。
实际应用中感应电极可以直接在PCB板上绘制成按键、滚轮或滑动条的应用样式,也可以做成弹簧件插在PCB板上,即使隔着绝缘层(玻璃、树脂)也不会对其检测性能有所影响。

二、硬件设计


网络标号描述

REF_LOAD:对按键进行充放电的引脚,所有按键必须共用一个LOAD(保证一致性)。也可以用VCC代替。

SH_MCKEY:屏蔽引脚,这个根据实际情况来觉得是否接,一般调试的时候预留着

PD2-PD6 PC6 PC7为用户按键部分

注意:不要将按键检测脚安排在True open drain引脚和OSC1/PA1,OSC2/PA2引脚上(前者无法输出高电平,后者的内部结构与一般IO口不同,不适宜作为按键检测脚使用)


三、软件分析

MCU需要资源

1个16位定时器 (用于采集按键信号: 测量RC充放电时间)
1个8位定时器 (主要作为后处理的时基信号)

资料与固件代码下载地址

主函数(main)
void main(void)
{
    volatile u16 temp;

    CLK_HSICmd(ENABLE);//使能HSI
    CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);//
    CLK_SYSCLKConfig(CLK_PRESCALER_HSIDIV1);//主频16M
    Delay(10000);  

    TSL_Init(); //按键库初始化
    Extra_Init();


    while(1) 
    { 
        temp = uMainCounting;
        TSL_Action();//获取按键状态
        Runing_Session[0] = uMainCounting - temp;


        temp = uMainCounting;
        Key_State_Machine();
        Runing_Session[1] = uMainCounting - temp;
    }
}

初始化触摸固件库
void TSL_Init(void)
{

  disableInterrupts();

  DetectionIntegrator = DETECTION_INTEGRATOR_DEFAULT;
  EndDetectionIntegrator = END_DETECTION_INTEGRATOR_DEFAULT;
  ECSTimeStep = ECS_TIME_STEP_DEFAULT;
  ECSTemporization = ECS_TEMPO_DEFAULT;
  RecalibrationIntegrator = RECALIBRATION_INTEGRATOR_DEFAULT;
  DetectionTimeout = DTO_DEFAULT;

  ECS_K_Fast = ECS_IIR_KFAST_DEFAULT;
  ECS_K_Slow = ECS_IIR_KSLOW_DEFAULT;
  ECSTimeStepCounter = ECSTimeStep;
  ECSTempoCounter = 0;
  ECSTempoPrescaler = 0;

  TSL_IO_Init();

#if (RTOS_MANAGEMENT == 0)
  TSL_Timer_Init();
#endif

#if NUMBER_OF_SINGLE_CHANNEL_KEYS > 0
  TSL_SCKey_Init();
#endif
#if NUMBER_OF_MULTI_CHANNEL_KEYS > 0
  TSL_MCKey_Init();
#endif

  enableInterrupts();

  TSLState = TSL_IDLE_STATE;

}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章