07-中断系统与外部中断应用

外部中断的基本操作与应用

关于51单片机的中断系统
一般来说,51单片机有5个中断源(忽略定时/计数器2),分2个优先级,这个5个中断源按照自然优先级从高到低依次为:
外部中断0INT0

定时/计数器0TF0

外部中断1INT1

定时/计数器1TF1

串口中断RI/TI

下面一图将充分说明51单片机的中断系统结构:

171231xqxwduha6qx6hfff.jpg.thumb

每个中断源都对应着一个固定的入口地址,也就是中断向量,它们依次是:

0 0x0003INT0
1 0x000BTF0
2 0x0013INT1
3 0x001BTF1
4 0x0023RI/TI

也就是说,不管主程序执行到什么地方,只要外部中断1产生请求,内核要响应该中断,就会到0x0013这个地址去执行代码。如果你是在使用汇编语言进行程序开发的时候,你需要记住每个中断源对应的地址;如果你使用的是C语言,你只需要记住中断源的顺序就可以了,也就是最左边的中断号

3、中断相关的寄存器
中断相关的寄存器有4个,每个寄存器都是可以位寻址的,这该编程带来了方便。 其中2个为控制寄存器:IE寄存器IP寄存器

165617a1cwsz3qkjthbn8f.png.thumb

另外2个为中断请求标志:TCON寄存器SCON寄存器

205324oahcr5z126920711.png.thumb

4、关于中断服务函数程序的编写
一般情况下,中断的处理函数有两个,其一为中断初始化函数,其二为中断服务函数。初始化函数就是一个普通的函数,而中断服务函数却有特殊的格式要求:
<1> 中断函数没有返回值,也不能带参数。
<2> 函数名后面要跟一个关键字interrupt,说明这是一个中断服务函数。
<3> 在关键字interrupt后面要跟上中断号,说明这个中断服务函数是为那个中断服务的。

中断服务函数的格式为:
void 函数名() interrupt 中断号
{ ----函数体---- }
我们要利用定时器0来进行间隔定时,中断程序架构我们C语言可以这样写:

165742v1q9l997b455bb5q.png.thumb

20231005144114

由上可知将J5跳帽接到2~3脚,S5按键可以操作外部中断INT0

原理图如下:

20231005162624

方法一:

#include <REGX52.H>

sbit L1 = P0^0;
sbit L8 = P0^7;

// 延时函数
void Delay_ms(unsigned int xms) {
	unsigned int i,j;
	for(i = 0; i<xms; i++) {
		for(j=0;j<299;j++);
	}
	
}
// 10us
void Delay(unsigned int t) {
	while(t--);
	while(t--);
	while(t--);
}

void _74HC138(unsigned char n) {
	switch(n) {
		case 4:P2=(P2 & 0x1f) | 0x80;
		break;
		case 5:P2=(P2 & 0x1f) | 0xa0;
		break;
		case 6:P2=(P2 & 0x1f) | 0xc0;
		break;
		case 7:P2=(P2 & 0x1f) | 0xe0;
		break;
	
	}

}
void SystemInit(void) {
	_74HC138(5);
	P0=0X00;
	_74HC138(4);
	P0 = 0XFF;
}
void Working(void) {
	_74HC138(4);
	L1 = 0;
	Delay_ms(1000); // 1us = 1000ms
	L1 = 1;
	Delay_ms(1000);

}

void Init_INT0() {
	// 源类型选择器
	// IT0 = 0; 低电平触发, IT0=1;下降沿触发
	IT0 = 1;
	// 中断使能
	EX0 = 1;
	// 打开总中断
	EA = 1;
	
}

void main(void) {
	SystemInit();
	Init_INT0();
	while(1) {
		Working();
	
	}
}


// 由于P3_2口和INT0引脚一致
void Int0_Routine(void) interrupt 0 {
	L8 = 0;
	Delay_ms(1000);
	L8 = 1;
	Delay_ms(1000);
}

方法二:

#include <REGX52.H>

sbit L1 = P0^0;
sbit L8 = P0^7;

// 延时函数
void Delay_ms(unsigned int xms) {
	unsigned int i,j;
	for(i = 0; i<xms; i++) {
		for(j=0;j<299;j++);
	}
	
}
// 10us
void Delay(unsigned int t) {
	while(t--);
	while(t--);
	while(t--);
}

void _74HC138(unsigned char n) {
	switch(n) {
		case 4:P2=(P2 & 0x1f) | 0x80;
		break;
		case 5:P2=(P2 & 0x1f) | 0xa0;
		break;
		case 6:P2=(P2 & 0x1f) | 0xc0;
		break;
		case 7:P2=(P2 & 0x1f) | 0xe0;
		break;
	
	}

}
void SystemInit(void) {
	_74HC138(5);
	P0=0X00;
	_74HC138(4);
	P0 = 0XFF;
}
void Working(void) {
	_74HC138(4);
	L1 = 0;
	Delay_ms(1000); // 1us = 1000ms
	L1 = 1;
	Delay_ms(1000);

}

void Init_INT0() {
	// 源类型选择器
	// IT0 = 0; 低电平触发, IT0=1;下降沿触发
	IT0 = 1;
	// 中断使能
	EX0 = 1;
	// 打开总中断
	EA = 1;
	
}
unsigned char stat_int = 0;
void LED_INT() {
	if(stat_int == 1) {
	L8 = 0;
	Delay_ms(1000);
	L8 = 1;
	Delay_ms(1000);
	}
	stat_int = 0;
}
void main(void) {
	SystemInit();
	Init_INT0();
	while(1) {
		Working();
		LED_INT();
	}
}






// 由于P3_2口和INT0引脚一致

void Int0_Routine(void) interrupt 0 {
	stat_int = 1;
}
posted @ 2023-10-05 16:33  夏日清凉~  阅读(83)  评论(0编辑  收藏  举报