「STC8A8K64S4A12开发板」—单片机中断原理
前言
今天来说说单机中断原理,概念搞清楚很重要!
一、关于中断的一些概念
中断的概念:当CPU正在处理某件事的时候外界发生了紧急事件请求,要求CPU暂停当前的工作,转而去处理这个紧急事件,处理完以后,再回到原来被中断的地方,继续原来的工作,这样的过程称之为中断。
中断系统:实现中断功能的部件称为中断系统,中断系统是为CPU具有对外界紧急事件的实时处理能力而设置的。
中断请求源:请示CPU中断的请求源即为中断请求源,简称中断源。
中断优先级:中断系统一般允许多个中断源,当几个中断源同时向CPU请求中断,那就诞生一个优先处理哪个中断源的问题,这样中断优先级便产生了。
中断嵌套:CPU按照中断源的中断优先级处理一个低优先级中断的时候,假如有另外一个更高优先级的中断源发出中断请求,那CPU需要暂停原来中断源的服务程序,转而去处理更高优先级的中断源,待处理结束后,再回到原低优先级的中断服务程序,这个过程就是中断嵌套。
二、STC8A8K64S4A12系列的中断请求源
■ STC8A8K64S4A12系列单片机有22个中断请求源。具体如下:
5个外部中断:外部中断0/INT0、外部中断1/INT1、外部中断2/INT2、外部中断3/INT3、外部中断4/INT4 。
5个定时器中断:定时器0中断、定时器1中断、定时器2中断、定时器3中断、定时器4中断 。
4个串口中断:串口1中断、串口2中断、串口3中断、串口4中断 。
1个A/D转换中断。
1个低压检测(LVD)中断。
1个CCP/PWM/PCA中断。
1个SPI中断。
1个比较器中断。
1个PWM中断。
1个PWM异常检测中断。
1个I2C中断。
■ 比较常用的中断是:外部引脚中断、定时器中断、串行口(UART)中断。
■ 在讲到每一部分知识时,我们都会详细讲解相关的中断使用原理。
■ 下图是STC8A8K64S4A12系列的中断结构图,大家需要了解的是:
所有中断使能的话都必须有个“总闸”控制,那就是总中断允许位EA。
有多个中断一起触发时,如何仲裁以保证有序的先后执行顺序,那就存在中断优先级的问题。
关于中断,有个不可回避的概念,那就是中断向量。
三、关于中断的一些概念STC8A8K64S4A12系列的中断结构图
四、STC8A8K64S4A12系列的中断优先级
STC8A8K64S4A12系列单片机自然优先级:手册里面称之为辅助优先级结构或者内部的查询次序。如下图。
在C语言编程时,中断查询次序号就是中断号,例如,针对外部中断0的中断服务函数:
void INT0_Isr (void) interrupt 0
{
; //添加中断处理语句
}
1
2
3
4
5
STC8A8K64S4A12系列单片机中断优先级的设置: STC8A8K64S4A12系列单片机通过设置特殊功能寄存器(IP、IPH、IP2和IP2H)中的相应位,对有4个优先级中断的中断请求源进行编程。
仅有1个中断优先级(最低优先级0)的是:外部中断2/INT2、外部中断3/INT3、定时器2、定时器3、定时器4、串行口3、串行口4。(共7个)
STC8A8K64S4A12系列IP和IPH寄存器各位含义介绍如下:
STC8A8K64S4A12系列IP2和IP2H寄存器各位含义介绍如下:
STC8A8K64S4A12系列单片机中断嵌套: 中断优先级高的中断请求可以中断CPU正在处理的优先级低的中断服务程序,待完成了中断优先级高的中断服务程序后,再继续被打断的低优先级的中断服务程序。
下图描述了主程序和中断服务程序的示意图,也诠释了中断嵌套的含义。
中断比喻举例,以下情形:
只有排长或者团长给士兵打电话;
排长和团长同时给士兵打电话;
士兵已在排长地里接到团长电话;
士兵已在团长地里接到排长电话;
士兵同时接到两个排长的电话;
士兵同时接到两个团长的电话。
STC8A8K64S4A12系列单片机中断产生而且被CPU响应,主程序被中断,接下来将执行如下操作:
当前正被执行的指令全部执行完毕。
PC值被压入栈。
现场保护。
阻止同级别或更低级别其他中断。
将中断向量地址装载到程序计数器PC。
执行响应的中断服务程序。
中断向量:当某中断被响应时,被装载到程序计数器PC的数值称为中断向量,是该中断源相对应的中断服务程序的起始地址。具体各中断源服务程序的入口地址就不一一列举了。
总结
不知道说得够不够清楚,望大家指正!
「STC8A8K64S4A12开发板」—单片机外部中断
前言
接着之前单机中断原理,再跟大家说说外部中断!
一、硬件电路设计
1.开发板IO口外部中断硬件电路
STC8A8K64S4A12开发板上设计了4个用户轻触按键,其中KEY1和KEY2按键可以为外部中断引脚提供触发信号,电路如下。
■ 开发板5个可用外部中断引脚如下表:
表1:开发板外部中断引脚分配
INT对应IO口功能描述说明备注
INT0P3.2外部中断0非独立GPIOLCD显示屏模块用。
INT1P3.3外部中断1非独立GPIOnRF24L01模块接口J11使用。
INT2P3.6外部中断2非独立GPIOW5500模块接口J7使用。
INT3P3.7外部中断3非独立GPIOW5500模块接口J7使用。
INT4P3.0外部中断4非独立GPIO板载USB转TTL电路用。
☆注:独立GPIO表示开发板没有其他的电路使用这个GPIO,非独立GPIO说明开发板有其他电路用到了该GPIO。针对非独立GPIO使用时需特别注意。
2.STC8A8K64S4A12系列MCU外部中断
STC8A8K64S4A12系列MCU不是每一个GPIO口都可以作为外部中断输入使用,只有特定的GPIO口才可以作为特定的外部中断输入使用。STC8A8K64S4A12系列MCU具有5个外部中断引脚,列表如下。
表2:STC8A8K64S4A12系列外部中断引脚分配
序号INT对应IO口功能描述备注
1INT0P3.2外部中断0中断优先级可设置0/1/2/3。
2INT1P3.3外部中断1中断优先级可设置0/1/2/3。
3INT2P3.6外部中断2只能为最低中断优先级0。
4INT3P3.7外部中断3只能为最低中断优先级0。
5INT4P3.0外部中断4中断优先级可设置0/1/2/3。
单片机外部中断引脚电平变化了,就有可能触发中断,进而执行中断服务程序。电平变化有可能是高电平到低电平(即产生下降沿),也可能是低电平到高电平(即产生上升沿)。STC8A8K64S4A12系列外部中断引脚支持的触发方式是不一样的。如下表。
表3:STC8A8K64S4A12系列外部中断引脚触发方式
序号触发方式INT备注
1下降沿触发INT0、INT1、INT2、INT3、INT4
2上升沿触发无指只可上升沿触发的意思。
3上升沿或下降沿触发INT0、INT1
实现GPIO口电平变化的方式有很多,使用外部按键改变GPIO口电平是一种简单直观的方式。但在实际使用中单片机的外部中断功能是应用于一些模块或芯片的中断引脚上,比如W5500以太网模块、nRF24L01无线模块等。
下面介绍下带有中断引脚(IRQ)的模块或传感器与单片机连接示意图。
图2:带中断引脚的模块或传感器与单片机连接示意图
■ 需要弄清楚的问题。
模块或传感器IRQ引脚的有效电平(低电平有效还是高电平有效)。
模块或传感器IRQ引脚一旦跳变到有效电平后需要单片机执行的操作。
■ 延伸出的问题。
如果模块或传感器IRQ引脚是低有效电平,那么产生的就是下降沿;如果模块或传感器IRQ引脚是高有效电平,那么产生的就是上升沿。这就需要单片机外部中断引脚有匹配的触发方式才可,如果没有怎么办呢?
与模块或传感器IRQ引脚相连的单片机引脚可以不是外部中断引脚,而是普通的GPIO口吗?
■ 回答延伸出的问题。
从STC8A8K64S4A12系列外部中断引脚触发方式表格中可以获悉,单片机INT0和INT1可选择为上升沿或下降沿触发方式,这基本可以满足大部分的应用需求的。如果单片机只有INT2、INT3或INT4(下降沿触发方式)的外部中断引脚可用,比较简便的方式是对模块或传感器的IRQ信号进行取反处理,硬件上加个反相器是一种做法,但务必考虑会有一个信号延时的问题。
模块或传感器IRQ引脚一般是可以和单片机GPIO口引脚相连的,这在程序设计时采用的就是查询方式。也就是单片机程序设计时不断循环查询与模块或传感器IRQ引脚相连的GPIO口状态,若检测到GPIO口跳变到有效电平后才会执行需要的操作。当单片机使用中断引脚与模块或传感器IRQ引脚相连时,设计程序便可采用中断方式,后面会详细介绍查询方式和中断方式的区别。
3.单片机中断方式和查询方式
单片机中断方式,是事件触发的,占用的CPU资源相对很少。换言之打开中断之后,CPU可以做其他事情,只有当符合条件的事件产生时才会进入中断,去执行中断服务程序。举例,针对STC8A8K64S4A12系列单片机,前面介绍的下降沿中断或上升沿中断都是触发中断的条件,在这个条件不满足时单片机是不用理会外部中断引脚的,而一旦条件满足,如果程序中没有其他同时发生的更高优先级的中断的话,CPU会立即执行该外部中断对应的中断服务函数。
单片机查询方式,就是在主函数里面不停循环,查询端口状态,这会占用大量CPU资源。这时模块或传感器IRQ引脚是可以和单片机普通IO口引脚相连的。这种方式的弊端:
占用过多CPU资源,影响响应速度。
在处理事件多,处理流程复杂,函数嵌套执行的情况下,由于CPU处理不过来可能会丢失事件。(往往模块或传感器IRQ引脚跳变到有效电平的时间也是有限的,如果在有限的时间内没有捕获到有效信号就会丢失事件)
☆注:单片机查询方式的缺点就是单片机中断方式的优点。当然,单片机查询方式的优点是可以使用普通IO口甚至不使用IO口。
4.外部中断配置步骤
针对STC8A8K64S4A12系列单片机5个外部中断引脚,软件的配置过程如下:
图3:外部中断软件配置步骤
☆注:实验例程即是按照上述配置步骤操作寄存器相关位实现,后有详述。
二、软件设计
1.寄存器解析
首先普及一个常用知识点:在操作单片机寄存器时常说有的寄存器支持位寻址,有的寄存器不支持位寻址?这里的位寻址究竟是什么含义?
位寻址定义:对位地址中的内容进行位操作的寻址方式称为位寻址。由于单片机中只有内部RAM和特殊功能寄存器的部分单元有位地址,因此位寻址只能对有位地址的这两个空间进行寻址操作。
单片机中不是每个寄存器都支持位寻址的,一般如果SFR(特殊功能寄存器)的地址值能被8整除,则该SFR可以进行位寻址。举例P0端口数据寄存器是支持位寻址的。
图4:P0端口数据寄存器
☆注:单片机中寄存器地址值如不能被8整除,则该寄存器是不支持位寻址的。针对STC8A8K64S4A12系列有些SFR是位于扩展RAM中,这些SFR不可以按照这个总结的规则去判定是否支持位寻址。访问位于扩展RAM中的SFR需要先操作P_SW2的BIT7才可,这个在用到时讲解。
1.1.中断允许寄存器IE
中断允许寄存器IE支持位寻址,该寄存器的B7位是单片机所有中断的总闸,即其他中断位使能后,最后还必须将这个总中断打开才能开启中断,与外部中断有关的还有B0和B2位,含义如下图。
图5:中断允许寄存器
1.2.外部中断和时钟输出控制寄存器INTCLKO2
外部中断允许和时钟输出寄存器INTCLKO2不支持位寻址,该寄存器的B4、B5和B6位是外部中断2、外部中断3和外部中断4的中断允许位。因为AUXR2寄存器不支持位寻址,所以操作该寄存器位时,不可以直接“EX2=0;”进行操作INT2中断允许位,参考下图。
图6:外部中断和时钟输出控制寄存器
1.3.定时器/计数器中断控制寄存器TCON
定时器/计数器中断控制寄存器TCON支持位寻址,该寄存器的B0位和B2位是选择INT0和INT1中断源类型的(可理解成中断触发方式),寄存器B1位和B3位是INT0和INT1中断请求标志,含义如下图。
图7:定时器/计数器中断控制寄存器
☆注:单片机中很多寄存器都像TCON寄存器一样,寄存器关联的单片机外设不止一个,这就需要我们在操作寄存器时一定要按位操作,用不到的位千万不要操作,否则在程序比较复杂、用到的外设比较多时,往往会遇到不可知问题。
2.外部中断0实验(下降沿中断方式)
☆注:本节的实验源码是在“实验2-2-2: GPIO输入按键检测(多个c文件)”的基础上修改。本节对应的实验源码是:“实验2-4-1:外部中断0(下降沿中断方式)”。
2.1.工程需要用到的c文件
本例需要用到的c文件如下表所示,工程需要添加下表中的c文件。
表4:实验需要用到的c文件
序号文件名后缀功能描述
1led.c包含与用户led控制有关的用户自定义函数。
2exint.c外部中断有关的用户自定义函数。
3delay.c包含用户自定义延时函数。
2.2.头文件引用和路径设置
■ 需要引用的头文件
#include "delay.h"
#include "led.h"
#include "exint.h"
1
2
3
■ 需要包含的头文件路径
本例需要包含的头文件路径如下表:
表5:头文件包含路径
序号路径描述
1…\ Sourceled.h、exint.h和delay.h头文件在该路径,所以要包含。
2…\UserSTC8.h头文件在该路径,所以要包含。
MDK中点击魔术棒,打开工程配置窗口,按照下图所示添加头文件包含路径。
图8:添加头文件包含路径
2.3.编写代码
首先,在exint.c文件中编写外部中断0初始化函数INT0_Init,代码如下。
程序清单:外部中断0初始化函数
/***********************************************************
功能描述:外部中断0初始化
入口参数:无
返回值:无
************************************************************/
void INT0_Init(void)
{
IE0 = 0; //将INT0中断请求标志位清"0"
EX0 = 1; //使能INT0中断允许位
IT0 = 1; //选择INT0为下降沿触发方式
}
1
2
3
4
5
6
7
8
9
10
11
然后,编写外部中断服务函数,一旦进入中断会执行翻转蓝色指示灯D3的任务,代码如下。
程序清单:中断服务函数
/***********************************************************
功能描述:外部中断服务程序
入口参数:无
返回值:无
************************************************************/
void INT0_Isr (void) interrupt 0
{
led_toggle(LED_3); //翻转蓝色指示灯D3
}
1
2
3
4
5
6
7
8
9
最后,在主函数中调用INT0初始化函数,开启总中断,在主循环中没有任务,蓝色指示灯D3变化来自于中断。
代码清单:主函数
int main(void)
{
INT0_Init(); //外部中断0的初始化配置
EA = 1; //允许总中断
while (1)
{
; //无任务,说明LED亮灭来自于中断
}
}
1
2
3
4
5
6
7
8
9
10
2.4.硬件连接
本实验需要使用P3.2(外部中断0引脚)连接到J26端子KEY1,因此需要按下图所示连接杜邦线。
图9:开发板连接图
3.外部中断0实验(上升沿或下降沿中断方式)
☆注:本节的实验源码是在“实验2-4-1:外部中断0(下降沿中断方式)”的基础上修改。本节对应的实验源码是:“实验2-4-2:外部中断0(上升沿或下降沿中断方式)”。
3.1.程需要用到的c文件
本实验需要用到的头文件以及添加头文件包含路径的方法请参考“实验2-4-1:外部中断0(下降沿中断方式)”部分。
3.2.编写代码
首先,在exint.c文件中编写外部中断0初始化函数INT0_Init,代码如下。
程序清单:外部中断0初始化函数
/***********************************************************
功能描述:外部中断0初始化
入口参数:无
返回值:无
************************************************************/
void INT0_Init(void)
{
IE0 = 0; //将INT0中断请求标志位清"0"
EX0 = 1; //使能INT0中断允许位
IT0 = 0; //选择INT0为上升沿或下降沿触发方式
}
1
2
3
4
5
6
7
8
9
10
11
然后,编写外部中断服务函数,一旦进入中断会执行翻转蓝色指示灯D3的任务,代码如下。
程序清单:中断服务函数
/***********************************************************
功能描述:外部中断服务程序
入口参数:无
返回值:无
************************************************************/
void INT0_Isr (void) interrupt 0
{
led_toggle(LED_3); //翻转蓝色指示灯D3
}
1
2
3
4
5
6
7
8
9
最后,在主函数中调用INT0初始化函数,开启总中断,在主循环中没有任务,蓝色指示灯D3变化来自于中断。
代码清单:主函数
int main(void)
{
INT0_Init(); //外部中断0的初始化配置
EA = 1; //允许总中断
while (1)
{
; //无任务,说明LED亮灭来自于中断
}
}
1
2
3
4
5
6
7
8
9
10
3.3.硬件连接
本实验需要使用P3.2(外部中断0引脚)连接到J26端子KEY1,因此需要按下图所示连接杜邦线。
图10:开发板连接图
4.外部中断0实验(上升沿或下降沿中断方式)
☆注:本节的实验源码是在“实验2-4-1:外部中断0(下降沿中断方式)”的基础上修改。本节对应的实验源码是:“实验2-4-3:外部中断1(下降沿中断方式)”。
4.1.工程需要用到的c文件
本实验需要用到的头文件以及添加头文件包含路径的方法请参考“实验2-4-1:外部中断0(下降沿中断方式)”部分。
4.2.编写代码
首先,在exint.c文件中编写外部中断1初始化函数INT1_Init,代码如下。
程序清单:外部中断1初始化函数
/***********************************************************
功能描述:外部中断1初始化
入口参数:无
返回值:无
************************************************************/
void INT1_Init(void)
{
IE1 = 0; //将INT1中断请求标志位清"0"
EX1 = 1; //使能INT1中断允许位
IT1 = 1; //选择INT1为下降沿触发方式
}
1
2
3
4
5
6
7
8
9
10
11
然后,编写外部中断服务函数,一旦进入中断会执行翻转蓝色指示灯D3的任务,代码如下。
程序清单:中断服务函数
/***********************************************************
功能描述:外部中断服务程序
入口参数:无
返回值:无
************************************************************/
void INT1_Isr (void) interrupt 2
{
led_toggle(LED_3); //翻转蓝色指示灯D3
}
1
2
3
4
5
6
7
8
9
最后,在主函数中调用INT1初始化函数,开启总中断,在主循环中没有任务,蓝色指示灯D3变化来自于中断。
代码清单:主函数
int main(void)
{
INT1_Init(); //外部中断1的初始化配置
EA = 1; //允许总中断
while (1)
{
; //无任务,说明LED亮灭来自于中断
}
}
1
2
3
4
5
6
7
8
9
10
4.3.硬件连接
本实验需要使用P3.3(外部中断1引脚)连接到J26端子KEY1,因此需要按下图所示连接杜邦线。
图11:开发板连接图
5.外部中断1实验(上升沿或下降沿中断方式)
☆注:本节的实验源码是在“实验2-4-3:外部中断1(下降沿中断方式)”的基础上修改。本节对应的实验源码是:“实验2-4-4:外部中断1(上升沿或下降沿中断方式)”。
5.1.工程需要用到的c文件
本实验需要用到的头文件以及添加头文件包含路径的方法请参考“实验2-4-1:外部中断0(下降沿中断方式)”部分。
5.2.编写代码
首先,在exint.c文件中编写外部中断1初始化函数INT1_Init,代码如下。
程序清单:外部中断1初始化函数
/***********************************************************
功能描述:外部中断1初始化
入口参数:无
返回值:无
************************************************************/
void INT1_Init(void)
{
IE1 = 0; //将INT1中断请求标志位清"0"
EX1 = 1; //使能INT1中断允许位
IT1 = 0; //选择INT1为上升沿或下降沿触发方式
}
1
2
3
4
5
6
7
8
9
10
11
然后,编写外部中断服务函数,一旦进入中断会执行翻转蓝色指示灯D3的任务,代码如下。
程序清单:中断服务函数
/***********************************************************
功能描述:外部中断服务程序
入口参数:无
返回值:无
************************************************************/
void INT1_Isr (void) interrupt 2
{
led_toggle(LED_3); //翻转蓝色指示灯D3
}
1
2
3
4
5
6
7
8
9
最后,在主函数中调用INT1初始化函数,开启总中断,在主循环中没有任务,蓝色指示灯D3变化来自于中断。
代码清单:主函数
int main(void)
{
INT1_Init(); //外部中断1的初始化配置
EA = 1; //允许总中断
while (1)
{
; //无任务,说明LED亮灭来自于中断
}
}
1
2
3
4
5
6
7
8
9
10
5.3.硬件连接
本实验需要使用P3.3(外部中断1引脚)连接到J26端子KEY1,因此需要按下图所示连接杜邦线。
图12:开发板连接图
6.外部中断2实验(下降沿中断方式)
☆注:本节的实验源码是在“实验2-4-1:外部中断0(下降沿中断方式)”的基础上修改。本节对应的实验源码是:“实验2-4-5:外部中断2(下降沿中断方式)”。
6.1.工程需要用到的c文件
本实验需要用到的头文件以及添加头文件包含路径的方法请参考“实验2-4-1:外部中断0(下降沿中断方式)”部分。
6.2.编写代码
首先,在exint.c文件中编写外部中断2初始化函数INT2_Init,代码如下。
程序清单:外部中断2初始化函数
int main(void)
/***********************************************************
功能描述:外部中断2初始化
入口参数:无
返回值:无
************************************************************/
void INT2_Init(void)
{
INTCLKO |= 0x10; //使能INT2中断允许位
}
1
2
3
4
5
6
7
8
9
10
然后,编写外部中断服务函数,一旦进入中断会执行翻转蓝色指示灯D3的任务,代码如下。
程序清单:中断服务函数
/***********************************************************
功能描述:外部中断服务程序
入口参数:无
返回值:无
************************************************************/
void INT2_Isr (void) interrupt 10
{
led_toggle(LED_3); //翻转蓝色指示灯D3
}
1
2
3
4
5
6
7
8
9
最后,在主函数中调用INT2初始化函数,开启总中断,在主循环中没有任务,蓝色指示灯D3变化来自于中断。
代码清单:主函数
int main(void)
{
INT2_Init(); //外部中断2的初始化配置
EA = 1; //允许总中断
while (1)
{
; //无任务,说明LED亮灭来自于中断
}
}
1
2
3
4
5
6
7
8
9
10
6.3.硬件连接
本实验需要使用P3.6(外部中断2引脚)连接到按键KEY2,因此需要按下图所示连接短路帽。
图13:开发板连接图
7.外部中断3实验(下降沿中断方式)
==☆注:本节的实验源码是在“实验2-4-1:外部中断0(下降沿中断方式)”的基础上修改。本节对应的实验源码是:“实验2-4-6:外部中断3(下降沿中断方式)”。 ==
7.1.工程需要用到的c文件
本实验需要用到的头文件以及添加头文件包含路径的方法请参考“实验2-4-1:外部中断0(下降沿中断方式)”部分。
7.2.编写代码
首先,在exint.c文件中编写外部中断3初始化函数INT3_Init,代码如下。
程序清单:外部中断3初始化函数
/***********************************************************
功能描述:外部中断3初始化
入口参数:无
返回值:无
************************************************************/
void INT3_Init(void)
{
INTCLKO |= 0x20; //使能INT3中断允许位
}
1
2
3
4
5
6
7
8
9
然后,编写外部中断服务函数,一旦进入中断会执行翻转蓝色指示灯D3的任务,代码如下。
程序清单:中断服务函数
/***********************************************************
功能描述:外部中断服务程序
入口参数:无
返回值:无
************************************************************/
void INT3_Isr (void) interrupt 11
{
led_toggle(LED_3); //翻转用户指示灯D3
}
1
2
3
4
5
6
7
8
9
最后,在主函数中调用INT3初始化函数,开启总中断,在主循环中没有任务,蓝色指示灯D3变化来自于中断。
代码清单:主函数
int main(void)
{
INT3_Init(); //外部中断3的初始化配置
EA = 1; //允许总中断
while (1)
{
; //无任务,说明LED亮灭来自于中断
}
}
1
2
3
4
5
6
7
8
9
10
7.3.硬件连接
本实验需要使用P3.7(外部中断3引脚)连接到按键KEY1,因此需要按下图所示连接短路帽。
图14:开发板连接图
8.外部中断4实验(下降沿中断方式)
==☆注:本节的实验源码是在“实验2-4-1:外部中断0(下降沿中断方式)”的基础上修改。本节对应的实验源码是:“实验2-4-7:外部中断4(下降沿中断方式)”。 ==
8.1.工程需要用到的c文件
本实验需要用到的头文件以及添加头文件包含路径的方法请参考“实验2-4-1:外部中断0(下降沿中断方式)”部分。
8.2.编写代码
首先,在exint.c文件中编写外部中断4初始化函数INT4_Init,代码如下。
程序清单:外部中断4初始化函数
/***********************************************************
功能描述:外部中断4初始化
入口参数:无
返回值:无
************************************************************/
void INT4_Init(void)
{
INTCLKO |= 0x40; //使能INT4中断允许位
}
1
2
3
4
5
6
7
8
9
然后,编写外部中断服务函数,一旦进入中断会执行翻转蓝色指示灯D3的任务,代码如下。
程序清单:中断服务函数
/***********************************************************
功能描述:外部中断服务程序
入口参数:无
返回值:无
************************************************************/
void INT4_Isr (void) interrupt 16
{
led_toggle(LED_3); //翻转用户指示灯D3
}
1
2
3
4
5
6
7
8
9
最后,在主函数中调用INT4初始化函数,开启总中断,在主循环中没有任务,蓝色指示灯D3变化来自于中断。
代码清单:主函数
int main(void)
{
INT4_Init(); //外部中断4的初始化配置
EA = 1; //允许总中断
while (1)
{
; //无任务,说明LED亮灭来自于中断
}
}
1
2
3
4
5
6
7
8
9
10
8.3.硬件连接
本实验需要使用P3.0(外部中断4引脚)连接到J26端子KEY1,因此需要按下图所示连接杜邦线。
图15:开发板连接图
9.多个外部中断实验
==☆注:本节的实验源码是在“实验2-4-1:外部中断0(下降沿中断方式)”的基础上修改。本节对应的实验源码是:“实验2-4-8:多个外部中断”。 ==
9.1.工程需要用到的c文件
本实验需要用到的头文件以及添加头文件包含路径的方法请参考“实验2-4-1:外部中断0(下降沿中断方式)”部分。
9.2.编写代码
首先,在exint.c文件中编写外部中断0初始化函数INT0_Init和外部中断1初始化函数INT1_Init,代码如下。
程序清单:外部中断0初始化函数
/***********************************************************
功能描述:外部中断0初始化
入口参数:无
返回值:无
************************************************************/
void INT0_Init(void)
{
IE0 = 0; //将INT0中断请求标志位清"0"
EX0 = 1; //使能INT0中断允许位
IT0 = 1; //选择INT0为下降沿触发方式
/* 将INT0优先级设置为最低优先级 */
IP &= 0xFE; //将PX0位置0
IPH &= 0xFE; //将PX0H位置0
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
程序清单:外部中断1初始化函数
/***********************************************************
功能描述:外部中断1初始化
入口参数:无
返回值:无
************************************************************/
void INT1_Init(void)
{
IE1 = 0; //将INT1中断请求标志位清"0"
EX1 = 1; //使能INT1中断允许位
IT1 = 1; //选择INT1为下降沿触发方式
/* 将INT1优先级设置为最高优先级 */
IP |= 0x04; //将PX1位置1
IPH |= 0x04; //将PX1H位置1
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
然后,编写外部中断服务函数,一旦进入外部中断0会执行翻转4次蓝色指示灯D3的任务,进入外部中断1会执行翻转4次蓝色指示灯D4的任务,代码如下。
程序清单:中断服务函数
/***********************************************************
功能描述:外部中断服务程序
入口参数:无
返回值:无
************************************************************/
void INT0_Isr (void) interrupt 0
{
led_on(LED_3); //点亮用户指示灯D3
delay_ms(200);
led_off(LED_3); //熄灭用户指示灯D3
delay_ms(100);
led_on(LED_3); //点亮用户指示灯D3
delay_ms(200);
led_off(LED_3); //熄灭用户指示灯D3
delay_ms(100);
led_on(LED_3); //点亮用户指示灯D3
delay_ms(200);
led_off(LED_3); //熄灭用户指示灯D3
delay_ms(100);
led_on(LED_3); //点亮用户指示灯D3
delay_ms(200);
led_off(LED_3); //熄灭用户指示灯D3
delay_ms(100);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
程序清单:中断服务函数
/***********************************************************
功能描述:外部中断服务程序
入口参数:无
返回值:无
************************************************************/
void INT1_Isr (void) interrupt 2
{
led_on(LED_4); //点亮用户指示灯D4
delay_ms(200);
led_off(LED_4); //熄灭用户指示灯D4
delay_ms(100);
led_on(LED_4); //点亮用户指示灯D4
delay_ms(200);
led_off(LED_4); //熄灭用户指示灯D4
delay_ms(100);
led_on(LED_4); //点亮用户指示灯D4
delay_ms(200);
led_off(LED_4); //熄灭用户指示灯D4
delay_ms(100);
led_on(LED_4); //点亮用户指示灯D4
delay_ms(200);
led_off(LED_4); //熄灭用户指示灯D4
delay_ms(100);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
最后,在主函数中调用INT0和INT1初始化函数,开启总中断。在主循环中没有任务,蓝色指示灯D3和蓝色指示灯D4变化来自于中断。
代码清单:主函数
int main(void)
{
INT0_Init(); //外部中断0的初始化配置
INT1_Init(); //外部中断1的初始化配置
EA = 1; //允许总中断
while (1)
{
; //无任务,说明LED亮灭来自于中断
}
}
1
2
3
4
5
6
7
8
9
10
11
9.3.硬件连接
本实验需要使用P3.2(外部中断0引脚)连接到J26端子KEY1,P3.3(外部中断1引脚)连接到J26端子KEY2,因此需要按下图所示连接杜邦线。
图16:开发板连接图
总结
以上就是今天要讲的内容,大家看完不妨思考一下:根据本例实验现象分析INT0和INT1谁的中断优先级高?为什么?
相关问答
stc中断 优先级设置?1)由中断源提出中断请求,由中断控制允许控制决定是否响应中断,如果允许响应中断,则CPU按设定好的优先级的顺序响应中断。如果是同一优先级的中断,则按单片...
STC单片机 通过继电器控制交流电机,在电机启动和停止的瞬间会多次进入 中断 ?现场干扰总是在所难免的。你已经采取了一些常用的抗干扰措施,但是,关键问题没有解决。1、继电器本来就是隔离的,无需单独供电,光电耦合器的输入端如果需要...
描述 stc单片机 ,按键控制灯亮灭和闪烁,上电灯不亮,按一下按键灯亮,再按一下灯闪烁,再按一下?51单片机的IO口接按键,实现外部触发(外部中断,高低电平,上下降沿),触发后再通过IO控制LED的开关即可。51单片机的IO口接按键,实现外部触发(外部中断,高低电平...
stc单片机 怎么让t2口输出一定数量的脉冲后停止输出?在输出脉冲的中断子程序里加入一个标志数和一段判断程序,每中断输出一个脉冲时都把标志数加一然后再判断标志数是否大于了某个设定值,大于时就关中断。在输...
51 单片机 怎么休眠 - 177****2285 的回答 - 懂得51单片机,如STC系列单片机,可以进入休眠状态(或者掉电模式),待机方式(或者空闲模式),掉电模式:为时钟停止的所有工作状态全部停止,可以有...
51 单片机 串口 中断 是怎么触发的?首先,你要用软件允许中断,即C语言中EA=1;//允许总中断ES=1;//允许串口中断汇编中可用SETBEA;允许总中断SETBES;允许串口中断当单片机接收到一帧数据后,RI会置1...
51 单片机中断 唤醒-ZOL问答3、中断返回不用return图,代码。光是这么空口说无法判断。看看以前的问题与解答,也许有帮助。键入:STC89系列单片机掉电模式或者休眠模式应用搜索答案...
51 单片机 定时器不够用怎么办?确实如此,定时器是使用频率最高的资源。STC89C52单片机有3个定时器,分别是T0,T1和T2。一般够用,一个串口波特率发生,2个计时。其中T2有捕捉功能。由于定时器...
单片机STC 12C5A60S2不接晶钟和复位能下载程序吗-ZOL问答至于复位,应该是让单片机停止当前工作,接收上面的程序,这个有点不确定。希望帮...如果使用C语言编程,中断查询次序号就是中断号,例如:voidInt0_Routine(void)...
STC 12c5204AD 单片机 22.1184晶振如何实现115200波特率串口通...这个是stc-isp软件生成的串口初始化函数:voidUartInit(void)//115200bps@22.1184MHz{PCON|=0x80;//使能波特率倍速位SMODSCON...