符合中小企业对网站设计、功能常规化式的企业展示型网站建设
本套餐主要针对企业品牌型网站、中高端设计、前端互动体验...
商城网站建设因基本功能的需求不同费用上面也有很大的差别...
手机微信网站开发、微信官网、微信商城网站...
C51中断函数格式
创新互联建站主营昌邑网站建设的网络公司,主营网站建设方案,App定制开发,昌邑h5微信小程序开发搭建,昌邑网站营销推广欢迎昌邑等地区企业咨询
Keil C51编译器中断函数语法定义如下:
(C语言不用处理现场保护了) interrupt n ----这个是重点
void 函数名() interrupt n
{
}
//定时器T0中断
void 函数名() interrupt 1
{
}
C51编译器允许0~31个中断,下列中断及其相关地址为8051控制器所提供的中断:
0:EXTERNAL 0 地址:0003H
1:TIMER/COUNTER 0 地址:000BH
2:EXTERNAL 1 地址:0013H
3:TIMER/COUNTER 1 地址:001BH
4:SERIAL PORT 地址:0023H
编写中断函数时应遵循下列规则:
·不能进行参数传递。如果中断过程包括任何参数声明,则编译器将产生一个错误信息。
·无返回值。如果想定义一个返回值将产生错误,但是,如果返回整型值,编译器将不产生
错误信息,因为整型值是默认值,编译器不能清楚识别。
·在任何情况下,不能直接调用中断函数,否则编译器会产生错误。由于退出中断过程是由
指令RETI完成的,该指令影响MCS-51单片机的硬件中断系统,直接调用中断函数时,硬件
上没有中断请求存在,因而这个指令的结果是不定的,并且通常是致命的。
·编译器从绝对地址8n+3处产生一个中断向量,其中n为中断号,该向量包括一个中断过
程的跳转,向量的产生可由编译器控制指令NOINTVECTOR压缩,因而程序员可以从独立的汇
编模块中提供中断向量。
·可以在中断函数定义中使用using指定当前使用的寄存器组。格式如下:
void 函数名([形式参数])interrupt n [using m]
MCS-51单片机有四组寄存器R0~R7,程序具体使用哪一组寄存器由程序状态字PSW中
的两位RS1和RS0来确定。在中断函数定义时,可以用using指定该函数具体使用哪一组寄
存器,m在0,1,2,3这4个数中取值,对应四组寄存器组。例如:
void delay() interrupt 3 using 2
·在中断函数中调用的函数所使用的寄存器组必须与中断函数相同。当没有使用using指令
时,编译器会选择一个寄存器组作为绝对寄存器访问。程序员必须保证按要求使用相应寄存
器组,C编译器不会对此检查。
·如果在中断函数中执行浮点运算,必须保存浮点寄存器状态,当没有其他程序执行浮点运
算时,可以不保存。
驻留程序
通俗点讲
就是
程序运行完了,
还要保留
临时数据
和
运行状态,
等下一次
调用时
继续
执行
和普通程序的
区别:
普通程序(如一个
子函数)
调用完了
,
临时数据
就
不需要了,
分配的
内存
空间
就
回收了,
而
驻留程序
是
要保留这些的
驻留
程序
主要
用于
中断函数
,
非中断函数
也
有应用,较少。分别举个例子:
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函数
在
密码
验证
阶段
就要
常驻
内存
形式如下:
void 中断名(void) inerrupt 中断号 using 工作寄存器组
比如外部中断0
void ext0(void) interrupt 0 using 1 //后面的using 1可以省略,缺省为0
定时器1
void t1isr() interrupt 3
扩展资料:
单片机内部结构
1、CPU
它的名字没有改,还是称为CPU(Central Processing Unit)。它是单片机的核心部件,包括运算器和控制器。
运算器既是算术逻辑单元ALU(Arithmetic logic Unit),其功能是进行算术运算和逻辑运算。
控制器一般由指令寄存器、指令译码器、时序电路和控制电路组成。其作用是完成取指令、将指令译码形成各种微操作并执行指令,同时控制计算机的各个部件有条不紊地工作。
2、单片机内部结构之一ROM
“硬盘”,改了名字,称为程序存储器,也叫只读存储器。用ROM(Read only memery)表示。其作用和计算机的硬盘差不多,用来存放用户编写的程序。特点是:掉电后不会丢失数据(程序)。
对于C51单片机,其内部总共有五级中断源
分别为外部中断0、定时器0、外部中断1、定时器1及串行中断。
C51单片机的中断使用时,主要是通过中断服务号来决定的。
如你定义一个中断服务函数:
void KEY(void) intterrupt 0
{
}
当外部中断0申请中断时
会自动根据interrupt后面的0,找到上面定义的这个中断服务函数。
对于其他四个中断源,其对应的中断号分别为1、2 、3、4
首先你要写中断函数
然后在主程序中像调用子函数一样调用就可以了
举个例子吧
#define uchar unsigned char
#define uchar unsigned char
sbit D1=P1^0;
uchar aa;
void init()
{
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
}
void main()
{
init();
while(1)
{
if(aa==20)
{
D1=~D1;
aa=0;
}
}
}
void T0time()interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
aa++;
}
给你上个较完整的程序,可以直接在KEIL中运行并观察输出
/******************************************************************************
功能:
本程序在12M晶振模式下,通过定时器中断精确实现数字时钟计时操作,并在KEIL
中实现输出。时、分、秒的变化在定时中断里处理。
说明:
因采用工作方式2,自动装入初值,所以此程序计时很精确,只是在KEIL中模拟输
出显示的变化速度很快,这点可不理会
******************************************************************************/
#include
#include
#define
TEST
//此行用于KEIL输出显示,如果不需要显示可将其删除
typedef
unsigned
char
uchar;
typedef
unsigned
int
uint;
#define
TH0TL0_INIT
(256-250)
//定时器8位自动装入模式下寄存器初值,0.25ms中断一次
char
cHour;
//时
char
cMin;
//分
char
cSec;
//秒
uint
iCount;
//秒计数,计数达到4000时1s,4000*0.25ms
=1000ms
=
1s
bit
bSecChanged;
//秒发生变化标志,每秒送一次输出显示,送显完成后清0,提高主程序效率
//==============================================================================
//T0定时器中断服务程序,12M晶振下每0.25ms产生中断,本程序执行一次
//==============================================================================
void
Timer0()
interrupt
1
{
iCount++;
//秒计数值+1
if(iCount==4000)
{//时间计数达到1S
iCount
=
0;
//重新开始下一秒计数
cSec++;
//时钟:秒+1
bSecChanged
=
1;
//置秒发生变化标志
if(cSec==60)
{//计够60s
cSec
=
0;
//重新开始下一分计数
cMin++;
//时钟:分+1
}
if(cMin==60)
{//计够60分钟
cMin
=
0;
//重新开始下一小时计数
cHour++;
//时钟:小时+1
}
if(cHour==24)
{//计够24小时
cHour
=
0;
//重新开始第二天计数
}
}
}
//==============================================================================
//主程序
//==============================================================================
void
main()
{
uchar
outstr[10];
//输出字符串,我的编译器可能有问题,直接输出有错
TMOD
=
0X02;//工作方式2,8位自动重装计时模式
TH0
=
TH0TL0_INIT;
//0.25ms中断一次
TL0
=
TH0TL0_INIT;
//0.25ms中断一次
#ifdef
TEST
SCON
=
0x50;
/*
SCON:
mode
1,
8-bit
UART,
enable
rcvr
*/
TMOD
|=
0x20;
/*
TMOD:
timer
1,
mode
2,
8-bit
reload
*/
TH1
=
221;
/*
TH1:
reload
value
for
1200
baud
@
16MHz
*/
TR1
=
1;
/*
TR1:
timer
1
run
*/
TI
=
1;
/*
TI:
set
TI
to
send
first
char
of
UART
*/
#endif
cHour
=
0;
//时
cMin
=
0;
//分
cSec
=
0;
//秒
iCount
=
0;
//秒计数
bSecChanged
=
0;
outstr[2]
=
':';
//时分分隔符
outstr[5]
=
':';
//分秒分隔符
outstr[8]
=
0;
//字符串结束符
EA=1;
//开总中断
ET0=1;
//允许T0中断
TR0=1;
//启动T0
while(1)
{
if(bSecChanged==1)
{//秒发生变化,将时间值转换为可显示字符串准备送显示
bSecChanged
=
0;//清除标志,节省CPU资源
outstr[0]
=
cHour/10
+
0x30;
//将秒转换为ASCII码
outstr[1]
=
cHour%10
+
0x30;
outstr[3]
=
cMin/10
+
0x30;
//将分转换为ASCII码
outstr[4]
=
cMin%10
+
0x30;
outstr[6]
=
cSec/10
+
0x30;
//将小时转换为ASCII码
outstr[7]
=
cSec%10
+
0x30;
#ifdef
TEST
printf("
%s\r",outstr);
//在KEIL中显示时钟
#endif
}
}
}