主要参考资料:《赛元SC95F系列TouchKey MCU 应用指南v0.0.1.pdf》。资料包链接如下:
1.我下载时的地址:
SC95F8X1X触控资料
2.我转存的百度盘:[SC95F8X1X触控资料] 链接:https://pan.baidu.com/s/1FaoaZUbpgLb9LvdgFPGV7w?pwd=fnn7
提取码:fnn7
3.csdn下载 SC95F8X1X触控资料
先来看看资料包的内容:
触摸库分为2种(高可靠模式和高灵敏度模式),3个(高灵敏度有T1和T2两种),看看他们有什么区别:
通过上表的信息,我只用到一路触摸,我就选用了高灵敏度模式T1。因为T2至少要3个按键。
下面来看看配置文件的源码《S_TOUCHKEYCFG.H》:
//*************************************************************************************************
// Copyright (c) 深圳市赛元微电子有限公司
// 文件名称 : S_TouchKeyCFG.h
// 作者 :
// 模块功能 : 触控键配置文件
// 版本 : V0.1
// 更改记录 :
//************************************************************************************************
#ifndef __S_TOUCHKEYCFG_H__
#define __S_TOUCHKEYCFG_H__
#define SOCAPI_SET_TOUCHKEY_TOTAL 2 // 触摸按键总数
#define SOCAPI_SET_TOUCHKEY_CHANNEL 0x000000c0 // 1个bit对应的引脚
unsigned int code TKCFG[17] = {
1, // [0]应用类型(0-弹簧,1-隔空)
0, // [1]按键类型(0-单键,1-双键)
0, // [2]AirSeparationDistance 隔空距离
7, // [3]CONFIRMTOUCHCNT 确认按键次数:该参数决定触控算法运行的出键速度,出键速度与一轮按键扫描时间有关,若
// 扫描一轮按键需要 12MS,按键确认次数为5次,则按键需要的响应时间为5*12MS=60MS.
10, // [4]INIT_AUTO_UPDATE_TIME 初始化自动更新时间,这个意思可能是没有按键时,自动更新按键AD基值
3000, // [5]SET_KEY_CONTI_TIME 按键最长输出,单位为轮数.
//如果按键一直触摸,超过这个时间,就会取消按键有效状态,并把这时的AD当做新的按键AD基值。
300, // [6]SET_SYNC_UPDATE 动态更新基线时间:该参数用于处理按键浮起的更新速度,保持默认不改动
200, // [7]SET_UPDATE_SPEED 基线更新速度:该参数用于更新基线。保持默认不改动
2, // [8]AUTO_UPDATE_TIME 基线复位速度:该参数决定基线复位的速度。值越大,更新速度越慢,保持默认不改动
0, // [9]FilteredKValue 滤波 K值:保持默认不改动
0, // [10]SET_ANTIJAM 抗干扰设置:用于扫描时钟变频,有助于通过 EMI 测试,当项目有 EMI 测试要求,
// 需要选择打开 1:12bit。
4, // [11]BAUD
100, // [12]DwellTime 采样时间
10, // [13]SaveTime
65535, // [14]SaveTime
65535, // [15]SaveTime
10 // [16]NOISE
};
unsigned char code TKChannelCfg[SOCAPI_SET_TOUCHKEY_TOTAL][8]={
0x03, //SET_TOUCH_FREQ 时钟
0x18, //SET_RESOLUTION 分辨率
0x04, //SET_GAIN_CFG 增益
0x1f, //SCANTIME 扫描周期
0x1f, //SET_ICHA
0x05, //
0x0C, //FINGER_THRESHOLD_H 触摸阈值高字节
0xbe, //FINGER_THRESHOLD_L 触摸阈值低字节
0x03,0x18,0x04,0x1f,0x1f,0x05,0x05,0x3a,
};
#endif
我就更改了3个地方:
高灵敏度模式T1包含了2个库,区别在于库使用到的临时变量区间选择在哪个区域。我选用了Small。
SC95F8X1X_HighSensitive_Lib_T1_S_V0.0.2.LIB --- 使用Small模式编译,变量区间在data
SC95F8X1X_HighSensitive_Lib_T1_L_V0.0.2.LIB --- 使用Large模式编译,变量区间在xdata
把库文件添加到自己的工程中,下面4个文件:
这几个文件的官方介绍:
触摸库API函数接口说明:
触摸库使用流程图:
3.2.1 设置IO口为推挽输出,且输出高电平(我用了P31-TK6作为触摸口)
P3CON = B0011_1111; 设置P3.6,P3.7输入模式
P3PH = 0x00;
P31 = 1; // P31作为触控,配置成强推挽,输出1
3.2.2 在main函数中调用初始化函数TouchKeyInit
TouchKeyInit(); //调用库函数,初始化TouchKey
3.2.3 在main函数中,1ms扫描一次按键
void main(void)
{
...
TouchKeyInit();
...
while(1){
WDT_CLR ; //清看门狗
if(FlagTick_1ms){
FlagTick_1ms = 0;
#if CFG_TOUCH_BODY == 1
Sys_Scan(); // 扫描触摸按键
#endif
}
...
}
}
void Sys_Scan(void)
{
if(SOCAPI_TouchKeyStatus&0x80) //重要步骤2: 触摸键扫描一轮标志,是否调用TouchKeyScan()一定要根据此标志位置起后
{
SOCAPI_TouchKeyStatus &=0x7f; //重要步骤3: 清除标志位, 需要外部清除。
exKeyValueFlag = TouchKeyScan();
ChangeTouchKeyvalue(); //键值
TouchKeyRestart(); //启动下一轮转换
}
}
/**************************************************
*函数名称:void ChangeTouchKeyvalue(void)
*函数功能:键值转换函数
*入口参数:void
*出口参数:void
*功能说明:请参考触控库使用手册进行操作
**************************************************/
#define KEY_STAT_DELAY_TICK 15
#define KEY_UP_STAT_DELAY_TICK 15
unsigned char xdata bKeyIsDown; /// 记录前一个状态,累计10次确认
unsigned char xdata keyChangeDelay; /// 状态时间累计
void ChangeTouchKeyvalue(void)
{
if(exKeyValueFlag != 0x00000000) //有键按下
{
switch(exKeyValueFlag)
{
case 0x00000040:
if(!bKeyIsDown){ // 前一个状态是松开的,累计时间
keyChangeDelay++;
if(keyChangeDelay > KEY_STAT_DELAY_TICK){
keyChangeDelay = 0;
bKeyIsDown = 1;
FlagPeopleNotInBed = 0;
LED1 = 1;
}
}
break;
default: exKeyValueFlag = 0x00000000;
}
}else { //释放按键
if(bKeyIsDown){ // 前一个状态是按下的,累计时间
keyChangeDelay++;
if(keyChangeDelay > KEY_UP_STAT_DELAY_TICK){
keyChangeDelay = 0;
bKeyIsDown = 0;
LED1 = 0;
FlagPeopleNotInBed = 1;
}
}
}
}
我的应用有些特殊,我是在按摩椅系统中,用来检测人体是否到位。在按摩椅表层放置一根细长的导线。一开始,我把TKCFG[5]SET_KEY_CONTI_TIME 按键最长输出 设置为0xFFFF(默认为十进制3000),按键最长输出为8分钟左右,我需要按键能够持续输出30分钟。于是找到了触摸库文件《S_TouchKeyCFG.C》
/**************************************************
*函数名称:unsigned int TouchKeyScan(void)
*函数功能:检测按键接口
*入口参数:void
*出口参数:按键通道, 返回的是一个int , 通道数
*备注 :1, 调用触控库检测函数SensorKeyFlag()
2, 分析得出16个通道,哪个通道有按下,按下bit 位设置为1,否则为0
3, 检测是否需要立即更新baseline: 大于MAX_KEY_RESET_BASELINE 个按键按下时立即更新baseline
4, 双键或者单键按下时, 时间大于SetOneKeyPushResetTime()结果时更新baseline
**************************************************/
unsigned long int TouchKeyScan(void)
{
unsigned char t;
unsigned char MultipleCnt = 0;//按键计数
unsigned long int Keyvalue = 0;
unsigned long int KeyData = 0;
if(GetIsNeedUpdateBaseline() == 0) //检测是否需要更新baseline
{
Keyvalue = SensorKeyFlag(); //Sensor判断, 这里如果bMultiple = 1 表示中间有干扰 //分析按键,得出标准的16通道bit 位
for(t=0;t<CurrentChannelMax;t++)
{
Keyvalue = Keyvalue>>1;
if(TK_CY)
{
KeyData |= ((unsigned long int)0x01 << (CurrentChannel[t]));
MultipleCnt++;
}
}
if(MultipleCnt >= 2) //进入多按键处理
{
bMultiple = 1;
if(MultipleCnt >= SOCAPI_MAX_KEY_NUM_INVALID)
{
SetNeedUpdateBaseline(); // 立即更新baseline ,例如亚克力板盖上去
}
else
{
if(IsDoubleKeyOrSlideKey())
{
bMultiple = 0;
}
}
}
if(bMultiple == 0) //进入按键判断
{
if(KeyData != 0x0) //单个按键达到多长时间就update baseline ,松手检测
{
UpdateBaseLNum++;
}
else
{
UpdateBaseLNum = 0;
}
}
else
{
//考虑基线更新
MultipleLNum++;
KeyData = 0x00;
}
// if(UpdateBaseLNum > SetOneKeyPushResetTime()){ //按键超出最长输出时间更新基线
// SetNeedUpdateBaseline();
// UpdateBaseLNum = 0;
// }
if(MultipleLNum >SOCAPI_MAX_KEY_MUTIPLE) //干扰计数大于最大计数更新基线
{
SetNeedUpdateBaseline();
MultipleDealTpye = 1;
MultipleLNum = 0;
}
}
else
{
MultipleDeal(TKCFG[AUTO_UPDATE_TIME]); //基线复位处理
}
return KeyData;
}
注释掉的如下代码,就可以保证按键持续输出时间超过30分钟:
if(UpdateBaseLNum > SetOneKeyPushResetTime()) //按键超出最长输出时间更新基线
{
SetNeedUpdateBaseline();
UpdateBaseLNum = 0;
}