中断函数是不需要额外通过代码调用的
东丽网站建设公司创新互联公司,东丽网站设计制作,有大型网站制作公司丰富经验。已为东丽1000+提供企业网站建设服务。企业网站搭建\成都外贸网站建设公司要多少钱,请找那个售后服务好的东丽做网站的公司定做!
当中断条件满足,单片机会打断当前执行的语句,跳转到中断函数,然后执行完中断函数后,再次返回之前被打断的语句继续执行
中断函数中,每次都会对定时器重新初始化,即头两句对TH1和TL1的赋值,这样每50ms会再次进入一次中断函数.每20次进入中断,即经过了1秒,然后对全局变量miao自增1
而main函数则是不断对变量miao进行输出
标准c语言没有中断调用机制,但是不同编译器都有相应的中断处理方式,可以使用户实现中断功能。
解决方案:
1、采取轮询的方式解决,就是每10毫秒检查一下是否有键盘请求,总的来说,这样基本上可以解决问题,而且简单易行,但每10毫秒都要检查,系统消耗太大。
2、采取中断的方式:
(1)用高级语言调用中断来处理问题。中断是cpu响应一个中断外围设备8259A的一个过程,当键盘敲击,cpu保存断点暂停执行并且跳到相应的中断处理程序继续执行,结束后根据断点再跳回来。通过这种方式可以轻松+愉快地解决这个问题。但是需要用到高级语言调用汇编,根据编译器的不同而有所差别。
(2)自己模拟中断。可以另外建立一个线程专门响应键盘的敲击,如果有敲击则打断主线程。这样做实现起来很复杂,而且涉及到不少复杂的关键技术,比如信号量之类的东西。
3、强大的vc
vc采取了消息映射的机制来处理外部设备的请求,比如时钟中断、键盘中断等等。通过此可以灰常灰常容易的处理外部中断。
在子程序中用While(一个全局变量){这里执行子程序的操作}
要中断时把这个变量设为0,
则那个子程序就退出了.
这里假设你的子程序是个重复反复执行的操作.如果不是,那么你的需求本身就是错的做法你需要重新评估你的设计合理性.
51的C语言中断是函数,那这个中断是否可以调用?如果能,怎么调用?
只从计算机原理来讲,是可以的。
理论上,中断函数也是一个程序的入口,只要把程序指令指针指向这个中断的入口地址,
就可以执行相应的代码,从这个角度来讲,是可操作的。
但在实际问题处理中,通常不行,因为中断是提供给系统处理应急事件的,
并非设计来作为常规函数呼叫。
如果只是想要使用中断处理中的某些功能,可把那些功能封装为独立的函数,
供给中断处理和一般流程来调用。
应用程序直接调用中断,是有违中断设计的初衷的,
不建议这样使用,易导致原本正常的流程的莫名异常,
因为调用中断处理,会占用中断的相关资源,导致正常的中断无法执行,出现异常。
//功能:99秒时钟
#includeAT89X51.H //包含头文件
#define uchar unsigned char //预定义关键词
#define uint unsigned int
#define ulong unsigned long
uchar tcount,secount; //定义全局变量
uchar code DISP[] //字形表
={0x28,0x7e,0xa2,0x62,0x74,0x61,0x21,0x7a,0x20,0x60};
//0,1,2,3,4,5,6,7,8,9
uchar code LED[] //位码表
={0xfd,0xfb,0xf7,0xef,0xdf,0xbf};
//P2.6,P2.5,P2.4,P2.3,P2.2,P2.1
/*****************************************************************************/
void DELAY_1MS(uint i) //延时1毫秒子程序
{
uchar j; //定义局部变量j
while(i--) //每循环一次,变量减一,为零返回
{
for(j=0;j123;j++); //循环123次
}
}
/*****************************************************************************/
void t0() interrupt 1 using 0//50毫秒定时器t0中断入口
{
tcount++; //定时器中断计数器加一
if(tcount==20) //计数20次
{
tcount=0; //清零定时器中断计数器
secount++; //秒计数器加一
if(secount==100) //秒计数器等于100
{
secount=0; //秒计数器清零
}
}
TH0=(65535-50000)/256; //重赋定时器初值高位
TL0=(65535-50000)%256; //重赋定时器初值低位
}
/*****************************************************************************/
void main() //主程序
{
TMOD=0x01; //初始化定时器t0,工作于方式1,16位定时器
TH0=(65535-50000)/256; //赋初值高低
TL0=(65535-50000)%256; //赋初值低位
TR0=1; //启动定时器t0
ET0=1; //允许定时器t0中断
EA=1; //开放总中断
tcount=0; //定时器中断计数器初始化
secount=0; //秒计数器初始化
while(1) //主循环
{
P0=DISP[secount/10]; //秒计数器十位送显示
P2=LED[4]; //点亮对应数码管
DELAY_1MS(2); //延时2毫秒
P0=DISP[secount%10]; //秒计数器个位送显示
P2=LED[5]; //点亮对应数码管
DELAY_1MS(2); //延时2毫秒
}
}
外部中断的常用功能
外部中断经常用来记录外部脉冲的个数,也就是当我们使用外部中断1时,如果想记录自身单片机的某个引脚的下降沿个数,只需用杜邦线把这个引脚和P3.3连接即可。
比如P2.3引脚产生这样的电平无规律跳转,则下降沿的个数为5
所以我们就用外部中断1来实现记录K4按键从按下到松手的抖动过程中经历了多少个下降沿,把下降沿的个数显示在数码管上。
2.程序思路
我们定义一个16位的全局变量pulse用来记录P2.3下降沿的个数,在中断函数中的任务就是简单的pulse自加,因为引脚遇到下降沿就会进入中断函数。
在主函数里就是负责数码管显示即可。
3.代码#include
#include //详见第六章第8讲
u16 pulse=0;
void main()
{
u16 x,PULSE_buf;
IT1 = 1; //下降沿触发模式
EX1 = 1;
EA = 1;
LED_Init();//初始化LED硬件模块
KEY_Init();//初始化按键功能模块
ShowNumber(pulse);
while(1)
{
SEG_Scan();
if(PULSE_buf!=pulse)ShowNumber(pulse);//pulse不再是前一次的值,也就是pulse数值更新了,所以数码管缓存区也要更新pulse的数值以便显示出来
x++;
if(x=50)//隔一段时间过来记录此时的pulse数值
{
x=0;
PULSE_buf=pulse;
}
}
}
//请把P3.3和P2.3用杜邦线连接起来
void EXTI1_IRQHandler() interrupt 2
{
pulse++;
}
大家多按几次K4,发现按下后松手的一个动作里有时pulse就自加了几次,显示在数码管上的数加了好几下。