C语言编写中断驻留程序

Python016

C语言编写中断驻留程序,第1张

驻留程序 通俗点讲 就是 程序运行完了, 还要保留 临时数据 和 运行状态, 等下一次 调用时 继续 执行

和普通程序的 区别: 普通程序(如一个 子函数) 调用完了 , 临时数据 就 不需要了, 分配的 内存 空间 就 回收了, 而 驻留程序 是 要保留这些的

驻留 程序 主要 用于 中断函数 , 非中断函数 也 有应用,较少。分别举个例子:

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平台。