|
|
本帖最后由 慕名而来 于 2026-8-17 13:26 编辑
这个古老的电磁炉应该是国内可见家用电磁炉年代的第一梯队的老物件了,五年前就因为面板按键膜破洞无法使用了,貌似那时锅仔片的薄膜开关还没有普及吧,这货只是隔着面板膜按动轻触开关,久了没有不破露的,当时淘宝没有找到替换的键盘膜就用外接按键来凑合用了,最近没啥玩的、手痒难耐就对它下手了,编程时在豆包各种拐带、各种坑后弄了好久仍然无法实现控制目标,无奈收拢心神分析STC的官方例程最终完成了改造,这次改造主要工程就是DIY一个按键面板,买了2mm厚度的亚克力板连锯带磨也没费多少功夫,倒是三个按键的体现比较费劲但喷了漆以后面板完成效果还是不错的,没有想到的是用的粘接胶竟然把油漆给融掉了,使得最终的成品面目全非惨不忍睹,既然使用功能没问题了也不再纠结外观了,凑合用了。
这可能是多年来所有制作中最不成功的一次!!!
虽然外观完败,但触摸功能还是很稳定的,源程序在此分享供坛友交流。
原机有6个按键,分别是电源开关键,大火力键,增加键,中火力键,减少键,小火力键,改造后保留减少、电源开关、增加三个按键,使用感觉更加简单、快捷,触摸灵敏度适中,无失控、不乱跳。
声明:程序根据STC官方代码改编。使用带有触摸功能的单片机STC8H1K08T,下载程序时配置系统时钟22.1184MHz
程序原创:wannenggong,由豆包AI辅助整理、标注
- #include <STC8H.h>
- #include "delay.h"
- #include "STC8_uart.h"
- //----输出引脚定义-----------------------------
- sbit power = P3 ^ 2; // 电源开关
- sbit high = P3 ^ 3; // 强火力
- sbit enhance = P3 ^ 4; // 增强
- sbit medium = P3 ^ 5; // 中火力
- sbit weaken = P3 ^ 6; // 减弱
- sbit Small = P3 ^ 7; // 小火力
- //----本地变量声明-----------------------------
- u16 xdata TK_cnt[8]; // 按键计数值, 16位
- u16 xdata TK_zero[8]; // 按键0点值, 16位
- u16 KeyState; // 按键状态, 每个bit对应一个键, 1为按下, 0为释放
- u8 read_cnt; // 读次数
- bit B_TK_Lowpass; // 低通允许, 1允许, 0禁止
- bit key_power = 0;
- u8 tk_freeze[8]; // 新增:对应TK0~TK7,1=按下冻结零点,0=空闲允许零点跟踪
- static u8 n, kn;
- //---------------------------------------------
- // K0 K1 K2 K3 K4 K5 K6 K7
- u16 code T_KeyPress[8] = { 0, 0, 0, 0, 50, 150, 350, 0 }; //触摸后的变化值
- u16 code T_KeyState[8] = { 0, 0, 0, 0, 0x0010, 0x0020, 0x0040, 0 }; //8个键对应的状态, 0为未触摸,1为触摸
- //----按键控制输出函数-------------------------
- //模拟轻触按键控制
- void output_control()
- {
- switch(n)
- {
- case 0:
- Small = 0;//IO口输出高电平、模拟按键按下一次
- delay_ms(200);
- Small = 1;//IO输出恢复低电平空闲状态
- break;
- case 1:
- weaken = 0;
- delay_ms(200);
- weaken = 1;
- break;
- case 2:
- medium = 0;
- delay_ms(200);
- medium = 1;
- break;
- case 3:
- enhance = 0;
- delay_ms(200);
- enhance = 1;
- break;
- case 4:
- high = 0;
- delay_ms(200);
- high = 1;
- break;
- case 5:
- power = 0; //发送脉宽100ms的低电平脉冲模拟轻触按键按下一次后抬起
- delay_ms(200);
- power = 1;
- if(key_power == 0) //当前是关机 → 本次是【开机】
- {
- delay_ms(250);
- n = 2;
- medium = 0;
- delay_ms(200);
- medium = 1;
- key_power = 1; //状态切为开机
- }
- else //当前是开机 → 本次是【关机】
- {
- key_power = 0; //状态切为关机,不再追加output_control
- }
- break;
- }
- SendUInt16(n);
- }
- ///----主函数----------------------------------
- void main(void)
- {
- u8 i;
- u16 j;
- EAXSFR();
- GPIO_set(); //配置所有I/O为准双向模式
- P1M0 = 0x00;//P1.4、P1.5、P1.7触摸按键接口配置为高阻态
- P1M1 = 0x70;
- P3M0 = 0xfc;//6个开关输出口配置为开漏输出(适配主控单片机ADC键盘)
- P3M1 = 0xfc;
-
-
-
- EA = 1;
- UartInit();
- TSCHEN1 = 0x70; //TK0~TK7
- TSCHEN2 = 0x00; //TK8~TK15
- TSCFG1 = (7 << 4) + 3; //B6~B4:开关电容工作频率 = fosc/(2*(TSCFG1[6:4]+1)), B2~B0:放电时间(系统时钟周期数) 0(125) 1(250) 2(500) 3(1000) 4(2000) 5(2500) 6(5000) 7(7500) 最好大于等于3(1000)
- TSCFG2 = 1; //B1~B0:配置触摸按键控制器的内部参考电压(AVCC的分压比), 0(1/4) 1(1/2) 2(5/8) 3(3/4)
- TSRT = 0x00; //没有LED分时扫描
- IE2 |= 0x80; //允许触摸按键中断
- delay_ms(500); //延时一下
- B_TK_Lowpass = 0; //禁止低通滤波
- for(read_cnt = 0; read_cnt < 10; read_cnt++) //扫描10次键, 将此值作为未触摸时的0点, 要求上电时不要触摸按键
- {
- TSCTRL = (1 << 7) + (1 << 6); //开始扫描, 无平均
- delay_ms(50); //延时一下, 等待扫描完成
- }
- TK_zero[4] = TK_cnt[4];
- TK_zero[5] = TK_cnt[5];
- TK_zero[6] = TK_cnt[6];
- B_TK_Lowpass = 1; //允许低通滤波
- KeyState = 0;
- read_cnt = 0;
- power = 1;//初始化各个输出端口
- high = 1;
- enhance = 1;
- medium = 1;
- weaken = 1;
- Small = 1;
- n = 2;
- kn = 0;
- while(1)
- {
- TSCTRL = (1 << 7) + (1 << 6); //开始扫描, 无平均
- delay_ms(20); //延时一下, 根据实际扫描速度调整
- if(++read_cnt >= 3)
- {
- read_cnt = 0;
- j = KeyState;
- for(i = 4; i < 7; i++)
- {
- if(TK_zero[i] > TK_cnt[i]) //0点值比当前值大, 触摸方向
- {
- //只有未按下才允许零点向下跟踪;按下后冻结,禁止TK_zero[i]--
- if(!(KeyState & T_KeyState[i]))
- {
- TK_zero[i]--; //空闲状态才缓慢0点跟随
- }
- if((TK_zero[i] - TK_cnt[i]) >= T_KeyPress[i] / 2)
- {
- KeyState |= T_KeyState[i]; //判定按下
- tk_freeze[i] = 1;
- }
- else if((TK_zero[i] - TK_cnt[i]) <= T_KeyPress[i] / 3)
- {
- KeyState &= ~T_KeyState[i]; //判定释放
- tk_freeze[i] = 0;
- }
- }
- else //0点值比当前值小, 释放方向,原版向上回零点逻辑完全原样保留不动
- {
- KeyState &= ~T_KeyState[i]; //键状态: 释放
- tk_freeze[i] = 0;
- if((TK_cnt[i] - TK_zero[i]) > 100) TK_zero[i] += 100; //差别很大, 则快速回0点
- else TK_zero[i] += 10; //差别不大, 则慢速回0点
- }
- }
- j = (j ^ KeyState) & KeyState;
- }
- //SendUInt16(TK_cnt[4]);SendString("-");
- //SendUInt16(TK_cnt[5]);SendString("-");
- //SendUInt16(TK_cnt[6]);
- //SendString("\r\n");
- if(j & T_KeyState[4]) // TK4 向下阶梯
- {
- // 新增:如果当前在上行阶梯中间n=3,按TK4直接回弹基准2、清kn
- if(n == 3)
- {
- n = 2;
- kn = 0;
- }
- else if(n == 4)
- {
- n = 2;
- kn = 0;
- }
- else if(n == 2)
- {
- n = 1;
- kn = 1;
- }
- else if((n == 1) && (kn == 1))
- {
- n = 1;
- kn = 2;
- }
- else if((n == 1) && (kn == 2))//语句A
- {
- n = 0;
- kn = 0;
- }
- else if(n <= 0)
- {
- n = 0;
- }
- output_control();
- j &= ~T_KeyState[4];
- }
- if(j & T_KeyState[5])
- {
- n = 5;
- kn = 0;
- output_control();
- j &= ~T_KeyState[5];
- }
- if(j & T_KeyState[6]) // TK6 向上阶梯
- {
- // 新增:如果当前在下行阶梯中间n=1,按TK6直接回弹基准2、清kn
- if(n == 1)
- {
- n = 2;
- kn = 0;
- }
- else if(n == 0)
- {
- n = 2;
- kn = 0;
- }
- else if(n == 2)
- {
- n = 3;
- kn = 1;
- }
- else if((n == 3) && (kn == 1))
- {
- n = 3;
- kn = 2;
- }
- else if((n == 3) && (kn == 2))//语句B
- {
- n = 4;
- kn = 0;
- }
- else if(n >= 4)
- {
- n = 4;
- }
- output_control();
- j &= ~T_KeyState[6];
- }
- }
- }
- //----触摸按键中断函数-------------------------
- void TKSU_ISR(void) interrupt 35
- {
- 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; //保存某个通道的读数
- else TK_cnt[j] = (TK_cnt[j] >> 1) + (TSDAT >> 1); //保存某个通道的读数 1/2低通滤波
- }
- }
复制代码
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|