找回密码
 立即注册
查看: 336|回复: 16

关于STC8H8K 64U按键的迷惑

[复制链接]

48

主题

87

回帖

907

积分

高级会员

积分
907
发表于 2026-9-23 18:23:09 | 显示全部楼层 |阅读模式
最近使用江协科技状态机按键程序,感觉不错,在stc32g12k128,使用效果很好,我把它移植到我的一个稳压电源上,使用的是STC8H8K,按键完全不能使用,,不管长按、短按、双击都执行按键里的操作,与豆包讨论很久也没有解决,原稳压电源使用的布丁橘长里的按键程序,说明硬件没有问题,江协科技按键程序在stc32g中运行良好,说明按键程序问题,各位大佬讨论什么原因,
我不愿用布丁局长按键程序因为他的.c文件有10ms延时,理论上还是阻塞式按键程序,我试试把他.c文件里去掉10ms延时,按键扫描放到1ms定时器每隔10ms执行一次应该可以吧
下面江协科技的按键.C文件和.H文件,各位大佬讨论什么原因






#include "Key.h"

#define KEY_PRESSED                                1
#define KEY_UNPRESSED                        0

#define KEY_TIME_DOUBLE                        200
#define KEY_TIME_LONG                        2000
#define KEY_TIME_REPEAT                        100

uint8_t Key_Flag1[KEY_COUNT];


uint8_t Key_GetState(uint8_t n)
{
        if (n == KEY_1)
        {
                if (P33 == 0)
                {
                        return KEY_PRESSED;
                }
        }
//        else if (n == KEY_2)
//        {
//                if (P34 == 0)
//                {
//                        return KEY_PRESSED;
//                }
//        }
//        else if (n == KEY_3)
//        {
//                if (P35 == 0)
//                {
//                        return KEY_PRESSED;
//                }
//        }
//        else if (n == KEY_4)
//        {
//                if (P32 == 0)
//                {
//                        return KEY_PRESSED;
//                }
//        }
        return KEY_UNPRESSED;
}

uint8_t Key_Check(uint8_t n, uint8_t Flag)
{
        if (Key_Flag1[n] & Flag)
        {
                if (Flag != KEY_HOLD)
                {
                        Key_Flag1[n] &= ~Flag;
                }
                return 1;
        }
        return 0;
}

void Key_Tick(void)
{
        static uint8_t Count, i;
        static uint8_t CurrState[KEY_COUNT], PrevState[KEY_COUNT];
        static uint8_t S[KEY_COUNT];
        static uint16_t Time[KEY_COUNT];
       
        for (i = 0; i < KEY_COUNT; i ++)
        {
                if (Time[i] > 0)
                {
                        Time[i] --;
                }
        }
       
        Count ++;
        if (Count >= 30)
        {
                Count = 0;
               
                for (i = 0; i < KEY_COUNT; i ++)
                {
                        PrevState[i] = CurrState[i];
                        CurrState[i] = Key_GetState(i);
                       
                        if (CurrState[i] == KEY_PRESSED)
                        {
                                Key_Flag1[i] |= KEY_HOLD;
                        }
                        else
                        {
                                Key_Flag1[i] &= ~KEY_HOLD;
                        }
                       
                        if (CurrState[i] == KEY_PRESSED && PrevState[i] == KEY_UNPRESSED)
                        {
                                Key_Flag1[i] |= KEY_DOWN;
                        }
                       
                        if (CurrState[i] == KEY_UNPRESSED && PrevState[i] == KEY_PRESSED)
                        {
                                Key_Flag1[i] |= KEY_UP;
                        }
                       
                        if (S[i] == 0)
                        {
                                if (CurrState[i] == KEY_PRESSED)
                                {
                                        Time[i] = KEY_TIME_LONG;
                                        S[i] = 1;
                                }
                        }
                        else if (S[i] == 1)
                        {
                                if (CurrState[i] == KEY_UNPRESSED)
                                {
                                        Time[i] = KEY_TIME_DOUBLE;
                                        S[i] = 2;
                                }
                                else if (Time[i] == 0)
                                {
                                        Time[i] = KEY_TIME_REPEAT;
                                        Key_Flag1[i] |= KEY_LONG;
                                        S[i] = 4;
                                }
                        }
                        else if (S[i] == 2)
                        {
                                if (CurrState[i] == KEY_PRESSED)
                                {
                                        Key_Flag1[i] |= KEY_DOUBLE;
                                        S[i] = 3;
                                }
                                else if (Time[i] == 0)
                                {
                                        Key_Flag1[i] |= KEY_SINGLE;
                                        S[i] = 0;
                                }
                        }
                        else if (S[i] == 3)
                        {
                                if (CurrState[i] == KEY_UNPRESSED)
                                {
                                        S[i] = 0;
                                }
                        }
                        else if (S[i] == 4)
                        {
                                if (CurrState[i] == KEY_UNPRESSED)
                                {
                                        S[i] = 0;
                                }
                                else if (Time[i] == 0)
                                {
                                        Time[i] = KEY_TIME_REPEAT;
                                        Key_Flag1[i] |= KEY_REPEAT;
                                        S[i] = 4;
                                }
                        }
                }
        }
}









#ifndef __KEY_H
#define __KEY_H

#include "config.h"

#define KEY_COUNT                                1

#define KEY_1                                        0
#define KEY_2                                        1
#define KEY_3                                        2
#define KEY_4                                        3

#define KEY_HOLD                                0x01
#define KEY_DOWN                                0x02
#define KEY_UP                                        0x04
#define KEY_SINGLE                                0x08
#define KEY_DOUBLE                                0x10
#define KEY_LONG                                0x20
#define KEY_REPEAT                                0x40


uint8_t Key_Check(uint8_t n, uint8_t Flag);
void Key_Tick(void);

