找回密码
 立即注册
查看: 269|回复: 5

STC32G12K128 使用P3.2/INT0,外部中断当按键怎么实现进入掉电模式后长按开机?

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:118
  • 最近打卡:2025-12-17 09:07:39
已绑定手机

1

主题

5

回帖

115

积分

注册会员

积分
115
发表于 2025-10-9 10:41:25 | 显示全部楼层 |阅读模式
一个锂电产品,关机后要进入低功耗,用INT0(P3.2)引脚实现按键唤醒,现在情况是这样,我写的程序 在关机后能进入低功耗模式。但是在长按按键唤醒开机时出现下面两种情况
1.按键按下直接就开机了,没有经过检测长按
2.按键需要按两次,第一次按下唤醒,第二次按下可以实现长按开机
所以我想问问各位,怎么实现在 进入低功耗模式后,实现长按开机,麻烦各位给点思路
回复

使用道具 举报 送花

3

主题

2944

回帖

1634

积分

等待验证会员

积分
1634
发表于 2025-10-9 10:48:01 | 显示全部楼层
在使用STC32G12K128单片机实现低功耗掉电模式并通过外部中断INT0(P32)实现按键长按开机功能时,需要综合考虑硬件设计、中断配置、低功耗模式进入与退出机制以及软件逻辑判断等多个方面。以下从原理分析与实现思路两个层面进行详细说明,帮助您实现“进入掉电模式后,通过长按按键开机”的功能。

一、问题分析

您当前遇到的问题可以归纳为:

1. 按键按下直接唤醒:说明INT0中断触发方式为边沿触发(如下降沿),但未进行按键持续时间的判断。
2. 需要按两次按键才能实现长按功能:第一次唤醒系统后,系统未能在唤醒后立即检测按键是否持续按下,导致无法判断“长按”动作。

因此,核心问题在于:如何在系统从掉电模式中唤醒后,判断按键是否持续按下并达到“长按”时间阈值。

二、实现思路

1. 硬件基础配置
使用P32/INT0作为外部中断输入引脚,连接按键至地(GND),并配置上拉电阻(可使用内部上拉)。
按键按下时,P32为低电平,松开后恢复高电平。

2. 中断配置
将INT0配置为下降沿触发中断,用于唤醒系统。
在进入掉电模式前,使能INT0中断并开启全局中断。

3. 低功耗模式配置
使用掉电模式(Power Down Mode),该模式下CPU停止运行,仅保留中断唤醒能力。
进入掉电模式前,关闭所有不必要的外设和时钟,以降低功耗。

4. 唤醒后判断“长按”

这是实现长按开机功能的关键。具体步骤如下:

1. 系统被INT0中断唤醒后,立即重新配置系统时钟(如使用内部RC或外部晶振)。
2. 配置一个定时器(如Timer0或Timer2)用于计时。
3. 在唤醒后延时一段时间(如10ms)进行按键消抖。
4. 再次读取P32引脚电平状态:
若仍为低电平,说明按键仍在按下状态。
此时启动定时器开始计时。
5. 持续检测按键状态,直到按键释放或达到“长按”时间阈值(如1秒):
如果在1秒内按键释放,则视为“短按”,不执行开机操作。
如果按键持续按下超过1秒,则视为“长按”,执行开机操作。

三、代码逻辑结构(伪代码示例)
  1. c
  2. void main(void) {
  3.     // 初始化系统时钟、GPIO、定时器等
  4.     SystemInit();
  5.     while(1) {
  6.         // 主循环执行正常操作
  7.         if (shouldenterpowerdown()) {
  8.             enterpowerdownmode();
  9.         }
  10.     }
  11. }
  12. void enterpowerdownmode(void) {
  13.     // 关闭所有外设
  14.     disableperipheral();
  15.     // 设置INT0为下降沿触发
  16.     INT0EDGEFALLING();
  17.     // 使能INT0中断
  18.     enableINT0();
  19.     // 使能全局中断
  20.     EA = 1;
  21.     // 进入掉电模式
  22.     PCON |= 0x02;
  23.     // 等待中断唤醒
  24.     asm("nop");
  25. }
  26. void INT0ISR(void) interrupt 0 {
  27.     // 清除中断标志
  28.     INT0CLEARFLAG();
  29.     // 唤醒后延时消抖
  30.     DelayMs(10);
  31.     // 检测按键是否仍在按下
  32.     if (KEYDOWN()) {
  33.         // 启动定时器开始计时
  34.         starttimer();
  35.         while (KEYDOWN()) {
  36.             if (timercount >= 1000) { // 达到1秒
  37.                 // 长按确认,执行开机操作
  38.                 systempoweron();
  39.                 break;
  40.             }
  41.         }
  42.     }
  43. }
