从51到ARM裸机开发实验(007) AT89C51 中断实验

一、中断概念  

        对于单片机来说,中断是指CPU正在处理某一任务A时,发生了另外一件事件B,需要CPU迅速去处理(中断发生),CPU暂停当前的A任务(中断响应),转而去处理事件B(中断服务),待CPU将事件B处理完毕后,再回到原来任务A被中断的地方继续处理任务A(中断返回),这一套流程即称为“中断”。来实现这样一个场景:四个LED依次亮灭,时间间隔最小0.5秒,最大5秒,要求精确延时。使用两个按键分别控制间隔时间的增减,每按一次增或减0.5秒。精确延时用定时器中断实现,按键响应使用外部中断实现。

AT89C51单片机内部共有6个中断源,从上图可以看出,中断服务程序是可以再次被中断的,这就涉及到中断优先级问题,中断都可以打断正在执行的非中断任务,高优先级中断可以打断正在执行的比自己优先级低的中断服务程序,低优先级中断无法打断正在执行的比自己优先级高的中断服务程序,中断无法打断优先级相同的中断服务程序。AT89C51中断源如下表所示:

中断源说明默认中断优先级序号(C语言使用)入口地址(汇编使用)
INIT0外部中断0,由P3.2端口线引入,低电平或下降沿触发最高00003H
T0定时器/计数器0中断,由T0计数器计满回零触发第21000BH
INIT1外部中断1,由P3.3端口线引入,低电平或下降沿触发第320013H
T1定时器/计数器1中断,由T1计数器计满回零触发第43001BH
TI/RI串口中断,串口完成一帧数据发送或接收时触发第540023H
T2定时器/计数器2中断,由T2计数器计满回零触发最低5002BH

中断允许寄存器IE:
IE是一个八位寄存器,可以位寻址,每一位可进行单独操作,实现以下功能:

位序号位符号功能描述
D7EA

全局中断允许位。1:打开全局中断控制 0:关闭全部中断。

D6--保留
D5ET2

定时器/计数器2中断允许位。1:打开T2中断。0:关闭T2中断。

D4ES

串口中断允许位。1:打开串口中断。0:关闭串口中断。

D3ET1定时器/计数器1中断允许位。1:打开T1中断。0:关闭T1中断
D2EX1外部中断1中断允许位。1:打开外部中断1中断。0:关闭外部中断1中断
D1ET0定时器/计数器0中断允许位。1:打开T0中断。0:关闭T0中断
D0EX0外部中断0中断允许位。1:打开外部中断0中断。0:关闭外部中断0中断

中断优先级寄存器IP:
IP是一个八位寄存器,用来设定中断的优先级,具体可阅读对应的芯片手册。本次实验场景比较简单,不再对中断优先级做设定,使用默认的优先级。

定时器/计数器工作方式寄存器TMOD:
TMOD是一个八位寄存器,不能位寻址,用来确定定时器的工作方式及功能选择,复位时整个寄存器清零。每一位定义如下所示。低四位控制定时器/计数器T0,高四位控制T1。而T2的工作方式控制器为T2MOD,详见芯片手册,本场景中未使用到。

位序号位符号功能描述
D7GATE门控制位。GATE=0时,定时器/计数器启停仅受TCON寄存器中TRA(X=0/1)控制。GATE=1时,定时器/计数器启停仅受TCON寄存器中TRA(X=0/1)和外部中断引脚(INT0或INT1)上的电平状态来共同控制。
D6C/T定时器模式/计数器模式选择位。
D5M1M1M0工作方式选择位。00:方式0,为13位定时器/计数器。01:方式1,为16位定时器/计数器。10:方式2,8位初值自动重装的8位定时器/计数器。11:仅适用于T0,分成两个8位计数器,T1停止计数。
D4M0
D3GATE同上
D2C/T同上
D1M1同上
D0M0同上

定时器/计数器控制寄存器TCON:
IP也是一个八位寄存器,用来设定中断的优先级,具体可阅读对应的芯片手册。本次实验场景比较简单,不再对中断优先级做设定,使用默认的优先级。

根据定时时长设置定时器寄存器值:
对于T0来说,由TL0寄存器作为低8位、TH0寄存器作为高8位,组成16位的加1计数器。定时器一旦启动,它就会在原来的数值上开始加1计数,若程序开始时,没有设置TH0和TL0,则默认值是0,假设始终频率为12MHz,12个时钟周期为一个机器周期,此时及其周期是1us,计满TH0和TL0就需要2^16-1个数,再来一个脉冲计数器就会溢出,随即触发中断。因此从0开始到中断发生需要65536us,约65.5ms。如果需要50ms,就需要给TH0和TL0设置一个初值,初值基础上计数50000次,就会消耗约50ms。65536-50000=15536,即TH0和TL0中应装入的总数为15536。TH0为高8位,即15536/256。TL0为低8位,即15536%256。以后接触高等级的芯片,关于寄存器的设置会更复杂一些。本实验中采用的是11.0592M的晶振(为什么没有直接用12M的,是因为后面做串口实验的时候,11.0592M更有利于串口通信频率的设定),机器周期=12*(1/11059200)≈1.09us,若需要每个时间周期t=50ms,则N(计数周期)=50000/1.09≈45872。高8位TH0装入(65536-45872)/256,低8位TL0装入(65536-45872)%256。

