yang_alex 发表于 2018-4-24 23:21

【新版CH554评测】---3、触摸按键例程学习及验证

<div class='showpostmsg'> 本帖最后由 yang_alex 于 2018-4-24 23:21 编辑

       通过阅读CH554器件手册,可以了解到CH554 芯片提供了电容检测模块及相关的定时器,具有 6 个输入通道,自电容方式可以支持最多6个触摸按键,互电容方式可以支持最多15个触摸按键。

       新评估板的电容触摸按键例程是通过自电容方式检测按键。使用了P14、P15、P16、P17四个通道。对应输入通道如下表。
      
       器件手册的第17章第3节描述了电容触摸按键的检测步骤,电容触摸按键例程也是按此编写程序的。
      

使用一个MCU的功能,首先要对它进行初始化。电容触摸按键初始化函数在TouchKey.C文件中。

照前面电容触摸按键的检测步骤要求,被选择的输入通道,其所在 GPIO 引脚必须设置为高阻输入模式、或者开漏输出模式并且处于输出 1 的状态(相当于高阻输入),Pn_DIR_PU=0。所以在电容触摸按键初始化函数
UINT8 TK_Init( UINT8 channel , UINT8 queryFreq, UINT8 ie )
中,把相关引脚设置成高阻输入模式、或者开漏输出模式
         P1_DIR_PU &= ~channel;
      P1_MOD_OC &= ~channel;
   电容检测定时器的周期选择有2种,通过Touch-Key 控制寄存器(TKEY_CTRL)的bTKC_2MS 位选择:0-1mS;1-2mS。
   

   在程序中就是通过电容触摸按键初始化函数的参数 queryFreq来设置(0-1mS;1-2mS)。
   UINT8 TK_Init( UINT8 channel , UINT8 queryFreq, UINT8 ie )
   在初始化过程中,对使用的电容触摸按键通道采样初始值,这个初始值是采样几次进行平均。
         /* Get Key_FreeBuf. Save the data in flash or macro define. */
      /* DO NOT get Key_FreeBuf in Mass Production. */
      for ( i = 0; i < TOUCH_NUM; i++ )
      {
                sum = 0;
                j = SAMPLE_TIMES;
                TK_SelectChannel( i );
//                TKEY_CTRL |= TK_Code;
                while( j-- )
                {
                        OverTime = 0;
                        while( ( TKEY_CTRL & bTKC_IF ) == 0 )
                        {
                              if( ++OverTime == 0 )
                              {
                                        return FAIL;
                              }
                        }
                        sum += TKEY_DAT;                                                                                                      /**/
                }
                Key_FreeBuf = sum / SAMPLE_TIMES;
                printf( "Key_FreeBuf[%d]=%d\t", (UINT16)(i), (UINT16)Key_FreeBuf );
      }
   采样次数SAMPLE_TIMES在TouchKey.H头文件中定义          #define                SAMPLE_TIMES      (0x05)
   电容触摸按键是使用中断模式工作的,所以在初始化函数末尾,打开电容触摸按键中断。
          if( ie != 0 )               /* Enable interrupt ?*/      
       {
                IE_TKEY = 1;                                                                                                   
      }      
    至此,电容触摸按键初始化工作完成。
    接下来,确定我们使用那几个通道。参见第一个表格
   UINT8 TK_SelectChannel( UINT8 ch )
{
      if ( ch <= TOUCH_NUM )
      {
                TKEY_CTRL = ( TKEY_CTRL & 0XF8) | TK_Code;
                return SUCCESS;
      }
      return      FAIL;
}
   这里的 TOUCH_NUM 是在下面这里定义的。
   UINT8         TK_Code = {                /* Arrange the input channel */                        
//      0x01, 0x02,                                                      /* CH0 CH1 */
      0x03, 0x04,                                                          /* CH2 CH3 */
      0x05, 0x06                                                         /* CH4 CH5 */
};      
   电容触摸按键是使用中断模式工作的,所以接下来记得把中断打开。EA = 1;                        /* Enable global interrupt. */      CH554检测到电容触摸按键的中断后,进入电容触摸按键中断服务程序,里边把检测到的值和门槛值进行比较,(这里要注意两点。1、前面讲到的电容检测步骤第4条:进入中断程序中,首先从 TKEY_DAT 中读取当前通道的电容数据,并屏蔽最高位 bTKD_CHG,该
数据是相对值,与电容量成反比,当触摸按键按下时的数据比未按下时的数据小。2、用步骤(4)读取的 TKEY_DAT 数据与之前保存的该通道无按键时的数据比较,判断是否电容变化和是否有按键被按下。),并选择下一通道以便继续扫描按键。
void TK_int_ISR( void ) interrupt INT_NO_TKEY using 1
{
      static UINT8 ch = 0;
      UINT16 KeyData;

      KeyData = TKEY_DAT;
      
      if( KeyData < ( Key_FreeBuf - TH_VALUE ) )
      {
                Touch_IN |=1 << ( TK_Code - 1 );
      }
      
//      printf( "ch[%d]=%d\t", (UINT16)(TK_Code - 1), (UINT16)KeyData );

      if( ++ch >= TOUCH_NUM )
      {
//                printf("\n");
                ch = 0;
      }      
      TK_SelectChannel( ch );
}
   主程序在死循环中判断哪个通道发生按键动作:      while ( 1 )
      {
//                if( TK_Measure() != SUCCESS )                                        /* For Query Mode. */
//                {
//                        printf("ERROR\n");
//                }
               
                if( Touch_IN != 0 )
                {
                        if( Touch_IN & CH0 )
                        {
                              printf("CH0 is pressed.\n");
                        }
                        if( Touch_IN & CH1 )
                        {
                              printf("CH1 is pressed.\n");
                        }
                        if( Touch_IN & CH2 )
                        {
                              printf("CH2 is pressed.\n");
                        }
                        if( Touch_IN & CH3 )
                        {
                              printf("CH3 is pressed.\n");
                        }
                        if( Touch_IN & CH4 )
                        {
                              printf("CH4 is pressed.\n");
                        }
                        if( Touch_IN & CH5 )
                        {
                              printf("CH5 is pressed.\n");
                        }
                        Touch_IN = 0;
                }
      }

这里有几个地方需要注意一下:1、由于在电容触摸按键初始化时检测了按键上电容的初始值,并在后续检测中进行比较。所以要注意上电时,电容触摸按键要保持和后续检测按键时一样的状态。换句话说就是不要在上电时在电容触摸按键上覆盖东西,但在使用按键检测是,这个东西又被移走了。

2、电容触摸按键的门槛值是可以设置的。门槛值TH_VALUE在TouchKey.H头文件中定义          #define                TH_VALUE                (100)

运行结果如下:

看样子需要加个去重复按键的机制:lol


此内容由EEWORLD论坛网友yang_alex原创,如需转载或用于商业用途需征得作者同意并注明出处












</div><script>                                        var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;"   style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
                                       
                                        if(parseInt(discuz_uid)==0){
                                                                                                (function($){
                                                        var postHeight = getTextHeight(400);
                                                        $(".showpostmsg").html($(".showpostmsg").html());
                                                        $(".showpostmsg").after(loginstr);
                                                        $(".showpostmsg").css({height:postHeight,overflow:"hidden"});
                                                })(jQuery);
                                        }                </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>

沁恒USB单片机 发表于 2018-4-25 08:14

:handshake:handshake

zwei9 发表于 2018-4-27 10:43

:time:{:1_102:}:handshake{:1_103:}
页: [1]
查看完整版本: 【新版CH554评测】---3、触摸按键例程学习及验证