复制代码

四、注意事项

1. 按键消抖处理:硬件或软件消抖是必须的,否则可能误触发。
2. 系统时钟恢复:从掉电模式唤醒后,需要重新配置系统时钟源。
3. 中断优先级与嵌套:确保INT0中断优先级合适,避免被其他中断打断。
4. 功耗控制:唤醒后应尽快判断按键状态,避免长时间运行导致功耗升高。
5. 定时器精度:选择合适的定时器精度,确保“长按”时间判断准确。

五、总结

要实现“进入掉电模式后通过长按按键开机”的功能,关键是:
在进入掉电模式前正确配置中断和功耗模式;
唤醒后通过软件判断按键是否持续按下;
利用定时器检测按键持续时间,判断是否满足“长按”条件;
在满足长按条件后执行开机操作。

通过合理配置中断、时钟与定时器,并结合软件逻辑判断,即可在STC32G12K128平台上实现稳定可靠的长按开机功能。

如需进一步提供具体代码实现或硬件设计建议,欢迎继续交流。

[本文内容由国芯人工智能辅助生成,仅供参考]
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:647
  • 最近打卡:2025-12-18 07:29:35
已绑定手机

93

主题

6940

回帖

1万

积分

超级版主

积分
13026
发表于 2025-10-9 10:59:37 | 显示全部楼层
按下后立即唤醒是硬件决定的无法修改,可以按下唤醒后消抖并计时,期间持续判断按键状态,超过长按时间开机,否则再次进入省电模式
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:118
  • 最近打卡:2025-12-17 09:07:39
已绑定手机

1

主题

5

回帖

115

积分

注册会员

积分
115
发表于 2025-10-9 13:19:00 | 显示全部楼层
Debu*** 发表于 2025-10-9 10:59
按下后立即唤醒是硬件决定的无法修改,可以按下唤醒后消抖并计时,期间持续判断按键状态,超过长按时间开机 ...

哦,有点思路了,我尝试一下,谢谢
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2025-12-03 18:22:27
已绑定手机

0

主题

1

回帖

4

积分

新手上路

积分
4
发表于 2025-12-3 18:22:27 来自手机 | 显示全部楼层
你好,同样的问题,无法实现长按开机。要么瞬间唤醒,要么不能唤醒,在INT0中断服务函数中判断按键时长,我想知道这种方法是不是压根不可行
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:118
  • 最近打卡:2025-12-17 09:07:39
已绑定手机

1

主题

5

回帖

115

积分

注册会员

积分
115
发表于 2025-12-4 09:29:21 | 显示全部楼层
kt3*** 发表于 2025-12-3 18:22
你好,同样的问题,无法实现长按开机。要么瞬间唤醒,要么不能唤醒,在INT0中断服务函数中判断按键时长,我 ...

在INT0中断服务函数中判断按键时长这种方法是可以的,下面是我之前实现的代码,看看对你有没有帮助,按下在中断里判断按下时间的长短,如果是达到满足开机条件,就给一个开机标志位实现开机,如果不满足,可以重新进入睡眠模式

#define LONG_PRESS_THRESHOLD 200 // 长按阈值,单位:ms
void INT0_Isr(void) interrupt 0{   
        if (KEY1 == 0 && system_state == SYSTEM_OFF && !usb_charging_mode)
                        {
        EX0 = 0; // 关闭中断,防止重复触发
                                EA = 0;
        delay_ms(20); // 消抖
        // 确认按键仍然按下
        if (KEY1 == 0)
        {                                        
            unsigned int press_duration = 0; // 简单的长按判断
                                                EX0 = 1;
                                                EA = 1;
                                                delay_ms(1);
            while (KEY1 == 0 && press_duration < LONG_PRESS_THRESHOLD)
            {
                delay_ms(1);
                press_duration++;
            }
                                                 EA = 0;           
            if (press_duration >= LONG_PRESS_THRESHOLD)// 如果计时达到阈值,说明是长按
            {
                g_power_on_flag = 1; // 设置开机标志位
                                                                key_state = KEY_STATE_0;  key_time = 0;  keynum = 0;
                                                         
            }
        }

        EX0 = 1; // 重新使能中断
                                EA = 1;  // 确保总中断是开启的
    }
}
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-12-18 16:27 , Processed in 0.112288 second(s), 73 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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