C51单片机学习笔记(四)——单片机的中断系统及应用

C51单片机学习笔记(四)——单片机的中断系统及应用

1.单片机的中断系统

  • 中断的概念:
    CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理(中断产生);
    CPU暂时中断当前的工作,转去处理事件B(中断响应和中断服务);
    待CPU将事件B处理完毕后,再回到原来事件A中断的地方继续处理事件A(中断返回),这一过程称为中断。
    在这里插入图片描述
  • 引起CPU中断的根源叫做中断源。中断源向CPU的请求,叫做中断请求。
    CUP暂时中断原来的事务A,转去处理事件B。对事件B处理完毕后,再
    回到原来被中断的地方(即断点),称为中断返回。实现上述中断功能的
    部件称为中断系统(中断机构)。在这里插入图片描述
  • 51单片机的中断源:引起中断的事件称为中断源,51单片机一共有5个中断源,如下图:
  • 中断优先级:当单片机正在执行主程序时,如果发生了几个中断请求,单片机会由根据中断优先级寄存器的默认优先级进行处理,如下表:
    在这里插入图片描述
  • 中断嵌套:51单片机最多可以执行二级嵌套:
    在这里插入图片描述

2.中断需要设置的4个寄存器

  • 中断允许寄存器IE
    CPU对中断源允许或不允许,由中断允许寄存器IE控制,IE在特殊功能寄存器中,字节地址为A8H,编程时可对寄存器的每一位单独操作,单片机复位时IE的各个位全部变为0.
    在这里插入图片描述
    在这里插入图片描述
  • 中断优先级寄存器IP
    中断优先级寄存器IP在特殊功能寄存器中,字节地址为B8H,IP用于设定各个中断源属于两级中断中的哪一级,单片机复位时,IP全部赋值为0
    在这里插入图片描述
    在这里插入图片描述
    注意:高优先级中断可以打断低优先级中断而形成中断嵌套,同优先级中断之间不能形成嵌套,低优先级中断不能打断高优先级中断。一般情况下,中断优先级寄存器不需要设置,而采用默认设置。
  • 定时器、计数器工作方式寄存器TMOD:
  • TMOD在单片机内部的特殊功能寄存器中,字节地址为89H,不能位寻址(编程时不能单独操作各个位,只能采用字节操作),该寄存器用来设定定时器的工作方法及功能选择,单片机复位时,TMOD全部为0.
    在这里插入图片描述
    在这里插入图片描述
  • 中断控制寄存器TCON:
    TCON在特殊功能寄存器中,字节地址为88H,可以进行位寻址,该寄存器用于控制定时器/计数器的开启停止、标志定时器/计数器的溢出和中断情况,还可对外部中断进行设置,单片机复位时TCON全部为0.
    在这里插入图片描述
  • 中断系统的工作原理图:
    在这里插入图片描述
  • 中断程序的写法格式:
void 函数名() interrupt 中断号
{
	中断服务程序的语句
}

3.使用中断控制流水灯

#include<reg52.h>
#define uchar unsigned char
#define LED P2
void main()
{
	EA = 1;	 //中断允许寄存器IE中的总控制开关,EA=0代表允许产生中断
	EX0 = 1; //中断允许寄存器IE中的EX0=1代表允许INT0产生中断
	IT0 = 0; //中断控制寄存器TCON 当IT0 =0时,为电平触发方式,
	         //如果P3.2为低电平,则产生中断请求(我的单片机P3.2连的是按键6,所以当按键6被按下时,产生中断请求)
	
	LED = 0x0f; //使后四个LED灯亮

}
void Change_LED() interrupt 0
{
	LED = 0xf0;	 //使前四个LED灯亮
}

4.定时器T0和T1的工作方式1

  • 这里用到前面所展示的定时器和计数器的工作方式寄存器TMOD

    在这里插入图片描述
    • 工作方式1的计数位是16位,下面以T0为例说明(T1和T0方式1是一样的)。T0有两个寄存器TL0个TH0组成,TL0为低8位,TH0为高8位。
    • 启动T0后TL0便在机器周期的作用下从0000 0000开始计数每次加一,当TL0计满(1111 1111十进制255)时,再计一个到256,此时TL0清零,同时向TH0进一位,直到TH0也计满此时达到65535,再计一个数就溢出,产生中断请求,进入中断处理程序,同时TF0(中断标识位自动置1)中断程序执行完后,硬件将自动将TF0清0.

5.定时器控制流水灯

  • 下面用定时器做一个将发光二极管亮1s,熄1s,周期性闪烁
#include<reg52.h>
#define uchar unsigned char
#define LED P2
uchar num;
void main()
{
	LED = 0xf0;
	TMOD = 0x01;//将定时器0设为方式1,即16位定时器
	/*TH0中每增加1,就相当于计了256个数,所以TH0装入初值是对256取模,TL0是对256取余*/
	TH0 = (65536-45872)/256;//给定时器的高八位赋初值
	TL0 = (65536-45872)%256;//给定时器的低八位赋初值
	/*过程中不可能让其计65536个数,所以要给他赋初始值,单片机的晶振为11.0582MHz,机器周期为
	1.09us(计一个数的时间),若要每50ms产生一个中断,则要计数50000/1.09=45872,所以将其作为初值*/
	EA = 1;//开总中断
	ET0 = 1;//开定时器0中断
	TR0 = 1;//启动定时器T0
	while(1)
	{	   
		
		if(num == 20) //num=20代表用了50ms*20  = 1s
		{
			num = 0;
			LED = ~LED;
		}
	}
}
void T0time() interrupt 1
{
	TH0 = (65536-45872)/256;//重装初值
	TL0 = (65536-45872)%256;
	num++;			  //每发生一次中断后,num++,num等于几,用的时间就是几个50ms

}

6。按键+中断+流水灯实例

  • 要求,当按键按下时,流水灯停止流动,再次按下时,流水灯从原来的位置继续流动
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define LED P2
sbit S = P3^2;
int j;
uchar code table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
void init();
void key();
void delay(uint z);
void LED_display();
void main()
{
	init();
	while(1)
	LED_display();
}

void init()
{
	IT0 = 0; //设置低电平触发外部中断
	EA = 1;  //开总中断
	EX0 = 1;//开外部中断
	j = 0;
}
void key()
{
	if(S == 0)
	{
		delay(8); //按键消抖
		if(S == 0)
		{
			j++;
			if(j==2)
			j = 0;
		}
	}
	while(!S);
}
void delay(uint z) //延时函数
{
	uint x,y;
	for(x = z;x>0;x--)
		for(y=110;y>0;y--);
}
void LED_display()
{
	uint i;
	for(i=0;i<8;i++)   //数组控制流水灯
	{
		LED = table[i];
		delay(500);
	}
}
void stop() interrupt 0
{
	do{
		key();
	}while(j == 1);  //中断函数,当按键按下时中断

}

猜你喜欢

转载自blog.csdn.net/qq_40181592/article/details/88914454