外部中断控制:
外部中断的控制比较简单,打开中断,设置触发方式就可以了,包括低电平触发和下降沿触发。此处为了防止重复触发(抖动或者低电平持续时一直触发中断),采用了下降沿触发,为了消除抖动,下降沿触发后关闭外部中断,延时一段时间后再次打开。真实应用场景中,极少有按键直接连接触发外部中断引脚的情况,此处只为演示外部中断触发

二、仿真电路

LED模块的接法和《从51到ARM裸机开发实验(003) AT89C51 GPIO实验》中的接法相同。按键TIME+、TIME-分别接了P3.2、P3.3,即外部中断0和外部中断1。

三、程序设计

1、驱动程序

interrupt.h

#ifndef _INTERRUPT_H_
#define _INTERRUPT_H_
void set_interrupt_callback(int interrupt_num, void* isr_callback);
void timer0_isr();
void external0_isr();
void external1_isr();
#endif

interrupt.c

#include <reg52.h>
#include "interrupt.h"

void (*callback0)(); // 函数指针
void (*callback1)(); // 函数指针
void (*callback2)(); // 函数指针

//设置中断回调函数
void set_interrupt_callback(int interrupt_num, void* isr_callback){
	if(interrupt_num == 0){
		callback0 = isr_callback;
	}else if(interrupt_num == 1){
		callback1 = isr_callback;
	}else if(interrupt_num == 2){
		callback2 = isr_callback;
	}
}

//定时器0中断
void timer0_isr() interrupt 1
{
	callback1();
}

//外部中断0
void external0_isr() interrupt 0
{
	callback0();
}

//外部中断1
void external1_isr() interrupt 2
{
	callback2();
}

delay.h

#ifndef _DELAY_H_
#define _DELAY_H_
	void delayms(unsigned int xms);
#endif

delay.c

#include "delay.h"

void delayms(unsigned int xms){
	unsigned int i,j;
	for(i=xms;i>0;i--){
		for(j=110;j>0;j--);
	}
}

2、应用程序

application.h

#ifndef _APPLICATION_H_
#define _APPLICATION_H_
	void timer0_callback();
	void external0_callback();
	void external1_callback();
#endif

application.c

#include <reg52.h>
#include "application.h"
#include "interrupt.h"
#include "delay.h"

#define uchar unsigned char
#define uint unsigned int
sbit led1 = P0^0;
sbit led2 = P0^1;
sbit led3 = P0^2;
sbit led4 = P0^3;
#define MAX_CYCLE 100
#define MIN_CYCLE 10

uchar num;
uchar time_cycle = 10;

//主函数
void main(){
	set_interrupt_callback(0, &external0_callback);
	set_interrupt_callback(1, &timer0_callback);
	set_interrupt_callback(2, &external1_callback);
	TMOD = 0x01; //设置定时器0为工作方式1(M1M0为01)
	TH0=(65536-45872)/256;
	TL0=(65536-45872)%256;
	EA=1;		//开总中断
	EX0=1;	//打开外部中断0
	EX1=1;	//打开外部中断1
	IT0=1;	//INT0下降沿触发方式
	IT1=1;	//INT1下降沿触发方式
	ET0=1;	//开定时器0中断
	TR0=1;	//启动定时器0
	led1=0;
	while(1);
}

//定时器0中断回调函数
void timer0_callback(){
	TH0=(65536-45872)/256;
	TL0=(65536-45872)%256;
	num++;
	if(num>=time_cycle){
		num=0;
		if(led1 == 0){
			led1 = 1;
			led2 = 0;
		}else if(led2 == 0){
			led2 = 1;
			led3 = 0;
		}else if(led3 == 0){
			led3 = 1;
			led4 = 0;
		}else if(led4 == 0){
			led4 = 1;
			led1 = 0;
		}
	}
}

//外部中断0回调函数
void external0_callback(){
	EX0=0;				//关闭外部中断0
	delayms(10);	//延时
	if(time_cycle < MAX_CYCLE){
		time_cycle = time_cycle + 10;
	}
	EX0=1;				//打开外部中断0	
}

//外部中断1回调函数
void external1_callback(){
	EX1=0;				//关闭外部中断1
	delayms(10);	//延时
	if(time_cycle > MIN_CYCLE){
		time_cycle = time_cycle - 10;
	}
	EX1=1;				//打开外部中断1	
}

四、资料下载 

源码与仿真电路下载地址:https://download.youkuaiyun.com/download/qq_54140018/87761758

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值