蓝桥杯单片机竞赛学习计划(六)

蓝桥杯单片机学习计划之中断


前言

在上一节中,简单介绍了定时器的相关内容,一起学习并使用了定时器实现LED灯闪烁,那么在这一节中,我们就来一起学习一下中断。


一、中断是什么?

STC15系列单片机用户手册中的第六章,介绍了中断系统,里面讲的很详细:
在这里插入图片描述
但是理解起来可能比较困难,所以我举一个例子方便大家理解:假如我正在电脑上打游戏,这时候门铃响了,原来是快递小哥来送快递了,那么这时候我就要先暂停游戏,去开门取快递,取完快递再返回来打游戏,其中取快递的过程就是中断过程。我本来在电脑上打游戏打的好好的,但这时候发生了比打游戏更重要的事情——拿快递,那么我就要暂停游戏,先去处理拿快递这个事情,拿完快递再来继续打游戏。即在做一件事情的时候发生了一件更重要的事情去做,这时候就需要先去处理更重要的事情,处理完毕再返回来处理之前的事情,这就是中断。在单片机中,假如此时此刻正在while循环中执行某段程序,这时候发生了中断,有了更重要的程序去执行,那么单片机就会先暂停当前执行的程序,转而去处理更重要的程序,处理完毕后再回来原来被打断的程序中继续执行,这就是单片机的中断过程。
那么单片机要如何触发中断呢?或者说有什么紧急事件能够产生中断呢?
看下面这张图:
在这里插入图片描述
可以从上图中看到,STC15F2K60S2一共有14个事件可以触发中断,这一节我们先学习定时器0中断。

二、定时器0中断

1.如何触发中断?

那么定时器0要怎么样才能触发中断呢?很简单,下图中描述了各个中断的触发行为,可以看到定时器0溢出的时候就会触发中断,这里的溢出上一节讲过,就是TH0和TL0两个寄存器都为255时,再加1就会产生溢出,这时候就会触发中断。
在这里插入图片描述

2.定时器0中断相关的寄存器

关于定时器0中断相关的寄存器,我们只需要看中断允许寄存器IE其中的两位EA和ET0,先来看ET0,T0的溢出中断允许位,T0就是定时器0,这一位就是控制着定时器0中断的开关,只有这一位为1,定时器0中断才能使用,否则无法使用。再来看EA,这一位是总中断允许位,即如果这一位为0,即使ET0=1定时器0也无法开启中断,相当于是有两个开关来控制定时器0中断,只有EA和ET0这两个开关都打开时(都为1),定时器0才能够触发中断。
在这里插入图片描述
再来看下面这张中断结构图,红圈中的就是定时器0的中断结构,我们可以看到定时器0中断结构中有三个开关,第一个ET0、第二个EA,第三个我们暂时不去管它,从结构图中我们能清晰的看出ET0和EA这两个开关的作用,只有这两个开关同时闭合,定时器0才能产生中断,否则只要有一个断开,就无法产生中断。
在这里插入图片描述
到这里大家可能会有疑问,那么中断程序怎么进入呢?其实手册中都已经写好了,我们来看下图:
在这里插入图片描述
我们暂时不需要去纠结这个中断程序是怎么来的,为什么要这样写,只需要直接照这个敲入代码中就可以了,下面来写程序

三、代码

这个程序中结合了之前写过的数码管和按键程序,数码管扫描和按键消抖都不再使用延时了,而是利用定时器进行处理。实现的功能是按一下S7按键,数码管上显示的数字会加1。

#include <STC15F2K60S2.H>
#include "intrins.h"
sbit S7 = P3^0;

unsigned char SEG_Code[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};//0-9段码
unsigned char SEG_Buf[8];//显示数据缓冲区
unsigned int seg_num;
bit timer_flag_1ms;

void Key_scan()
{
	static bit key_backup=1;
	static unsigned char shake_cnt=0;
	if(timer_flag_1ms)//1ms刷新
	{
		timer_flag_1ms=0;
		if(S7 != key_backup ) //当前按键状态和上一次状态不同,说明按键有动作
		{
			if(++shake_cnt>=50)//50ms消抖
			{
				shake_cnt=0;
				if(S7 != key_backup)//再次判断是否不同
				{
					if(key_backup==1)//上一次状态为1,说明当前按键是按下
					{
						seg_num+=1;
					}
					key_backup=S7;//保存当前按键状态
				}
			}
		}
	}
}
void Seg_Display()//数码管扫描函数
{
	static unsigned char seg_index=0;//显示数据索引
	static unsigned char seg_temp=0x01;//位索引
	
	P2 = (P2&0x1f) | 0xC0;  //消隐
	P0= 0x00;
	P2=0x00;
	
	P2 = (P2&0x1f) | 0xE0;//选通段锁存器
	P0=SEG_Code[SEG_Buf[seg_index++]]; //送入段码
	P2=0x00;
	
	P2 = (P2&0x1f) | 0xC0;//选通位锁存器
	P0= seg_temp;//送入位码
	P2=0x00;
	seg_temp<<=1;
	if(seg_index>7)
	{
		seg_index=0;
		seg_temp=0x01;
	}
}

void main()
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0=1;//开启定时器0中断
	EA=1;//开启总中断
	while(1)
	{
		Key_scan();
		SEG_Buf[4]=seg_num/1000;
		SEG_Buf[5]=seg_num%1000/100;
		SEG_Buf[6]=seg_num%100/10;
		SEG_Buf[7]=seg_num%10;
	}
}
void Timer0_Rountine(void)   interrupt 1    //定时器0中断,1ms
{
	timer_flag_1ms=1;
	Seg_Display();//使用定时器进行数码管扫描
}
  • 29
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值