- <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]; // 按键计数值, 16位
- u16 xdata TK_zero[16]; // 按键0点值, 16位
- // K0 K1 K2 K3 K4 K5 K6 K7 K8 K9 K10 K11 K12 K13 K14 K15
- // 触摸后的变化值
- u16 code T_KeyPress[16]={ 1300, 2000, 900, 800, 900, 1000, 1100, 1400, 1000, 1200, 900, 1200, 750, 900, 1300, 1800};
- // 16个键对应的状态, 0为未触摸,1为触摸
- u16 code T_KeyState[16]={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[i] = TK_cnt[i];
- B_TK_Lowpass = 1;
- KeyState = 0;
-
- // ==== 设置TK15唤醒阈值 ====
- TSTH15 = TK_zero[15] - T_KeyPress[15]/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[j] = TSDAT; // 保存某个通道的读数 1.1us @24MHz
- // 保存某个通道的读数 1/2低通滤波 4.6us @24MHz, 低通a=0.25, 未按键读数20000, 按键读数21600, 则要11个次采样点(100Hz采样110ms)读数才到21500
- else TK_cnt[j] = (TK_cnt[j] >> 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[i] > TK_cnt[i])
- {
- TK_zero[i]--;
- if((TK_zero[i] - TK_cnt[i]) >= T_KeyPress[i]/2) KeyState |= T_KeyState[i];
- else if((TK_zero[i] - TK_cnt[i]) <= T_KeyPress[i]/3) KeyState &= ~T_KeyState[i];
- }
- else
- {
- KeyState &= ~T_KeyState[i];
- if((TK_cnt[i] - TK_zero[i]) > 100) TK_zero[i] += 100;
- else TK_zero[i] += 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 那么无法唤醒或者唤醒后绿灯不能正常开关
|