#endif









回复

使用道具 举报 送花

已绑定手机

11

主题

484

回帖

1362

积分

金牌会员

积分
1362
发表于 2026-9-23 20:08:24 | 显示全部楼层
按键程序写法繁多,各有适合的应用场景,哪有一招打遍天下的代码。
回复

使用道具 举报 送花

已绑定手机

2

主题

154

回帖

470

积分

中级会员

积分
470
发表于 2026-9-23 21:36:07 | 显示全部楼层
完全不能用是指什么,按键无作用,还是太灵敏。
无作用:检查p33端口模式设置正确了吗?
太灵敏:Key_Tick调用间隔多少,太快了,消抖不不太好。
回复

使用道具 举报 送花

83

主题

8317

回帖

1万

积分

超级版主

积分
17932
发表于 2026-9-23 22:30:57 | 显示全部楼层
不知道你是行列扫描还是单键。
哪怕8*8=64键的行列扫描,程序一般也就20来行,放在时隙里扫描。
按键程序只扫描按键提供键码,提供最基本的按下、释放、长按、双击,不要在按键扫描程序里执行按键。
回复

使用道具 举报 送花

48

主题

87

回帖

907

积分

高级会员

积分
907
 楼主| 发表于 2026-9-24 03:58:24 | 显示全部楼层
jrc*** 发表于 2026-9-23 21:36
完全不能用是指什么,按键无作用,还是太灵敏。
无作用:检查p33端口模式设置正确了吗?
太灵敏:Key_Tick ...

后面写了,不管长按、短按、双击都执行按键里的操作,比如
                if (Key_Check(KEY_1, KEY_LONG) )
                {
                                BEEP=1;                                                
                                BPj=0;
                }
与没有if判断一样  适中运行 BEEP=1; BPj=0;,蜂鸣器一直在响
回复

使用道具 举报 送花

48

主题

87

回帖

907

积分

高级会员

积分
907
 楼主| 发表于 2026-9-24 04:03:17 | 显示全部楼层
jrc*** 发表于 2026-9-23 21:36
完全不能用是指什么,按键无作用,还是太灵敏。
无作用:检查p33端口模式设置正确了吗?
太灵敏:Key_Tick ...

P33准双向口,Key_Tick调用间隙1ms,但Key_Tick里面有一个20次的判断,等于20ms扫描一次
回复

使用道具 举报 送花

48

主题

87

回帖

907

积分

高级会员

积分
907
 楼主| 发表于 2026-9-24 04:23:38 | 显示全部楼层
梁*** 发表于 2026-9-23 22:30
不知道你是行列扫描还是单键。
哪怕8*8=64键的行列扫描,程序一般也就20来行,放在时隙里扫描。
按键程序只 ...

单按键,关键在STC32G12K128,运行正常,在8h8k就不行,现在在8H8K这个单片机使用的是布丁橘长里按键程序,他的按键.c文件有10ms延时,按键键值读取放到while循环里,昨晚我把他的按键.c文件有10ms延时去掉,键值读取放到定时器1ms里,每隔10ms读取按键键值,正常使用有问题。后来我又改成20ms读取一次按键键值,按键单击就有遗漏,不是每次单击都执行,按理也不应该
回复

使用道具 举报 送花

已绑定手机

11

主题

484

回帖

1362

积分

金牌会员

积分
1362
发表于 2026-9-24 08:42:01 | 显示全部楼层
dong*** 发表于 2026-9-24 04:23
单按键,关键在STC32G12K128,运行正常,在8h8k就不行,现在在8H8K这个单片机使用的是布丁橘长里按键程序 ...

给你一个最基本的长、短按键程序参考

  1. unsigned char Key_value=0;
  2. //放在1ms中断函数中运行
  3. void keyscan()
  4. {
  5.         static unsigned int i=0;//计数变量
  6.         if(!key)//按键按下
  7.         {
  8.                 i++;
  9.                 if(i==600)//长按600ms
  10.                 {
  11.                         Key_value=1;
  12.                 }
  13.                 if(i>600)i=601;        //防止i溢出                                  
  14.         }
  15.         else                                //松手
  16.         {
  17.                 if(i>10 && i<300)//短按 大于10ms,小于300ms
  18.                 {
  19.                         Key_value=2;
  20.                 }
  21.                 i=0;
  22.         }
  23. }
  24. //按键服务程序 放在主函数中运行
  25. void key_service()                                       
  26. {
  27.         if(Key_value==1)
  28.         {
  29.                 Key_value=0;
  30.                 //执行长按任务
  31.         }
  32.         if(Key_value==2)
  33.         {
  34.                 Key_value=0;
  35.                 //执行短按任务
  36.         }
  37. }
复制代码
回复

使用道具 举报 送花

已绑定手机

2

主题

154

回帖

470

积分

中级会员

积分
470
发表于 2026-9-24 09:30:59 | 显示全部楼层
dong*** 发表于 2026-9-24 04:03
P33准双向口,Key_Tick调用间隙1ms,但Key_Tick里面有一个20次的判断,等于20ms扫描一次 ...

"P33准双向口",初始化为1了吗

后面补充:忽略我这段话。上电P3默认是1。
回复

使用道具 举报 送花

已绑定手机

2

主题

154

回帖

470

积分

中级会员

积分
470
发表于 2026-9-24 10:14:51 | 显示全部楼层
另外,Key_Tick()里的那些变量尽量要显示初始化,如果IDATAt和XDATA没有统一清0,上电后有可能是随机值的,然后if(S[i]==x)那里可能就没有命中的。
如:static uint16_t Time[xx] = {0};   /* 全部初始化为 0 */
回复

使用道具 举报 送花

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

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-11-7 12:22 , Processed in 0.076386 second(s), 80 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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