51单片机中如何通过一个按键实现暂停与恢复?需要一个编程的思想

背景是这样的:我采用矩阵式键盘,有十二个键执行不同的任务。有很多循环。
现在我需要一个按键,这个键的功能就是,我那十二个任务不论执行到什么地方,只要暂停建按下,那么程序原地踏步,按其他键都不管用,再按暂停键恢复到原来的地方。

1、创建项目文件。

2、按键:S1=P3^2,点亮: led=P1^5。

3、创建C语言主函数。

4、创建循环效果,检测效果。

while(1)   

{

}

5、创建选择效果。

6、当按下时,即暂停与恢复。

温馨提示:答案为网友推荐,仅供参考
第1个回答  推荐于2017-09-21
有以下几种情况:
1.循环查询按键。当按键按第一次时间,进入第一层循环查询语句内部,执行恢复。不跳出该层循环,继续查询按键。当第二次按下时间,进入第二层循环查询语句内部,执行暂停。循环结束。若想反复暂停和恢复,就在外面再加一层while(1)类似的死循环,反复执行其内部的两层循环查询语句。
2.用一个标志变量,记住按键的状态。初始化为个值,如“暂停”,按键之后检查标志变量,是“暂停”就执行“恢复”,再让它变为“恢复”说明当前已经执行了恢复。反之亦然。
3.掉电暂停。这样需要按键能触发cpu工作。所以,需要按键接到外部中断上面。中断后可以恢复CPU工作。在中断中再判断是否要让cpu掉电与否。
不知道这种方法你能接受不?还是用外部中断。此按键触发中断后,关掉所有其他的中断,也即EA=0(最好先用个变量记住EA,方便恢复),然后就一直在中断中等待该按键第二次按下再恢复EA,最后退出中断。追问

谢谢大侠,你给的答案最全面。我考虑了一下,适合我用的只能是方式三了。请问,掉电模式和空闲模式有何区别?暂停后如何恢复?一个按键如何具体操作?

追答

空闲模式是指CPU不再执行程序,但是片内的外围电路(如定时/计数器,中断控制电路,串口)仍然工作。掉电模式是指当进入掉电模式时,执行最后一条指令后,振荡器停止,cpu不工作了,可以将电压降低到2V,片内RAM和SFR的值保持原值。终止空闲模式有两种方法:a.任何使能的中断,程序自动从中断服务程序处恢复。b.硬件复位。终止掉电模式:要先将电压恢复至cpu正常工作电压,再进行下列方法:A.硬件复位,这种复位不像正常复位一样RAM,SFR的值都恢复为默认值,而是能保存RAM掉电前的值,SFR就不能了。B. 外部中断0或1被触发,前提是他们要被使能,并且为电平触发。中断服务中不能有其他语句,直接返回(汇编RETI指令),cpu就恢复执行掉电执行指令后的下一条指令。
具体怎么控制,你看PCON寄存器吧,很容易。PD=1,进入掉电模式,IDL=1进入空闲模式。
按照你的意思,要使用外部中断恢复比较好。那个按键就接到外部中断上面吧。
外部中断终止掉电模式,RAM与SFR都能保存的。硬件复位是只能保存RAM。

追问

试了几次,发现PCON寄存器不能进行位操作哦~~~如何每次给PD取反?若是不能这样那就不能用一个按键控制了呀

追答

给你说PD与IDL位,并不是让你进行位寻址啊。它的地址是0x87,不可以进行位寻址的。
设置方法:
1.比如想让第n位置1,可以写PCON=PCON|(1<<n);//要置位的位与1相或,其他不变的与0相或。若置位第三位,与0x40相或,即二进制0000 0100
2.若是想把第n位清零,可以写PCON=PCON&(~(1<<n));//要清零的位与0相与,其他不变的与1相与。若清第三位,则与0xFB相与,即二进制1111 1011
3.若是想检测PD的值,PCON&0x02就是PD的值了;判断它是1还是0,然后做相应操作。取反也就是,是1清零,是0置1。

追问

暂停的问题我解决了,但是还是不能用一个键处理,用的两个键~~~两个外部中断源一个用来进入掉电模式,一个用来唤醒单片机恢复工作。
部分程序如下:
void int_0() interrupt 0 using 0
{
PCON=0x02;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}
void int_1() interrupt 2 using 1
{
;
}
还是没能一个键处理,您看有改进的余地么?

