mppqgqha 发表于 2026-5-15 16:58:45

低功耗和唤醒

我使用的芯片是STC8H4K64TLCD   需要做低功耗和IO口唤醒   我通过按键下降沿中断唤醒,也就是说在进入低功耗之前需要先将该IO口设置为上拉状态,但是手册上说要省电的话
就要将IO设置为高阻输入并关闭数字输入,那这不是和我按键下降沿中断唤醒冲突吗

wulin 发表于 2026-5-15 17:28:12

建议按键接外部中断INTx用作中断唤醒,设置准双向模式。其它功能扩展的设置全部按默认状态。

mppqgqha 发表于 2026-5-15 17:38:32

wulin 发表于 2026-5-15 17:28
建议按键接外部中断INTx用作中断唤醒,设置准双向模式。其它功能扩展的设置全部按默认状态。 ...

关闭数字输入了还能进入中断吗
我现在就是想通过按键能唤醒 然后做低功耗时候不能因为这个按键功耗增大

wulin 发表于 2026-5-15 20:23:16

mppqgqha 发表于 2026-5-15 17:38
关闭数字输入了还能进入中断吗
我现在就是想通过按键能唤醒 然后做低功耗时候不能因为这个按键功耗增大 ...
IO口配置工具中4个基本配置就可以适合绝大多数应用场景,当然包括外部中断。所谓高级配置多数情况用不到,默认不开启。既然未使能就没有关闭一说,就当不存在,与外部中断何干?低功耗睡眠主要是应用于电池供电的设备。为了节电,单片机休眠时有可能因端口配置因素,受外围电路的影响导致低功耗电流达不到理想值。所以在休眠前关闭这些配置,减少功耗。唤醒后再恢复相关配置。
测试程序
//一键开/关机(掉电唤醒)
//适合STC15/STC8系列,测试平台STC8H3K48S2开发板
#include <STC8H.H>
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int

sbit key= P3^2;//S14

uchar Temp;
uchar Key_value; //键值
uintkeyTim;    //按键时长
bit   flag1ms;   //1ms中断标志
bit   on_off;    //开关标志
bit   allow;   //允许关机标志

//初始化单片机端口
void McuInit()
{
        P0M0 = 0x00; P0M1 = 0x00;
        P1M0 = 0x00; P1M1 = 0x00;
        P2M0 = 0x00; P2M1 = 0x00;
        P3M0 = 0x00; P3M1 = 0x00;
        P4M0 = 0x00; P4M1 = 0x00;
        P5M0 = 0x00; P5M1 = 0x00;
        P6M0 = 0x00; P6M1 = 0x00;
        P7M0 = 0x00; P7M1 = 0x00;
}
//关闭单片机端口
void McuSleep()
{
        P0M0 = 0x00; P0M1 = 0xff;
        P1M0 = 0x00; P1M1 = 0xff;
        P2M0 = 0x00; P2M1 = 0xff;
        P3M0 = 0x00; P3M1 = 0xf8;
        P4M0 = 0x00; P4M1 = 0xff;
        P5M0 = 0x00; P5M1 = 0xff;
        P6M0 = 0x00; P6M1 = 0xff;
        P7M0 = 0x00; P7M1 = 0xff;
}
void Timer0_Init()                //1毫秒@11.0592MHz
{
        AUXR |= 0x80;                        //定时器时钟1T模式
        TMOD &= 0xF0;                        //设置定时器模式
        TL0 = 0xCD;                                //设置定时初始值
        TH0 = 0xD4;                                //设置定时初始值
        TF0 = 0;                                //清除TF0标志
        TR0 = 1;                                //定时器0开始计时
        ET0 = 1;                                //使能定时器0中断
}

void Delay20ms(void)        //@11.0592MHz
{
        unsigned char data i, j, k;

        i = 2;
        j = 32;
        k = 60;
        do
        {
                do
                {
                        while (--k);
                } while (--j);
        } while (--i);
}


void key_scan()    //按键扫描函数
{
        if(flag1ms)//1ms时间标志
        {
                flag1ms = 0;//1ms时间标志清0
                if(!key && !on_off)
                {
                        if(++keyTim>1000)keyTim=1001;//防止溢出

                        if(keyTim==20) //大于20ms小于1s算短按
                        {
                                Key_value=0x01;
                        }
                        if(keyTim==1000) //达到1s算长按
                        {
                                Key_value|=0x10;
                        }
                }
                else
                {
                        keyTim=0;        //按键松手keyTim清0
                }
        }
}

void key_service()//按键服务函数
{//短按等松手响应,长按达1s不论是否松手即响应
        if((keyTim==0||keyTim==1000) && Key_value!=0x00)
        {
                if(Key_value==0x01)//短按任务
                {
                        Temp++;
                        P4=~Temp;//演示,LED低电平亮
                }
                if(Key_value==0x11)//长按关机
                {
                        allow=1;//允许休眠
                }
                Key_value=0x00;//任务完成后键值清0
        }
}

void Shutdown()//掉电模式函数
{
        if(allow)
        {
                McuSleep();                //关闭单片机端口
                //关闭所有在用硬件,减小能耗
                while(!key);//等待按键松手
                Delay20ms();//消抖防止误动作
                EX0 = 1;                //开外部中断
                PCON = 0x02;//MCU进入掉电模式
/************************************************/
                _nop_();    //掉电模式被唤醒后,首先执行此语句,然后再进入中断服务程序
                _nop_();    //中断服务程序执行完再接着此句继续执行
                while(!key);//等待按键松手,防止按键扫描程序误读
                Delay20ms();//消抖防止误动作
                //打开所有在用硬件,恢复正常运行
                allow=0;                //清0
                on_off=0;        //开关标志清0
                McuInit();//初始化单片机端口
                P4=~Temp;        //恢复LED显示
        }
}

void main()
{
        McuInit();
        IT0 = 1;//设置INT0的中断类型为下降沿唤醒
//        EX0 = 1;//使能INT0中断
        EA= 1;//开总中断
        Timer0_Init();//定时器初始化函数
        while (1)
        {
                key_scan();                //按键扫描函数
                key_service(); //按键服务函数
                Shutdown();                //掉电模式函数
        }
}
//INT0中断服务程序
void exint0() interrupt 0
{
        EX0 = 0;                //关外部中断
        on_off=1;//开关标志置1
}
//T0中断服务程序
void interruptTimer0() interrupt 1
{
        flag1ms = 1;    //1ms标志
}


_奶咖君_ 发表于 2026-5-16 09:01:02

我觉得这5点你应该按照 if - else if 的形式来判断。 而不是 if - if
页: [1]
查看完整版本: 低功耗和唤醒