触摸按键零点追踪长按问题
<div class="blockcode"><blockquote>// 方案001// 功能说明
/*******************************************************
* 器件引脚功能说明封装图
* -----------------------------------------------------
* [ 上视图 - 引脚逻辑分布 ]
*
* ┌────────────────────┐
* 电池电压检测 ──┤1 16 ├─ 触摸按键 (TK)
* 电机电流检测 ──┤2 15 ├─ LED / 电解片电压检测
* 电机开关 ──┤3 14 ├─ LED
* 电解片电流检测 ─┤4 13 ├─ LED
* PWM-1MHz 输出─┤5 12 ├─ 电解片开关
* VCC (电源正)──┤6 11 ├─ 充电座检测
* ADC-VREF基准─┤7 10 ├─ 充电开关 (充电时ON)
* GND (电源地)──┤8 9 ├─ 充电锁控制 (充满/脱离锁住)
* └────────────────────┘
*
* -----------------------------------------------------
* 功能说明:
* 1. 电池电压检测:ADC通道采样,用于监控电池电压。
* 2. 充电座检测:底座接触检测信号,判断是否在充电底座上。
* 3. 电机开关:控制电机通断。
* 4. 电解片电流检测:ADC采样检测电解片实际工作电流。
* 5. PWM-1MHz:输出高频PWM信号(1MHz)驱动或调制用。
* 6. VCC:系统电源正极输入。
* 7. ADC-VREF:ADC参考电压输入端。
* 8. GND:电源地。
*
* 9.充电锁控制:充满或脱离底座时锁定充电接口。
* 10. 充电开关:充电过程中打开,非充电状态关闭。
* 11. 电机电流检测:检测电机工作电流,防止过流。
* 12. 电解片开关:控制电解片通断。
* 13~15. LED:指示灯输出端,用于状态指示。
* 15. 另作电解片电压检测输入。
* 16. TK:触摸按键输入通道。
*
*******************************************************/
// 头文件
#include "STC8Hxxx.h"
// 引脚定义
sbit LEDR = P3^4;
sbit LEDG = P3^5;
sbit LEDB = P3^6;
// 宏定义
#define MAIN_Fosc 30000000L // 定义主时钟串口波特率 300 ~ 4800
// 声明
// 数组
u16 xdata TK_cnt; // 按键计数值, 16位
u16 xdata TK_zero; // 按键0点值, 16位
// K0 K1 K2 K3 K4 K5 K6 K7 K8 K9 K10 K11 K12 K13 K14 K15
// 触摸后的变化值
u16 code T_KeyPress={ 1300,2000,900, 800, 900, 1000, 1100, 1400,1000,1200, 900,1200,750, 900, 1300,1800};
// 16个键对应的状态, 0为未触摸,1为触摸
u16 code T_KeyState={0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};
// 函数
void delay_ms(u8 ms);
void TouchKey_Init(void);
void Timer2_Init(void);
// 变量
bit B_TK_Lowpass; // 低通允许, 1允许, 0禁止
u8 i;
u8 read_cnt; // 读次数
u8 mode = 2; // 初始待机模式 0:休眠, 1:恢复, 2:待机, 3:工作
u16 j;
u16 KeyState; // 按键状态, 每个bit对应一个键, 1为按下, 0为释放
// 函数模块
// 描述: 延时函数
// 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
void delay_ms(u8 ms)
{
u16 i;
do
{
i = MAIN_Fosc / 10000;
while(--i) ;
}while(--ms);
}
// 触摸按键初始化
void TouchKey_Init(void)
{
u8 i, read_cnt;
// ==== 启用触摸通道 ====
TSCHEN1 = 0x00; // 关闭 TK0~TK7
TSCHEN2 = 0x80; // 启用 TK15 (bit7)
// ==== 触摸参数配置 ====
TSCFG1= (7<<4) + 6; // 时钟、采样参数,根据实际硬件调
TSCFG2= 1;
TSRT = 0x00;
// ==== 开启触摸中断 ====
IE2 |= 0x80;
// ==== 采样建立初始零点 ====
delay_ms(50);
B_TK_Lowpass = 0;
for(read_cnt=0; read_cnt<10; read_cnt++)
{
TSCTRL = (1<<7) + (1<<6);// 开始扫描
delay_ms(50);
}
for(i=0; i<16; i++) TK_zero = TK_cnt;
B_TK_Lowpass = 1;
KeyState = 0;
// ==== 设置TK15唤醒阈值 ====
TSTH15 = TK_zero - T_KeyPress/2;
}
// 20ms心跳
void Timer2_Init(void) // 20毫秒@30.000MHz
{
AUXR &= 0xFB; // 定时器时钟12T模式
T2L = 0xB0; // 设置定时初始值
T2H = 0x3C; // 设置定时初始值
AUXR |= 0x10; // 定时器2开始计时
IE2 |= 0x04; // 使能定时器2中断
}
// 主函数
void main(void)
{
P_SW2 |= 0x80; // 允许访问扩展寄存器xsfr
// 引脚初始化
P1M0 = (P1M0 & ~0x03) | 0x08; P1M1 = (P1M1 & ~0x08) | 0x03; // (P10 11) 高阻输入 (P13) 推挽输出
P5M0 |= 0x10; P5M1 &= ~0x10; // (P54) 推挽输出
P3M0 = 0x7b; P3M1 = 0x84; // P32 37 高阻输入 (P30 31 33 34 35 36) 推挽输出
LEDR = 0;
LEDG = 0;
LEDB = 0;
EA = 1;
// 函数初始化
Timer2_Init();
TouchKey_Init();
while (1)
{
// 休眠模式
if(mode == 0)
{
TSCTRL = (1<<3) + (1<<2); // 触摸唤醒使能
// 除去 外部中断唤醒以及TK唤醒 其他全部高阻输入 禁止数字输入 降低功耗
P1M0 &= ~0x0b; P1M1 |= 0x0b; P1IE &= ~0x0b;
P5M0 &= ~0x10; P5M1 |= 0x10; P5IE &= ~0x10;
P3M0 = 0x00; P3M1 = 0xff; P3IE &= ~0x7b;
PCON |= 0x02; // MCU 睡眠
mode = 1; // 唤醒后自动跳出
}
if(mode == 1)
{
TSCTRL = (1<<7) + (1<<3) + (1<<2); // 恢复TK扫描
// 引脚初始化
P1M0 = (P1M0 & ~0x03) | 0x08; P1M1 = (P1M1 & ~0x08) | 0x03; // (P10 11) 高阻输入 (P13) 推挽输出
P5M0 |= 0x10; P5M1 &= ~0x10; // (P54) 推挽输出
P3M0 = 0x7b; P3M1 = 0x84; // P32 37 高阻输入 (P30 31 33 34 35 36) 推挽输出
}
if(mode == 2)
{
}
if(mode == 3)
{
}
}
}
// 中断服务函数
// 描述: 触摸按键中断服务函数
void TKSU_ISR(void) interrupt TKSU_VECTOR
{
u8 j;
j = TSSTA2;
if(j & 0x40) // 数据溢出, 错误处理(略)
{
TSSTA2 |= 0x40; // 写1清零
}
if(j & 0x80) // 扫描完成
{
j &= 0x0f;
TSSTA2 |= 0x80; // 写1清零
if(!B_TK_Lowpass) TK_cnt = TSDAT; // 保存某个通道的读数 1.1us @24MHz
// 保存某个通道的读数 1/2低通滤波 4.6us @24MHz, 低通a=0.25, 未按键读数20000, 按键读数21600, 则要11个次采样点(100Hz采样110ms)读数才到21500
else TK_cnt = (TK_cnt >> 1) + (TSDAT >> 1);
}
}
// 20ms心跳
void Timer2_Isr(void) interrupt 12
{
TSCTRL = (1<<7) + (1<<6); // 开始扫描, 无平均
if(++read_cnt >= 3)
{
read_cnt = 0;
j = KeyState;
for(i=0; i<16; i++)
{
if(TK_zero > TK_cnt)
{
TK_zero--;
if((TK_zero - TK_cnt) >= T_KeyPress/2) KeyState |=T_KeyState;
else if((TK_zero - TK_cnt) <= T_KeyPress/3) KeyState &= ~T_KeyState;
}
else
{
KeyState &= ~T_KeyState;
if((TK_cnt - TK_zero) > 100) TK_zero += 100;
else TK_zero += 10;
}
}
// 触摸值判断
j = (j ^ KeyState) & KeyState;
B = (u8)j;
B = (u8)(j >> 8);
if(B7) LEDG = ~LEDG; // mode = 3; else mode = 2; // 触摸后开始工作 反之待机模式
}
}
参考了零点追踪的触摸按键 但是发现貌似只适合单点触摸
测试长按的时候会跳到绿光回到红光 看起来无法检测长按 可能是达到阈值以后触发之后就重置了
应该怎么能让它识别长按因为需要触摸按键一直按着才能工作 松开就不工作了
并且mode = 2 的时候触摸是正常的
一旦mode = 0 那么无法唤醒或者唤醒后绿灯不能正常开关
还有个问题
这里的数字输入关闭 当我在恢复引脚状态的时候需要处理它吗 零点追踪用于没有按键按下时修正缓慢飘移的零点
零点追踪例程不支持长按,程序需要修改
由于按下按键时键值的斜率大,缓慢漂移时键值的斜率小
斜率即单位时间内键值的变化量,可以使用定时器或其他方式计时,计算出单位时间内键值的变化量
可以根据键值的斜率判断是否按下,当按下时屏蔽零点追踪,只有在没按下时进行零点追踪,就可以避免长按被误判为漂移
触摸按键和ADC等模拟信号的IO,初始化时直接关闭数字输入,不需要再打开 DebugLab 发表于 2025-11-2 20:35
零点追踪用于没有按键按下时修正缓慢飘移的零点
零点追踪例程不支持长按,程序需要修改
由于按下按键时键值 ...
也就是因为进行零点追踪导致无法使用长按
那么当按下时屏蔽零点追踪,只有在没按下时进行零点追踪这个触摸按键方式有案例吗?
触摸按键 ADC 比较器 外部中断这些都可以在初始化的时候就直接关闭数字输入
那么例如推挽输出的引脚 需要初始化为推挽输出 然后关闭数字输入吗?
// 方案001-2
// 功能说明
// 头文件
#include "STC8Hxxx.h"
// 引脚定义
sbit LEDR = P3^4;
sbit LEDG = P3^5;
sbit LEDB = P3^6;
// 宏定义
#define MAIN_Fosc 30000000L // 定义主时钟串口波特率 300 ~ 4800
// 声明
// 数组
u16 xdata TK_last;
u16 xdata TK_slope;
u16 xdata TK_Pressed;
u16 xdata TK_cnt; // 按键计数值, 16位
u16 xdata TK_zero; // 按键0点值, 16位
// K0 K1 K2 K3 K4 K5 K6 K7 K8 K9 K10 K11 K12 K13 K14 K15
// 触摸后的变化值
u16 code T_KeyPress={ 1300,2000,900, 800, 900, 1000, 1100, 1400,1000,1200, 900,1200,750, 900, 1300,1800};
// 16个键对应的状态, 0为未触摸,1为触摸
u16 code T_KeyState={0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};
// 函数
void delay_ms(u8 ms);
void TouchKey_Init(void);
void Timer2_Init(void);
void Ext_Init(void);
void IO_Sleep(void);
void IO_Wakeup(void);
// 变量
bit B_TK_Lowpass; // 低通允许, 1允许, 0禁止
u8 i;
u8 read_cnt; // 读次数
u8 mode = 0; // mode 0:休眠/恢复模式 2:待机模式 3:工作模式
u16 j;
u16 KeyState; // 按键状态, 每个bit对应一个键, 1为按下, 0为释放
// 函数模块
// ms延时函数-自适应主时钟
void delay_ms(u8 ms)
{
u16 i;
do
{
i = MAIN_Fosc / 10000;
while(--i) ;
}
while(--ms);
}
// 触摸初始化
void TouchKey_Init(void)
{
u8 i, read_cnt;
TSCHEN1 = 0x00;
TSCHEN2 = 0x80; // 启用TK15
TSCFG1= (7<<4) + 6;
TSCFG2= 1;
TSRT = 0x00;
IE2 |= 0x80;
delay_ms(50);
B_TK_Lowpass = 0;
for(read_cnt=0; read_cnt<10; read_cnt++)
{
TSCTRL = (1<<7) + (1<<6);
delay_ms(50);
}
for(i=0; i<16; i++)
{
TK_zero = TK_cnt;
TK_last = TK_cnt;
TK_Pressed = 0;
}
B_TK_Lowpass = 1;
KeyState = 0;
TSTH15 = TK_zero - T_KeyPress/2;
}
// 20ms心跳
void Timer2_Init(void) // 20毫秒@30.000MHz
{
AUXR &= 0xFB; // 定时器时钟12T模式
T2L = 0xB0; // 设置定时初始值
T2H = 0x3C; // 设置定时初始值
AUXR |= 0x10; // 定时器2开始计时
IE2 |= 0x04; // 使能定时器2中断
}
// 外部中断0配置
void Ext_Init(void)
{
IT0 = 0; // INT0(P3.2)上升沿+下降沿中断
EX0 = 1; // 使能INT0中断
}
// IO休眠
void IO_Sleep(void)
{
// 休眠模式
P5M0 &= ~0x10; P5M1 |= 0x10; P5IE &= ~0x10;
P1M0 &= ~0x0b; P1M1 |= 0x0b; P1IE &= ~0x0b;
P3M0 = 0x00; P3M1 = 0xff; P3IE &= ~0x7b;
// 引脚状态
LEDR = 0; LEDG = 0;LEDB = 0;
// 允许 TK15 唤醒 MCU,其它按键可根据需要修改
TSCHEN1 = 0x00; // TK0~TK7 禁用唤醒
TSCHEN2 = 0x80; // TK8~TK15 允许 TK15 唤醒
TSCTRL= (1<<3) + (1<<2); // 数字比较器 + 低功耗唤醒使能
}
// IO唤醒
void IO_Wakeup(void)
{
// 恢复模式
P3M0 = 0x7b; P3M1 = 0x84; // P32 37 高阻输入 (P3 0 31 33 34 35 36) 推挽输出
P5M0 |= 0x10; P5M1 &= ~0x10; // (P54) 推挽输出
P1M0 = (P1M0 & ~0x03) | 0x08; P1M1 = (P1M1 & ~0x08) | 0x03; // (P10 11) 高阻输入 (P13) 推挽输出
// 引脚状态
LEDR = 0; LEDG = 0;LEDB = 0;
}
// 主函数
void main(void)
{
P_SW2 |= 0x80; // 允许访问扩展寄存器xsfr
IO_Wakeup(); // IO唤醒
EA = 1; // 开总中断
IRCDB = 0x10; // 配置唤醒
IAP_TPS = 0x30; // 30Mhz晶振
// 启动32k内部振荡器,用于触摸按键低功耗唤醒
IRC32KCR = 0x80;
while (!(IRC32KCR & 1)); // 等待时钟稳定
// 函数初始化
Ext_Init(); // 外部中断0初始化
TouchKey_Init(); // 触摸按键初始化--No.1
Timer2_Init(); // 定时器2初始化--No.2
// 主循环
while(1)
{
// 休眠/恢复模式
if(mode == 0)
{
IO_Sleep(); // IO休眠
// 寄存器初始化
PCON = 0x02; // MCU进入掉电模式
IO_Wakeup(); // IO唤醒
mode = 2; // 自动跳转待机
}
// 待机模式
if(mode == 2)
{
LEDR = 1;
LEDG = 0;
}
// 工作模式
if(mode == 3)
{
LEDR = 0;
LEDG = 1;
}
}
}
// 中断服务函数
// 外部中断0服务函数
void INT0_Isr(void) interrupt 0
{
}
// 描述: 触摸按键中断服务函数
void TKSU_ISR(void) interrupt TKSU_VECTOR
{
u8 j;
j = TSSTA2;
if(j & 0x40) // 数据溢出, 错误处理(略)
{
TSSTA2 |= 0x40; // 写1清零
}
if(j & 0x80) // 扫描完成
{
j &= 0x0f;
TSSTA2 |= 0x80; // 写1清零
if(!B_TK_Lowpass) TK_cnt = TSDAT; // 保存某个通道的读数 1.1us @24MHz
// 保存某个通道的读数 1/2低通滤波 4.6us @24MHz, 低通a=0.25, 未按键读数20000, 按键读数21600, 则要11个次采样点(100Hz采样110ms)读数才到21500
else TK_cnt = (TK_cnt >> 1) + (TSDAT >> 1);
}
}
// 定时器2中断(20ms心跳)
void Timer2_Isr(void) interrupt 12
{
TSCTRL = (1<<7) + (1<<6);
if(++read_cnt >= 3)
{
read_cnt = 0;
j = KeyState;
for(i=0; i<16; i++)
{
if (TK_cnt > TK_last)
TK_slope = TK_cnt - TK_last;
else
TK_slope = TK_last - TK_cnt;
TK_last = TK_cnt;
if (TK_slope > 200)
TK_Pressed = 1;
else if ((TK_zero > TK_cnt) ?
((TK_zero - TK_cnt) < T_KeyPress/4) :
((TK_cnt - TK_zero) < T_KeyPress/4))
TK_Pressed = 0;
if (TK_Pressed)
{
if ((TK_zero - TK_cnt) >= T_KeyPress/2)
KeyState |=T_KeyState;
}
else
{
if (TK_zero > TK_cnt)
TK_zero--;
else if (TK_zero < TK_cnt)
TK_zero++;
if ((TK_zero - TK_cnt) <= T_KeyPress/3)
KeyState &= ~T_KeyState;
}
}
}
// 扫描触摸按键判断
// 按下按键
if (KeyState & T_KeyState)
{
mode = 3; // 工作模式
}
// 松开按键
else
{
mode = 2; // 待机模式
}
}
现在这个程序的问题是
进入省电模式的时候 功耗达到了0.568mA 原来没有配置触摸按键唤醒的时候只有0.340mA
为什么功耗会变这么高 命名已经全部都关掉了
然后外部中断唤醒是正常的 但是触摸按键唤醒的时候会有问题 触碰以后 会变成红灯亮一下 然后 绿灯常亮 触摸按键功能不起作用了 HyunYong_7782 发表于 2025-11-3 02:05
也就是因为进行零点追踪导致无法使用长按
那么当按下时屏蔽零点追踪,只有在没按下时进行零点追踪这个触 ...
长按和零点追踪共存的例程暂无
外部中断是数字功能,且是输入,不能关闭数字输入
推挽输出可以关闭数字输入功能
关闭数字输入是为了防止省电模式时IO处于临界状态会有额外的功耗 HyunYong_7782 发表于 2025-11-3 12:02
现在这个程序的问题是
进入省电模式的时候 功耗达到了0.568mA 原来没有配置触摸按键唤醒的时候只有0.34 ...
300多μA和500多μA好像都不太正常,检查省电模式时IO是否有电流,IO要设置为没有电流的状态,注意外部的上下拉电阻 DebugLab 发表于 2025-11-4 06:28
长按和零点追踪共存的例程暂无
外部中断是数字功能,且是输入,不能关闭数字输入
推挽输出可以关闭数字输 ...
长按和外部中断的数字输入已经打开了 // 方案001-2
// 头文件
#include "STC8Hxxx.h"
// 引脚定义
sbit LEDR = P3^4;
sbit LEDG = P3^5;
sbit LEDB = P3^6;
sbit base = P3^2;
// 宏定义
#define MAIN_Fosc 30000000L // 定义主时钟串口波特率 300 ~ 4800
// 声明
// 数组
u16 xdata TK_last;
u16 xdata TK_slope;
u16 xdata TK_Pressed;
u16 xdata TK_cnt; // 按键计数值, 16位
u16 xdata TK_zero; // 按键0点值, 16位
// K0 K1 K2 K3 K4 K5 K6 K7 K8 K9 K10 K11 K12 K13 K14 K15
// 触摸后的变化值
u16 code T_KeyPress={ 1300,2000,900, 800, 900, 1000, 1100, 1400,1000,1200, 900,1200,750, 900, 1300,1800};
// 16个键对应的状态, 0为未触摸,1为触摸
u16 code T_KeyState={0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};
// 函数
void delay_ms(u8 ms);
void TouchKey_Init(void);
void Timer2_Init(void);
void Ext_Init(void);
void IO_Sleep(void);
void IO_Wakeup(void);
// 变量
bit B_TK_Lowpass; // 低通允许, 1允许, 0禁止
bit base_now; // 充电底座状态 1为充电底座上, 0为非充电底座上
u8 i;
u8 read_cnt; // 读次数
u8 mode = 2; // mode 0:休眠/恢复模式 2:待机模式 3:工作模式
u16 j;
u16 KeyState; // 按键状态, 每个bit对应一个键, 1为按下, 0为释放
u16 count;
// 函数模块
// ms延时函数-自适应主时钟
void delay_ms(u8 ms)
{
u16 i;
do
{
i = MAIN_Fosc / 10000;
while(--i) ;
}
while(--ms);
}
// 触摸初始化
void TouchKey_Init(void)
{
u8 i, read_cnt;
TSCHEN1 = 0x00;
TSCHEN2 = 0x80; // 启用TK15
TSCFG1= (7<<4) + 6;
TSCFG2= 1;
TSRT = 0x00;
IE2 |= 0x80;
delay_ms(50);
B_TK_Lowpass = 0;
for(read_cnt=0; read_cnt<10; read_cnt++)
{
TSCTRL = (1<<7) + (1<<6);
delay_ms(50);
}
for(i=0; i<16; i++)
{
TK_zero = TK_cnt;
TK_last = TK_cnt;
TK_Pressed = 0;
}
B_TK_Lowpass = 1;
KeyState = 0;
TSTH15 = TK_zero - T_KeyPress/2;
}
// 20ms心跳
void Timer2_Init(void) // 20毫秒@30.000MHz
{
AUXR &= 0xFB; // 定时器时钟12T模式
T2L = 0xB0; // 设置定时初始值
T2H = 0x3C; // 设置定时初始值
AUXR |= 0x10; // 定时器2开始计时
IE2 |= 0x04; // 使能定时器2中断
}
// 外部中断0配置
void Ext_Init(void)
{
IT0 = 0; // INT0(P3.2)上升沿+下降沿中断
EX0 = 1; // 使能INT0中断
}
// IO休眠
void IO_Sleep(void)
{
// 休眠模式
P5M0 &= ~0x10; P5M1 |= 0x10; P5IE &= ~0x10;
P1M0 &= ~0x0b; P1M1 |= 0x0b; P1IE &= ~0x0b;
P3M0 = 0x00; P3M1 = 0xff; P3IE &= ~0x7b;
// 引脚状态
LEDR = 0; LEDG = 0;LEDB = 0;
// 允许 TK15 唤醒 MCU,其它按键可根据需要修改
TSCHEN1 = 0x00; // TK0~TK7 禁用唤醒
TSCHEN2 = 0x80; // TK8~TK15 允许 TK15 唤醒
TSCTRL= (1<<3) + (1<<2); // 数字比较器 + 低功耗唤醒使能
}
// IO唤醒
void IO_Wakeup(void)
{
// 恢复模式
P3M0 = 0x7b; P3M1 = 0x84; // P32 37 高阻输入 (P3 0 31 33 34 35 36) 推挽输出
P5M0 |= 0x10; P5M1 &= ~0x10; // (P54) 推挽输出
P1M0 = (P1M0 & ~0x03) | 0x08; P1M1 = (P1M1 & ~0x08) | 0x03; // (P10 11) 高阻输入 (P13) 推挽输出
// 引脚状态
LEDR = 0; LEDG = 0;LEDB = 0;
}
// 主函数
void main(void)
{
P_SW2 |= 0x80; // 允许访问扩展寄存器xsfr
IO_Wakeup(); // IO唤醒
EA = 1; // 开总中断
IRCDB = 0x10; // 配置唤醒
IAP_TPS = 0x30; // 30Mhz晶振
// 启动32k内部振荡器,用于触摸按键低功耗唤醒
IRC32KCR = 0x80;
while (!(IRC32KCR & 1)); // 等待时钟稳定
// 函数初始化
Ext_Init(); // 外部中断0初始化
TouchKey_Init(); // 触摸按键初始化--No.1
Timer2_Init(); // 定时器2初始化--No.2
// 主循环
while(1)
{
if(base == 1) // 在充电底座上
{
base_now = 1;
LEDR = 0;
LEDG = 0;
}
else // 不在充电底座上
{
base_now = 0;
// 休眠/恢复模式
if(mode == 0)
{
IO_Sleep(); // IO休眠
// 寄存器初始化
PCON = 0x02; // MCU进入掉电模式
IO_Wakeup(); // IO唤醒
mode = 2; // 自动跳转待机
}
// 待机模式
if(mode == 2)
{
LEDR = 1;
LEDG = 0;
}
// 工作模式
if(mode == 3)
{
LEDR = 0;
LEDG = 1;
}
}
}
}
// 中断服务函数
// 外部中断0服务函数
void INT0_Isr(void) interrupt 0
{
}
// 描述: 触摸按键中断服务函数
void TKSU_ISR(void) interrupt TKSU_VECTOR
{
u8 j;
j = TSSTA2;
if(j & 0x40) // 数据溢出, 错误处理(略)
{
TSSTA2 |= 0x40; // 写1清零
}
if(j & 0x80) // 扫描完成
{
j &= 0x0f;
TSSTA2 |= 0x80; // 写1清零
if(!B_TK_Lowpass) TK_cnt = TSDAT; // 保存某个通道的读数 1.1us @24MHz
// 保存某个通道的读数 1/2低通滤波 4.6us @24MHz, 低通a=0.25, 未按键读数20000, 按键读数21600, 则要11个次采样点(100Hz采样110ms)读数才到21500
else TK_cnt = (TK_cnt >> 1) + (TSDAT >> 1);
}
}
// 定时器2中断(20ms心跳)
void Timer2_Isr(void) interrupt 12
{
if(base_now == 0) // 不在充电底座上才能判断触摸按键
{
// =========== 触摸按键数据读取 =========== //
TSCTRL = (1<<7) + (1<<6);
if(++read_cnt >= 3)
{
read_cnt = 0;
j = KeyState;
for(i=0; i<16; i++)
{
if (TK_cnt > TK_last)
TK_slope = TK_cnt - TK_last;
else
TK_slope = TK_last - TK_cnt;
TK_last = TK_cnt;
if (TK_slope > 200)
TK_Pressed = 1;
else if ((TK_zero > TK_cnt) ?
((TK_zero - TK_cnt) < T_KeyPress/4) :
((TK_cnt - TK_zero) < T_KeyPress/4))
TK_Pressed = 0;
if (TK_Pressed)
{
if ((TK_zero - TK_cnt) >= T_KeyPress/2)
KeyState |=T_KeyState;
}
else
{
if (TK_zero > TK_cnt)
TK_zero--;
else if (TK_zero < TK_cnt)
TK_zero++;
if ((TK_zero - TK_cnt) <= T_KeyPress/3)
KeyState &= ~T_KeyState;
}
}
}
// =========== 触摸按键数据读取 =========== //
// ========== 触摸按键扫描判断 ========== //
// 按下按键
if (KeyState & T_KeyState)
{
count = 0;
mode = 3; // 工作模式
}
// 松开按键
else
{
count++;
if(count >= 150)
{
count = 0;
mode = 0; // 进入休眠
}
else
{
mode = 2; // 待机模式
}
}
// ========== 触摸按键扫描判断 ========== //
}
}
我现在是做成这样 问题出现在触摸按键无法唤醒,只有外部中断引脚 base可以唤醒 DebugLab 发表于 2025-11-4 06:30
300多μA和500多μA好像都不太正常,检查省电模式时IO是否有电流,IO要设置为没有电流的状态,注意外部的 ...
我现在用的STC8H1K08T
会不会是P54不支持关闭数字输入引脚所导致的
页:
[1]
2