【新版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> :handshake:handshake :time:{:1_102:}:handshake{:1_103:}
页:
[1]