标题:
遇到了一个奇怪的单片机程序问题,百思不得其解
[打印本页]
作者:
zhth1979
时间:
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) 。
}
}
作者:
yzwzfyz
时间:
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:在进行休眠前、后修改。
要点:识别使用标记后,复位各标记。
作者:
npn
时间:
2023-5-19 18:16
楼主用的什么型号? 并不是所有IO口都可以外部中断。
作者:
wulin
时间:
2023-5-25 15:53
芯易德的MCU没有用过,既然是51的那就差不多,把管脚定义改一下就应该能用。这个示例是按STC15编写的,也适用于STC8系列。消除按键外部中断唤醒后误读按键的缺陷,实际就是加电正常工作,按键正常操作。当长按达1秒MCU睡眠。再按按键不论长短都能唤醒,但必须松手后才能进入正常工作状态,避免按键扫描函数误将外部中断唤醒当做正常操作。其实就加了一个识别标志。这个按键扫描函数只写了1个键,实际可以用于N个键的长短按。
一键开关机(掉电唤醒).rar
(12.49 KB, 下载次数: 9)
2023-5-25 15:52 上传
点击文件名下载附件
作者:
SuperZ
时间:
2023-7-10 16:47
你是不是长按关机没有判断IO口松开就进入休眠程序了,然后IO口又是低电平唤醒,所以会不断的开机
作者:
sbskywalker
时间:
2023-7-10 16:54
1. 要注意该单片机从休眠唤醒后是会复位还是在之前程序中接着运行
2. 要做好程序的健壮性,避免多次唤醒或重复进入中断
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1