数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 73|回复: 2

[C51] 尚朋堂电磁炉SR-1608键盘改STC触摸按键,触摸功能很棒外观完败【代码分享】

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
本帖最后由 慕名而来 于 2026-8-17 13:26 编辑

这个古老的电磁炉应该是国内可见家用电磁炉年代的第一梯队的老物件了,五年前就因为面板按键膜破洞无法使用了,貌似那时锅仔片的薄膜开关还没有普及吧,这货只是隔着面板膜按动轻触开关,久了没有不破露的,当时淘宝没有找到替换的键盘膜就用外接按键来凑合用了,最近没啥玩的、手痒难耐就对它下手了,编程时在豆包各种拐带、各种坑后弄了好久仍然无法实现控制目标,无奈收拢心神分析STC的官方例程最终完成了改造,这次改造主要工程就是DIY一个按键面板,买了2mm厚度的亚克力板连锯带磨也没费多少功夫,倒是三个按键的体现比较费劲但喷了漆以后面板完成效果还是不错的,没有想到的是用的粘接胶竟然把油漆给融掉了,使得最终的成品面目全非惨不忍睹,既然使用功能没问题了也不再纠结外观了,凑合用了。

这可能是多年来所有制作中最不成功的一次!!!

虽然外观完败,但触摸功能还是很稳定的,源程序在此分享供坛友交流。
原机有6个按键,分别是电源开关键,大火力键,增加键,中火力键,减少键,小火力键,改造后保留减少、电源开关、增加三个按键,使用感觉更加简单、快捷,触摸灵敏度适中,无失控、不乱跳。
声明:程序根据STC官方代码改编。使用带有触摸功能的单片机STC8H1K08T,下载程序时配置系统时钟22.1184MHz
程序原创:wannenggong,由豆包AI辅助整理、标注

  1. #include <STC8H.h>
  2. #include "delay.h"
  3. #include "STC8_uart.h"
  4. //----输出引脚定义-----------------------------
  5. sbit power    = P3 ^ 2;               // 电源开关
  6. sbit high     = P3 ^ 3;               // 强火力
  7. sbit enhance  = P3 ^ 4;               // 增强
  8. sbit medium   = P3 ^ 5;               // 中火力
  9. sbit weaken   = P3 ^ 6;               // 减弱
  10. sbit Small    = P3 ^ 7;               // 小火力
  11. //----本地变量声明-----------------------------
  12. u16        xdata TK_cnt[8];        // 按键计数值, 16位
  13. u16        xdata TK_zero[8];        // 按键0点值, 16位
  14. u16        KeyState;                        // 按键状态, 每个bit对应一个键, 1为按下, 0为释放
  15. u8        read_cnt;                        // 读次数
  16. bit        B_TK_Lowpass;                // 低通允许, 1允许, 0禁止
  17. bit key_power = 0;
  18. u8 tk_freeze[8];   // 新增:对应TK0~TK7,1=按下冻结零点,0=空闲允许零点跟踪
  19. static u8 n, kn;
  20. //---------------------------------------------
  21. //                         K0 K1 K2 K3     K4     K5      K6    K7
  22. u16 code T_KeyPress[8] = { 0, 0, 0, 0,   50,     150,    350,  0 };        //触摸后的变化值
  23. u16 code T_KeyState[8] = { 0, 0, 0, 0,  0x0010, 0x0020, 0x0040, 0 };        //8个键对应的状态, 0为未触摸,1为触摸
  24. //----按键控制输出函数-------------------------
  25. //模拟轻触按键控制
  26. void output_control()
  27. {
  28.   switch(n)
  29.   {
  30.     case 0:
  31.       Small = 0;//IO口输出高电平、模拟按键按下一次
  32.       delay_ms(200);
  33.       Small = 1;//IO输出恢复低电平空闲状态
  34.       break;

  35.     case 1:
  36.       weaken = 0;
  37.       delay_ms(200);
  38.       weaken = 1;
  39.       break;

  40.     case 2:
  41.       medium = 0;
  42.       delay_ms(200);
  43.       medium = 1;
  44.       break;

  45.     case 3:
  46.       enhance = 0;
  47.       delay_ms(200);
  48.       enhance = 1;
  49.       break;

  50.     case 4:
  51.       high = 0;
  52.       delay_ms(200);
  53.       high = 1;
  54.       break;

  55.     case 5:

  56.       power = 0;  //发送脉宽100ms的低电平脉冲模拟轻触按键按下一次后抬起
  57.       delay_ms(200);
  58.       power = 1;

  59.       if(key_power == 0)      //当前是关机 → 本次是【开机】
  60.       {
  61.         delay_ms(250);
  62.         n = 2;
  63.         medium = 0;
  64.         delay_ms(200);
  65.         medium = 1;
  66.         key_power = 1;      //状态切为开机
  67.       }
  68.       else                    //当前是开机 → 本次是【关机】
  69.       {
  70.         key_power = 0;      //状态切为关机,不再追加output_control
  71.       }

  72.       break;
  73.   }

  74.   SendUInt16(n);
  75. }

  76. ///----主函数----------------------------------
  77. void main(void)
  78. {
  79.   u8        i;
  80.   u16        j;

  81.   EAXSFR();
  82.   GPIO_set(); //配置所有I/O为准双向模式
  83.   P1M0 = 0x00;//P1.4、P1.5、P1.7触摸按键接口配置为高阻态
  84.   P1M1 = 0x70;
  85.   P3M0 = 0xfc;//6个开关输出口配置为开漏输出(适配主控单片机ADC键盘)
  86.   P3M1 = 0xfc;
  87.   
  88.   

  89. EA = 1;
  90.   UartInit();
  91.   TSCHEN1 = 0x70;                //TK0~TK7
  92.   TSCHEN2 = 0x00;                //TK8~TK15
  93.   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)
  94.   TSCFG2  = 1;                //B1~B0:配置触摸按键控制器的内部参考电压(AVCC的分压比), 0(1/4)  1(1/2)  2(5/8)  3(3/4)
  95.   TSRT = 0x00;                //没有LED分时扫描
  96.   IE2 |= 0x80;                //允许触摸按键中断
  97.   delay_ms(500);                //延时一下

  98.   B_TK_Lowpass = 0;        //禁止低通滤波

  99.   for(read_cnt = 0; read_cnt < 10; read_cnt++)        //扫描10次键, 将此值作为未触摸时的0点, 要求上电时不要触摸按键
  100.   {
  101.     TSCTRL = (1 << 7) + (1 << 6);                //开始扫描, 无平均
  102.     delay_ms(50);        //延时一下, 等待扫描完成
  103.   }

  104.   TK_zero[4] = TK_cnt[4];
  105.   TK_zero[5] = TK_cnt[5];
  106.   TK_zero[6] = TK_cnt[6];

  107.   B_TK_Lowpass = 1;        //允许低通滤波
  108.   KeyState = 0;
  109.   read_cnt = 0;
  110.   power    = 1;//初始化各个输出端口
  111.   high     = 1;
  112.   enhance  = 1;
  113.   medium   = 1;
  114.   weaken   = 1;
  115.   Small    = 1;

  116.   n = 2;
  117.   kn = 0;

  118.   while(1)
  119.   {


  120.     TSCTRL = (1 << 7) + (1 << 6);                //开始扫描, 无平均
  121.     delay_ms(20);                //延时一下, 根据实际扫描速度调整

  122.     if(++read_cnt >= 3)
  123.     {
  124.       read_cnt = 0;
  125.       j = KeyState;

  126.       for(i = 4; i < 7; i++)
  127.       {
  128.         if(TK_zero[i] > TK_cnt[i])        //0点值比当前值大, 触摸方向
  129.         {
  130.           //只有未按下才允许零点向下跟踪;按下后冻结,禁止TK_zero[i]--
  131.           if(!(KeyState & T_KeyState[i]))
  132.           {
  133.             TK_zero[i]--;        //空闲状态才缓慢0点跟随
  134.           }

  135.           if((TK_zero[i] - TK_cnt[i]) >= T_KeyPress[i] / 2)
  136.           {
  137.             KeyState |=  T_KeyState[i];        //判定按下
  138.             tk_freeze[i] = 1;
  139.           }
  140.           else if((TK_zero[i] - TK_cnt[i]) <= T_KeyPress[i] / 3)
  141.           {
  142.             KeyState &= ~T_KeyState[i];        //判定释放
  143.             tk_freeze[i] = 0;
  144.           }
  145.         }
  146.         else        //0点值比当前值小, 释放方向,原版向上回零点逻辑完全原样保留不动
  147.         {
  148.           KeyState &= ~T_KeyState[i];        //键状态: 释放
  149.           tk_freeze[i] = 0;

  150.           if((TK_cnt[i] - TK_zero[i]) > 100)        TK_zero[i] += 100;        //差别很大, 则快速回0点
  151.           else        TK_zero[i] += 10;        //差别不大, 则慢速回0点
  152.         }
  153.       }

  154.       j = (j ^ KeyState) & KeyState;

  155.     }

  156.     //SendUInt16(TK_cnt[4]);SendString("-");
  157.     //SendUInt16(TK_cnt[5]);SendString("-");
  158.     //SendUInt16(TK_cnt[6]);
  159.     //SendString("\r\n");

  160. if(j & T_KeyState[4])  // TK4 向下阶梯
  161. {
  162.   // 新增:如果当前在上行阶梯中间n=3,按TK4直接回弹基准2、清kn
  163.   if(n == 3)
  164.   {
  165.     n = 2;
  166.     kn = 0;
  167.   }
  168.   else if(n == 4)
  169.   {
  170.     n = 2;
  171.     kn = 0;
  172.   }
  173.   else if(n == 2)
  174.   {
  175.     n = 1;
  176.     kn = 1;
  177.   }
  178.   else if((n == 1) && (kn == 1))
  179.   {
  180.     n = 1;
  181.     kn = 2;
  182.   }
  183.   else if((n == 1) && (kn == 2))//语句A
  184.   {
  185.     n = 0;
  186.     kn = 0;
  187.   }
  188.   else if(n <= 0)
  189.   {
  190.     n = 0;
  191.   }

  192.   output_control();
  193.   j &= ~T_KeyState[4];
  194. }

  195. if(j & T_KeyState[5])
  196. {
  197.   n = 5;
  198.   kn = 0;
  199.   output_control();
  200.   j &= ~T_KeyState[5];
  201. }

  202. if(j & T_KeyState[6])  // TK6 向上阶梯
  203. {
  204.   // 新增:如果当前在下行阶梯中间n=1,按TK6直接回弹基准2、清kn
  205.   if(n == 1)
  206.   {
  207.     n = 2;
  208.     kn = 0;
  209.   }
  210.   else if(n == 0)
  211.   {
  212.     n = 2;
  213.     kn = 0;
  214.   }
  215.   else if(n == 2)
  216.   {
  217.     n = 3;
  218.     kn = 1;
  219.   }
  220.   else if((n == 3) && (kn == 1))
  221.   {
  222.     n = 3;
  223.     kn = 2;
  224.   }
  225.   else if((n == 3) && (kn == 2))//语句B
  226.   {
  227.     n = 4;
  228.     kn = 0;
  229.   }
  230.   else if(n >= 4)
  231.   {
  232.     n = 4;
  233.   }

  234.   output_control();
  235.   j &= ~T_KeyState[6];
  236. }


  237.   }
  238. }

  239. //----触摸按键中断函数-------------------------
  240. void        TKSU_ISR(void) interrupt 35
  241. {
  242.   u8        j;

  243.   j = TSSTA2;

  244.   if(j & 0x40)        //数据溢出, 错误处理(略)
  245.   {
  246.     TSSTA2 |= 0x40;        //写1清零
  247.   }

  248.   if(j & 0x80)        //扫描完成
  249.   {
  250.     j &= 0x0f;
  251.     TSSTA2 |= 0x80;        //写1清零

  252.     if(!B_TK_Lowpass)        TK_cnt[j] = TSDAT;        //保存某个通道的读数        
  253.     else                                TK_cnt[j] = (TK_cnt[j] >> 1) + (TSDAT >> 1);                //保存某个通道的读数        1/2低通滤波
  254.   }
  255. }
复制代码





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
发表于 1 小时前 来自手机浏览器 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

发表于 半小时前 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|数码之家-技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2026-8-17 15:39 , Processed in 0.093600 second(s), 9 queries , Gzip On, Redis On.

Powered by Discuz!

© MyDigit.Net Since 2006

快速回复 返回顶部 返回列表