本帖最后由 Bengor 于 2022-1-24 17:58 编辑
如果仅仅使用单路或几路触摸按键,我个人觉得官方的算法库太复杂了,所以自己写了一套单路触摸按键的代码。第一次接触芯旺的MCU,芯片规格书等技术文档相对简陋,摸索了一个多星期才写出来,测试了IO口、定时器和PWM等功能,代码有点乱,没来得及整理好。仅供大家讨论和参考,也欢迎大家指点一二。
这套代码可以检测触摸按下/松开和长按等状态,实现多种按键识别功能,可调整_Touch_Recognition的值来调节触摸灵敏度,可自适应环境变化定时调整电容触摸基准值。摘取部分代码如下,详细请看附件。
#define _TMR1_FD 5 //20us
#define _TMR0_FD 2 //10ms
#define _KeyDetectCounter 10 //count for key conform (double check)
#define _DCIntervalTime 50 //double click valid time 500ms, unit:10ms
#define _T0UserModeChange 300 //3s
#define _Time0_UpDate_CPS 30 //300ms
#define _Touch_Recognition 1000 //sensitivity of touch
//#define _Touch_Recognition 5000
typedef enum
{
_Key_Press,
_Key_Release
} __Key;
void Init()
{
OSCCTL = 0b01100000;//8MHz
P0LR = 0b00000000;
TR0 = 0b00011000; //set P0 port to input
PUR0 = 0b00000000; //pull up
IOCL = 0b00000000; //IOC
P1LR = 0b00000000;
TR1 = 0b00000100; //set P12 port to input
PUR1 = 0b00000000; //pull up
P2LR = 0b00000000;
TR2 = 0b00000100; //set P12 port to input
PUR2 = 0b00000000; //pull up
ANSEH = 0b00100010; //AN13 AN9
ANSEL = 0b00000000;
OPTR = 0b00000101; //1:64
T0 = 100; //5ms
PP1 = 250; //PWM 4K,TOP value 250
PWM1L = 0;
T1CTL = 0b00010001; //T1 enable, 1:2
CTCTL0 = 0b10101010; //touch enable channel p1.2
CTCTL1 = 0b01000000; //touch clk 1:8
CTCTL2 = 0b00000000; //single trigger
VDAC = 0b11110000; //0.8VDAC
VRES = 0b10000000; //0.65VDAC
VDACS = 0b01000000; //vref
VRECTL = 0b01010010; //Vref 2V, enable
// T3CTL = 0b11100000;//T3 enable, 1:8
T4CTL = 0b10010000; //T4 1:2 0.25us
T4H = 252;
T4L = 223;
TMR4_Start();
PCTL = 0b00011000; //IPEN enable
EIE2 = 0b10000000; //T3
EIE3 = 0b10000000; //T4
IP2 = 0b10000000; //T3 interrupt high
IP3 = 0b10000000; //T4 interrupt high
INTCTL = 0b00100000;
Interrupt_Enable();
}
void TMR0_Reload()
{
T0 = _TMR0_5MS; //5ms
}
void TouchReStart()
{
T3CLR = 1;
CTSTART = 1;
}
void TMR3_CLEAR()
{
T3CLR = 0;
}
uint16 GetTMR3Value()
{
uint16 tempValue;
tempValue = (T3H << 8) | T3L;
TMR3_CLEAR(); //clear the T3H and T3L for next CT detect
return tempValue;
}
//**********************
void TouchDetect()
{
if(Get_Raw_CTData_Flag == true)
{
Get_Raw_CTData_Flag = false;
Raw_CTData = GetTMR3Value();
Raw_CTData_Counter++;
New_CTData = New_CTData + Raw_CTData;
if(Raw_CTData_Counter >= 2)
{
if(Old_CTData == 0)
{
Old_CTData = New_CTData;
}
else if(New_CTData != Old_CTData)
{
if(New_CTData > Old_CTData)
{
Diff_CTData = New_CTData - Old_CTData;
if(Diff_CTData > _Touch_Recognition && GetKeyChangeFlag == true)
{
tempKey = _Key_Release;
Old_CTData = New_CTData;
T0_10ms_Update_CTData = 0;
}
else
{
if(tempKey != _Key_Press)
{
Old_CPS_UpDate();
}
}
}
else
{
Diff_CTData = Old_CTData - New_CTData;
if(Diff_CTData > _Touch_Recognition && GetKeyChangeFlag == true)
{
tempKey = _Key_Press;
Old_CTData = New_CTData;
T0_10ms_Update_CTData = 0;
}
else
{
Old_CPS_UpDate();
}
}
}
New_CTData = 0;
Raw_CTData_Counter = 0;
}
}
}
void KeyDetect()
{
if(Key != tempKey)
{
if(T0_5ms_Key >= 1) //5ms
{
T0_5ms_Key = 0;
tempCounter++;
}
if(tempCounter >= _KeyDetectCounter)
{
tempCounter = 0;
T0_10ms_Run_Delay = 0;
Key = tempKey;
if(Key == _Key_Press) //Key press
{
KeyChange = 1;
if(KeyClickCounter < 255)
{
KeyClickCounter++;
}
}
else //Key release
{
KeyChange = 2;
}
T0_10ms_KeyChanged = 0;
}
}
else
{
tempCounter = 0;
}
}
void KeyHandler()
{
if(T0_10ms_KeyChanged >= _DCIntervalTime)
KeyClickCounter = 0;
}
//double click
if(KeyChange == 1 && KeyClickCounter >= 2)
{
FunctionEntrance = 2; //go to double click function
KeyChange = 0;
KeyClickCounter = 0;
T0_10ms_KeyChanged = 0;
}
//single click
if(KeyChange == 2 && T0_10ms_KeyChanged >= _DCIntervalTime)
{
FunctionEntrance = 1; //go to single click function
KeyChange = 0;
KeyClickCounter = 0;
T0_10ms_KeyChanged = 0;
}
//Key LongPress
if(KeyChange == 1 && T0_10ms_KeyChanged >= _T0UserModeChange)
{
KeyChange = 0;
//put your long press function here
}
}
void Old_CPS_UpDate()
{
if(T0_10ms_Update_CTData >= _Time0_UpDate_CPS)
{
//calculate the average with the latest 20 CTData values
Old_CTData = (Old_CTData * 19/20) + (New_CTData/20);
T0_10ms_Update_CTData = 0;
}
}
void main()
{
Init();
__delay_ms(200);
while(1)
{
//****************************
if(T0_5ms_CTData >= 2) //start Touch module per 10ms
{
T0_5ms_CTData = 0;
TouchReStart(); //re-start Touch module
}
TouchDetect();
KeyDetect();
KeyHandler();
if(FunctionEntrance != 0)
{
if(FunctionEntrance == 1)
{
//put your single click function here
}
else
{
//put your double click function here
}
FunctionEntrance = 0;
}
}
}
|