追答

void int0() interrupt 0
{
IE0=0;//我用的是电平触发,需要软件清中断标志
delay();//简单的防抖动方式,你自己随便定义就行,对于普通按键能延迟100ms-300ms为好
if(pp==0x02)
{
pp=0;//清零,为唤醒时防止再次进入掉电做准备
PCON|=0x02;//进入掉电
}
else pp=0x02;//为下次进入掉电做准备
}
/*
pp定义为全局变量
编程思想:掉电仍能保持RAM,那就用个值来记录是此次中断是该掉电还是的唤醒。毕竟掉电与唤醒都是中断,所以要分清楚。它定义为全局变量就可以了。
*/

本回答被提问者采纳
第2个回答  2011-05-09
就是使用51的中断就可以了!
你的其他12个按键也可以使用中断来处理,只是把那个暂停键设为级别最高,不管什么情况下改建按下就到该键的子程序运行(注意此时要关闭中断功能、只是判断该暂停键是否第二次按下),若按下就跳到原来暂停前的位置即可,并开启中断!
看是这个意思吗!
第3个回答  2011-05-09
你说的暂停是指的,程序不执行其他操作?若是,请接着看
设定一个标志,当程序始终停滞在这个位置,或者是不执行其他程序,这个标志设为1时,此时执行空语句;当按键时,触发中断,把标志清零。追问

谢谢大侠的回答。我的暂停是:程序在执行其他任何动作的时候,只要一按这个键,自动停住原地踏步。再按,返回到原程序继续执行。你给的答案暂时应该不能解决这个问题哦

第4个回答  2011-05-09
推荐暂停 用 掉电模式追问

嗯,谢谢大侠。答案很好。有人也这么给我说过。只是我以前还没用过掉电模式,请问具体操作?而且,用掉电模式一个键能处理的来么?我怎么想都需要两个键哦...

追答

你看下PCON这个寄存器 其实很简单 写个数据就行了 至于一个按键 你用一个全局整型变量 每次按键中断取反即可

追问

我刚刚看了下关于掉电模式工作的资料,似乎有点问题,因为掉电了之后(PCON口的PD位置1)要退出掉电方式的唯一方法是由硬件复位,复位后所有寄存器的内容都初始化了呀~~~不能满足我的要求哦~~~但是空闲工作方式似乎又可以。大侠能否看看我补充的问题给出解决方法?

追答

我刚试了一下 外部中断可以退出掉电模式 你试试 空闲模式也行 只是定时器不会停止

追问

我试了一天,外部中断没办法跳出掉电模式啊。大侠能把你的中断程序给我看看么?

追答

测试附带的是数码管 方式可能和你不同 你参考下

#include

sbit duan=P2^6;
sbit wei=P2^7;
code char table[]={0x3f,0x6,0x5b,0x4f,0x66,
0x6d,0x7d,0x27,0x7f,0x6f,0x77,0x7c,0x39,0x5e,
0x79,0x71};

char bai,shi,ge,m;
long num;

void delayms(int k)
{
int i,j;
for(i=k;i>0;i--)
for(j=110;j>0;j--) ;
}

void main()
{
TMOD=0x01;
TH0=0;
TL0=0;
EA=1;
EX0=1;
EX1=1;
IT0=1;
IT1=1;
ET0=1;
TR0=1;
while(1)
{
wei=1;
P0=0xf7;
wei=0;

duan=1;
P0=table[bai];
duan=0;

delayms(5);

wei=1;
P0=0xef;
wei=0;

duan=1;
P0=table[shi];
duan=0;

delayms(5);

wei=1;
P0=0xdf;
wei=0;

duan=1;
P0=table[ge];
duan=0;

delayms(5);
if(ge==7){ge=0xff;ET0=0;PCON=0x02;}
}
}

void gfds() interrupt 1
{

m++;
if(m==10){m=0;
bai=num/100;
shi=num%100/10;
ge=num%10;

num++;
if(num==1000)num=0;
}

}

void adsa() interrupt 0
{}

void sfff() interrupt 2
{}

相似回答