中断的基本概念
百度百科上是这样说的,当中央处理机CPU正在处理某件事的时候外界发生了紧急事件请求,要求CPU暂停当前的工作,转而去处理这个紧急事件,处理完以后,再回到原来被中断的地方,继续原来的工作,这样的过程称为中断。通俗点说,就是当你在看书的时候有人敲门,这时你会打断看书去开门,之后再继续看书,这个过程就是中断。一般比较高级的单片机都会有中断嵌套,当CPU正在处理一个中断源请求的时候(执行相应的中断服务程序),发生了另外一个优先级比它还高的中断源请求。如果CPU能够暂停对原来中断源的服务程序,转而去处理优先级更高的中断请求源,处理完以后,再回到原低级中断服务程序,这样的过程称为中断嵌套。这里的中断嵌套在蓝桥杯比赛中并不常用,所以我们这里只需要了解一下就好。
我这里使用的是蓝桥杯4T的最新板子,使用的芯片是STC15F2K60S2系列。单片机提供了14个中断请求源,它们分别是:外部中断0(INT0)、定时器0中断、外部中断1(INT1)、定时器1中断、串口1中断、A/D转换中断、低压检测(LVD)中断、CCP/PWM/PCA中断、串口2中断、SPI中断、外部中断2(INT2)、外部中断3(INT3),定时器2中断以及外部中断4(INT4)。我们这里使用最多的是外部中断0、定时器0中断、外部中断1、定时器1中断、串口1中断。
中断系统的内部结构
如上图,我只是截取了我们比赛中使用比较多的几个中断,如果想了解更多请去看一下 STC15F2K60S2的使用手册。上图中的中断0和中断1为外部中断,它分为边沿触发(上升沿和下降沿)和电平触发(高电平和低电平),主要是通过外部信号触发中断(如按键)。使用中断前都需要初始化。例如外部中断初始化过程为:1、IT0=1(使用外部中断0)2、EX0=1(外部中断0开关闭合) 3、EA=1(总中断开关闭合)4、写中断服务函数(中断触发时,CPU执行的函数,执行后返回中断点)中断服务函数与其他函数不同,在写函数时后面需要加上中断号,如下图
外部中断的使用
开发板上的S5(P3^2)按键连接到外部中断0(INT0),S4(P3^3)按键连接到外部中断1(INT1)现在我们使用外部中断0来举例,外部中断1类似。
首先,我们先初始化外部中断0,写一个外部中断初始化函数。
void INT0_Init(void)
{
IT0=1; /* 选择外部中断的触发方式(1:仅下降沿,0:上升沿和下降沿) */
EX0=1; /* 使能INT0(外部中断0) */
EA=1; /* 使能总中断 */
}
其次,写一个外部中断0的中断服务函数,内容是你想在中断时操作的东西(每中断一次判断flag的数值)。
void Service_INT0() interrupt 0
{
/* 中断后需要操作的内容 */
if(flag==0)
flag=1;
else if(flag==1)
{
flag=0;
slect_138_573(4,0xff);
}
}
代码实现:
题目要求:L1以每500ms闪烁,按一下S5 L8亮,再按一下S5 L8灭。
#include "stc15f2k60s2.h"
#include "intrins.h"
void Delay1ms() //@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
void delay_ms(int x)
{
while(x--)
{
Delay1ms();
}
}
/* 选择通道并且输入数据 */
void slect_138_573(unsigned char channel, unsigned char dat)
{
P0 = 0x00;
P0 = dat; /* 这里用P0而不用其他端口是因为我们操作LED、数码管、继电器、蜂鸣器都是对P0进行操作 */
switch(channel) /* 选择通道 */
{
case 4: /* 使Y4输出低电平0,也就是操作LED */
P2 = (P2 & 0x1f) | 0x80; /* (P2 & 0x1f)就是将前3位清0,再操作前3位。将0x80转为2进制1000 0000,这里只看前3位100就是Y4 */
break;
case 5: /* 使Y5输出低电平0,也就是操作继电器和蜂鸣器 */
P2 = (P2 & 0x1f) | 0xa0;
break;
case 6: /* 使Y6输出低电平0,也就是操作8个数码管 */
P2 = (P2 & 0x1f) | 0xc0;
break;
case 7: /* 使Y7输出低电平0,也就是操作8个数码管中的1个数码管显示值 */
P2 = (P2 & 0x1f) | 0xe0;
break;
case 0: /* 关闭所有通道 */
P2 = (P2 & 0x1f) | 0x00;
break;
}
P2 = (P2 & 0x1f) | 0x00; /* 使用后,关闭所有通道 */
}
void INT0_Init(void)
{
IT0=1; /* 选择外部中断的触发方式(1:仅下降沿,0:上升沿和下降沿) */
EX0=1; /* 使能INT0(外部中断0) */
EA=1; /* 使能总中断 */
}
unsigned char flag=0;
void Service_INT0(void) interrupt 0
{
if(flag==0)
flag=1;
else if(flag==1)
{
flag=0;
slect_138_573(4,0xff);
}
}
void led(void)
{
if(flag==0)
{
slect_138_573(4,P0^0x01);
delay_ms(500);
}
else if(flag==1)
{
slect_138_573(4,0x7f);
delay_ms(1500);
slect_138_573(4,0xff);
}
}
void System_init(void)
{
slect_138_573(4,0xff);
slect_138_573(5,0x00);
INT0_Init();
P0=0xff;
}
void main(void)
{
System_init();
while(1)
{
led();
}
}
本人认为此处不太重要,考试时很少考,而且按下按键时会有抖动,也会影响实验造成实验不准,所以说此部分考题少,考的也少。以上仅为个人观点。如有不懂请到本人主页看前几篇文章。Do My Best的博客_CSDN博客-蓝桥杯单片机比赛学习,sim800c模块领域博主
后续模块更新中。。。