zhang32568 发表于 2026-2-20 21:08:58

请教大神一个问题。只有一个按键使用P3.2。作为下载和开关机

如题:芯片STC32G12K128使用带开关的EC11编码器,开关使用使用端口P3.2。
(USB下载时候长按P3.2进入下载模式)。
正常使用的时候作为一个菜单按键。
还要兼职长按关机。。在长按开机。可以实现吗?

DebugLab 发表于 2026-2-21 00:49:10

省电模式,INT0中断唤醒,GPIO读按键,可行

wulin 发表于 2026-2-22 17:13:08

此测试程序基本符合楼主需求,短按开机,正常工作期间可以用于菜单,长按关机。USB下载时候先按key再上电进入下载模式没有问题。
//一键开/关机(掉电唤醒)
//适合STC15/STC8系列,测试平台 TX-1C 开发板,MCU型号STC8H1K08
//#include <STC15F2K60S2.H>
#include <STC8H.H>
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int

sbit key= P3^2;//S14
sbit GND= P3^4;//矩阵键盘模拟接地

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

void Timer0Init(void)//1毫秒@11.0592MHz
{
        AUXR |= 0x80;                //定时器时钟1T模式
        TMOD &= 0xF0;                //设置定时器自动重载模式
        TL0 = 0xCD;                        //设置定时初始值
        TH0 = 0xD4;                        //设置定时初始值
        TF0 = 0;                                //清除TF0标志
        TR0 = 1;                                //定时器0开始计时
        ET0 = 1;                                //允许T0中断
//        EA= 1;                                //开总中断
}
void Delay20ms()                //@11.0592MHz
{
        unsigned char i, j;

        i = 216;
        j = 37;
        do
        {
                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++;
                        P1=~Temp;//演示,LED低电平亮
                }
                if(Key_value==0x11)//长按关机
                {
                        allow=1;//允许休眠
                }
                Key_value=0x00;//任务完成后键值清0
        }
}

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

void main()
{
        P0M0 = 0x00;//初始化IO
        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;
        GND= 0;
        IT0 = 1;//设置INT0的中断类型为下降沿唤醒
//        EX0 = 1;//使能INT0中断
        EA= 1;//开总中断                                                      
        Timer0Init();//定时器初始化函数
        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标志
}

zhang32568 发表于 2026-2-22 23:17:07

wulin 发表于 2026-2-22 17:13
此测试程序基本符合楼主需求,短按开机,正常工作期间可以用于菜单,长按关机。USB下载时候先按key再上电进 ...

非常感谢

llyymm 发表于 2026-2-23 10:18:44

wulin 发表于 2026-2-22 17:13
此测试程序基本符合楼主需求,短按开机,正常工作期间可以用于菜单,长按关机。USB下载时候先按key再上电进 ...

收藏了,感谢分享{:baoquan:}
页: [1]
查看完整版本: 请教大神一个问题。只有一个按键使用P3.2。作为下载和开关机