和普通程序的 区别: 普通程序(如一个 子函数) 调用完了 , 临时数据 就 不需要了, 分配的 内存 空间 就 回收了, 而 驻留程序 是 要保留这些的
驻留 程序 主要 用于 中断函数 , 非中断函数 也 有应用,较少。分别举个例子:
1)用于 中断:
假设 一个 用 定时器 做的 时钟函数,定时器 设置为 1s一个中断。
main()
{
显示 时间 hour,min,sec; // 循环 刷屏显示
}
中断函数
{
sec++
if(sec>=60)
{
sec=0
min++
}
if(min>=60)
{
min=0
hour++
}
if(hour>=24)
{
hour=0
}
}
这时候 就能看出, 中断程序 在 运行完的 时候 不能 把 3个 变量 清空, 因为 下次 中断 还要用到 上次的 值, 这个程序 要 一直 驻留 内存;
2)再来个 普通 函数的
假设 做了一个程序 ,程序中 有一个 函数aa,而 函数 aa 我只能 让它执行 3次就得 关闭程序(这个 用在 密码 验证上)
aa()
{
密码验证次数n+1
返回n 和 验证结果
}
那这个 aa函数 在 密码 验证 阶段 就要 常驻 内存
#i nclude <absacc.h> // 包含头文件#i nclude <reg51.h>
#i nclude <intrins.h>
#define Z8279 XBYTE[0xFF82] //定义外部命令口
#define D8279 XBYTE[0xFF80] //定义外部数据口
#define LEDMOD 0x10 //定义显示模式
////************************powered by [email protected] ***************************/////
#define LEDFEQ 0x38 //定义8279工作频率
#define LEDCLS 0xD1 //清除显示
#define LEDWR0 0x90 //写端口命令
#define READKB 0x40 //读端口命令
#define REIN 0 //定义一些常见的提示信息
#define DONE 1
#define IN1234 2
#define IN2 3
#define IN4 4
#define uchar unsigned char
sbit P11_2=P1^2 //程序运行指示
sbit l1=P1^0//灯L1控制
sbit l2=P1^1// 灯L2控制
unsigned char hour1=0,hour2=0,min1=0,min2=0,sec1=0,sec2=0,num_20//时 分 秒的十位和个位,初值为零
uchar led[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71}//定义0 到F的键码
uchar beetime[]={8,0,11,30,12,30,17,0} //定义闹铃时间
void test8279(void) //测试及初始化led函数
void delay(uchar) //延时程序
void view8279(void)//显示数据
void changh(void)//改小时
void changm(void)//改分钟
void changs(void)//改秒
void chang_bee(void)//改闹铃时间
void viewmsg(uchar msg)//显示提示信息,本程序中为空,留作扩展用
bit havekey(void) //判断有无键按下
uchar getkey(void) //读键值
bit view_flag=1 //是否刷新显示标志,默认显示
////************************powered by [email protected] ***************************/////
void main()//主程序
{uchar keyval,i
bit temp,bee_temp
SP=0x60 //堆栈底指针,可省略
test8279()
TMOD=0x01 //计时器初始化
TH0=0x4B//50ms初值
TL0=0xFC
IE=0x82
TR0=1 //启动计时器
num_20=20 //循环20个50ms
l1=0 //灯默认是灭的
l2=0
////************************powered by [email protected] ***************************/////
while(1) //循环判断是否是闹铃中的一个,是则坐相应操作,否则跳过
{
for (i=0i<4i++)
{ bee_temp=(hour1*10+hour2)==beetime[i+i] &&(min1*10+min2)==beetime[i+i+1] &&sec1==0 &&sec2==0
if (bee_temp)
{ switch(i)
{
case 0: //1亮2秒 ,2灭
l1=1delay(2)l1=0break
case 1: //1亮2秒,2亮
l1=1l2=1delay(2)l1=0break
case 2: //1亮两秒,2灭
l1=1l2=0delay(2)l1=0break
case 3: //1亮2秒,2亮10分钟
l1=1l2=1delay(2)l1=0delay(3)delay(3)delay(3)delay(3)delay(3)delay(3)delay(3)l2=0break
default:
}
}
} //end for
P1_2=~P1_2 //取反
temp=havekey() //读键
if (temp)
{keyval=getkey()
switch (keyval)
{ case 40 ://change hour
EA=0
changh()
EA=1
break
case 41 ://change minute
EA=0
changm()
EA=1
break
case 42: //change second
EA=0
changs()
EA=1
break
case 43: //change bee time
view_flag=0
chang_bee()
view_flag=1
break
default :
}
EA=1
}
} //end while
}
////************************powered by [email protected] ***************************/////
void changh(void)
{uchar i,j
bit flag
flag=1
while(flag) //读两个数,直到符合要求,并赋值
{ i=getkey()
j=getkey()
if ((i*10+j)<24 ) //判断是否符合要求
{hour1=i //修改相应值
hour2=j
viewmsg(DONE)
flag=0
}
else viewmsg(REIN)
} //end while(flag)
}
void changm(void)
{uchar i,j
bit flag
flag=1
while(flag) //读两个数,直到符合要求,并赋值
{
i=getkey()
j=getkey()
if (i<6 &&j<10 ) //判断是否符合要求
{ min1=i//修改相应值
min2=j
viewmsg(DONE)
flag=0
}
else viewmsg(REIN)
}
}
void changs(void)
{uchar i,j
bit flag
flag=1
while(flag) //读两个数,直到符合要求,并赋值
{
i=getkey()
j=getkey()
if (i<6 &&j<10 ) //判断是否符合要求
{ sec1=i //修改相应值
sec2=j
viewmsg(DONE)
flag=0
}
else viewmsg(REIN)
}
}
void chang_bee(void)
{ uchar key,h1,h2,s1,s2,temp1,temp2
bit flag
viewmsg(IN1234)
key=getkey() //再次读一个键 1234分别修改第1-4个闹钟时间
while (key<1 || key>4)
{viewmsg(REIN)
key=getkey()
}
////************************powered by [email protected] ***************************/////
flag=1
while(flag) //读4两个数,直到符合要求,并赋值
{ viewmsg(IN4)
h1=getkey()
h2=getkey()
s1=getkey()
s2=getkey()
temp1=h1*10+h2
temp2=s1*10+s2
if (temp1<24 &&temp2<60 ) //判断是否符合要求
{beetime[key+key-2]=temp1//修改相应值
beetime[key+key-1]=temp2
viewmsg(DONE)
flag=0
}
else //viewmsg(REIN)
}
}
bit havekey(void)
{uchar temp
temp=Z8279 //读外部端口
return(temp &0x0F) //返回非零为有键
}
uchar getkey(void)
{uchar temp
while (1)
if (havekey())
{
Z8279=READKB //写读数据口命令
temp=D8279 //读数据口
break
}
return(temp) //返回所读值
}
////************************powered by [email protected] ***************************/////
void viewmsg(uchar msg) //显示提示信息,本程序中为空,留作扩展用
{ switch (msg)
{ case REIN :
break
case DONE :
break
case IN1234:
break
case IN2:
break
case IN4:
break
default :
}
}
void delay(uchar n)
{
unsigned int i
for (i=1i<20000*ni++)
}
void test8279(void)
{uchar i
Z8279=LEDMOD //初始化
Z8279=LEDFEQ
Z8279=LEDWR0
for (i=0i<8i++) //每个led均显示8
D8279=0xFF
delay(2) //延时
Z8279=LEDCLS //清零
Z8279=LEDWR0
}
void view8279(void)
{ if (view_flag) //在正常显示情况下显示各位数字
{Z8279=LEDWR0
D8279=led[sec2]
D8279=led[sec1]
D8279=0x40
D8279=led[min2]
D8279=led[min1]
D8279=0x40
D8279=led[hour2]
D8279=led[hour1]
}
}
void timeint(void) interrupt 1 //中断程序
{
TH0=0x4B
TL0=0xFC
num_20--
if (num_20!=0) return //没有二十次则返回
if (sec1==5 &&sec2==9)
{ sec1=0
sec2=0
if (min1==5 &&min2==9)
{ min1=0
min2=0
if (hour1==2 &&hour2==3)
{hour1=0
hour2=0
}
else if (hour2==9)
{hour1++
hour2=0
}
else hour2++
}
else if (min2==9)
{min1++
min2=0
}
else min2++
}
else if (sec2==9)
{sec1++
sec2=0
}
else sec2++
num_20=20
view8279() //显示数值
}
一闪而过是程序自动结束,同时编译器没有提供结果驻留功能。对于此种情况,可以手动在代码结尾增加驻留功能的函数。常用的有如下两种:1 通过getch函数驻留。
getch会等待从屏幕的输入,在main函数退出前,增加
getch()
调用,系统会等待输入,直到有新的输入,才会退出界面。
2 通过system("pause")来实现驻留。
在main退出前调用
system("pause")
会调用系统的pause函数,提示并实现按任意键退出程序效果。
如果是已经编译好的C语言程序,可以通过开始->运行,键入cmd后回车。
在打开的命令行窗口,将可执行文件拖动到窗口上,再回车即可运行该程序,在此窗口不会出现闪退,从而观察运行结果。
由于该问题仅在windows平台出现,所以以上介绍均针对windows平台。