找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 835|回复: 5
打印 上一主题 下一主题
收起左侧

遇到了一个奇怪的单片机程序问题,百思不得其解

[复制链接]
跳转到指定楼层
楼主
ID:686513 发表于 2023-5-19 09:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
sbit unit = P1^0;   //P1.0为外部中断口(接菜单键)。我想实现:开机时按此键为菜单切换键,长按时休眠,休眠后再短按一下开机。 目前可以实现开机时菜单切换,自动休眠后再短按一下开机,但长按给Low_Power =101;按理论上应该可以进入休眠,但是休眠瞬间又复位开机了。如果把这句 Power_Down_F = 0;        放在掉电模式STOP2后,可以实现菜单切换,长按时休眠,但休眠后短按开机又出现了以下几个问题:1.自动休眠后需按两次才能开机,(休眠后电流为:15uA,按下第一次电流升到1到2mA但不开机,按下第二次才能开机)2.长按按键休眠后待机电流为1-2mA(休眠电流应该为:15uA,没有完全休眠),这时只需按下一次会开机。

目前我的思路是借鉴论坛里 “家用厨房电子秤” 的休眠程序 :原程序中没有长按关机功能,只是自动休眠前把外部中断打开,按下接外部中断的开关触发中断退出休眠。和之前WULIN老师说的方法类似,“利用单片机休眠功能即可解决。初次上电自动开机,P1.0作为普通按键使用,短按切换菜单,长按执行菜单下不同任务。只要再加一项菜单,长按打开外部中断,执行睡眠即可关机。在睡眠状态由外部触发唤醒,关闭外部中断,恢复P1.0作为普通按键使用。”
以下是按照上面的思路我写的。
//休眠 ---------------------------------------------------------------------------------------------                                                
  if(XmCnt==1)                                        //XmCnt为定时器500mS到标志,即500mS检测一下是否进来休眠
                {
     if(md1==0&&press<50)                            //如果md1==0&&press<50休眠
                                 
                          {
                                 Low_Power ++;        
                                }        
      else
                          {                        
                                 Low_Power = 0;        
                          }        
                 }

if(Low_Power > 100)             //50S休眠
                {
                        IT1=1;               //使能INT1下降沿中断                        
                        EX1=1;               //使能INT1中断

                       ET0=0;                    //关闭定时器0
                       ET1=0;                    //关闭定时器1                                
        WD_DIS                  // 看门狗关闭
                                                
//--配置IO模式 (确保不漏电)
                        P0M0 = 0x00; P0M1 = 0xff;
                        P1M0 = 0x00; P1M1 = 0xfe;      //P1.0为外部中断口
                        P2M0 = 0x00; P2M1 = 0xff;
                        P3M0 = 0x00; P3M1 = 0xff;
                        P4M0 = 0x00; P4M1 = 0xff;
                                       
                        P0 = 0x00;
                        P1 = 0x01;             //P1.0为外部中断口
                        P2 = 0x2E;             //p2.1 p2.2 p2.3 p2.5低电平驱动四个数码管的COM口
                        P3 = 0x00;
                        P4 = 0x00;
                         Power_Down_F = 0;        
                        
                                 _nop_();
                                        PCON |= 0x10;                        //进入掉电模式STOP2
                                 _nop_();                        
                                       
         //-- 关机 : 等待外部中断唤醒 ---         
                                while(1)
                                {
                                        if(Power_Down_F)                                                        
                                        PCON        = 0x0C;                 //唤醒                                                        
                                }        
                   }        
   }
}

void EX_Int1 (void) interrupt 2       //INT1
{         
Power_Down_F = 1 ;
}

按键为低层和应该用层扫描识别
void key_Service()       //应用层
{                          
  switch(Key_Scan())      //key_Scan()  为底层 返回键值                                                     
    {               
      case 2:   if(Setflag == 1){ KeyNum=0; E2prom_Read_user();T1Cnt=0; SSCnt=0; keyflag=0; Setflag=0;}  else {KeyNum=0; wnd++; if(wnd>2) wnd=0; E2prom_write_user();}     break;     //短按P1.0 键值为2     菜单窗口wnd切换
          -
          -
          -
        case 22:     KeyNum=0;  Low_Power = 101;         E2prom_write_user();   Setflag = 1;     break;      //长按P1.0 键值为22  这里给 Low_Power = 101;  进入上面的休眠部分,即   if(Low_Power > 100)    。            
        }
}                          




分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:123289 发表于 2023-5-19 15:15 | 只看该作者
【开机时】:需要定义一个标记B_ON,来识别当前状态是不是开机状态。
【按此键为菜单切换键,长按时休眠】:需要定义一个标记B_LONG,来识别长按与普通按。
【休眠后】:需要定义一个标记B_SLEEP,来识别当前状态是不是休眠中。
组合B_ON、B_LONG、B_SLEEP就可以达成你的需要,要点是如何决定这三个变量的0、1:
1、B_ON:开机时通过检查指定人RAM中不是不是特定的冷起动码,来修改B_ON值;或当你执行关机时,修改B_ON值,以便于下次识别开机;其它方法。
2、B_LONG:通过对按键按下的时间识别。
3、B_SLEEP:在进行休眠前、后修改。
要点:识别使用标记后,复位各标记。
回复

使用道具 举报

板凳
ID:57657 发表于 2023-5-19 18:16 | 只看该作者
楼主用的什么型号? 并不是所有IO口都可以外部中断。
回复

使用道具 举报

地板
ID:213173 发表于 2023-5-25 15:53 | 只看该作者
芯易德的MCU没有用过,既然是51的那就差不多,把管脚定义改一下就应该能用。这个示例是按STC15编写的,也适用于STC8系列。消除按键外部中断唤醒后误读按键的缺陷,实际就是加电正常工作,按键正常操作。当长按达1秒MCU睡眠。再按按键不论长短都能唤醒,但必须松手后才能进入正常工作状态,避免按键扫描函数误将外部中断唤醒当做正常操作。其实就加了一个识别标志。这个按键扫描函数只写了1个键,实际可以用于N个键的长短按。 一键开关机(掉电唤醒).rar (12.49 KB, 下载次数: 8)

回复

使用道具 举报

5#
ID:146507 发表于 2023-7-10 16:47 | 只看该作者
你是不是长按关机没有判断IO口松开就进入休眠程序了,然后IO口又是低电平唤醒,所以会不断的开机
回复

使用道具 举报

6#
ID:111463 发表于 2023-7-10 16:54 | 只看该作者
1. 要注意该单片机从休眠唤醒后是会复位还是在之前程序中接着运行
2. 要做好程序的健壮性,避免多次唤醒或重复进入中断
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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