以 STC15W4K58S4 为例,可以将片上的外部中断资源分为“高级”和“低级”两类,EXINT0 和 EXINT1 属于高级的,EXINT2 ~ EXINT4 属于低级的。
“高级”的外部中断可以配置中断优先级,选择中断源;低级的则不行。
EXINT0 和 EXINT1 的配置
这两个外部中断的配置寄存器都可位寻址,因此可以直接对寄存器的某个位进行操作。
配置步骤如下:
- 清除中断请求标志位
- 选择中断源类型
- 设置中断优先级
- 使能外部中断
- 使能总中断
- 编写中断服务函数
@清除中断标志位
直接操作 IE(Interrupt enquiry) 位。
IE0 = 0; // EXINT0 中断标志位清 0
IE1 = 0; // EXINT1 中断标志位清 0
这个标志位的复位值是 0, 所以其实不清 0 问题也不大,清 0 更加稳妥。
同时这个标志位在程序运行的过程中不需要用户管理,中断请求产生时由硬件置 1,中断响应完成后由硬件清 0。
@选择中断源类型
直接操作 IT(Interrupt Type) 位。
IT0 = 1; // EXINT0 配置为下降沿触发
IT0 = 0;// EXINT0 配置为上升沿和下降沿都触发
IT1 = 1; // EXINT1 配置为下降沿触发
IT1 = 0;// EXINT1 配置为上升沿和下降沿都触发
IT 写 1 则表示仅仅使用下降沿电平触发外部中断,IT 写 0 则表示上升沿电平和下降沿电平都会触发外部中断。
@配置中断优先级
直接操作 PX(Priority of External Interrupt) 位。
PX0 = 0; // EXINT0 配置为最低优先级
PX0 = 1; // EXINT0 配置为最高优先级
PX1 = 0; // EXINT1 配置为最低优先级
PX1 = 1; // EXINT1 配置为最高优先级
PX 写 1 则配置为最高优先级,PX 写 0 则配置为最高优先级。
@使能外部中断
直接操作 IE(Interrupt Enable) 位。
EX0 = 1; // 使能外部中断 0
EX1 = 1; // 使能外部中断 1
@ 使能总中断
直接操作 EA(Enable) 位
EA = 1; // 使能总中断
总中断是所有中断的开关,EA 写 1 开启总中断
@中断服务函数的编写
void INT0_ISR(void) interrupt 0 // EXINT0 的中断服务函数
{
/* 编写中断触发后需要执行的代码 */
}
中断服务函数的函数名可以任意写,后面的 interrupt 关键字加上中断服务号不能少,这是识别中断的标志
STC15W4K58S4 中断服务号的定义如下:
#define INT0_VECTOR 0
#define TIMER0_VECTOR 1
#define INT1_VECTOR 2
#define TIMER1_VECTOR 3
#define UART1_VECTOR 4
#define ADC_VECTOR 5
#define LVD_VECTOR 6
#define PCA_VECTOR 7
#define UART2_VECTOR 8
#define SPI_VECTOR 9
#define INT2_VECTOR 10
#define INT3_VECTOR 11
#define TIMER2_VECTOR 12
#define INT4_VECTOR 16
#define UART3_VECTOR 17
#define UART4_VECTOR 18
#define TIMER3_VECTOR 19
#define TIMER4_VECTOR 20
#define CMP_VECTOR 21
#define PWM_VECTOR 22
#define PWMFD_VECTOR 23
EXINT2 ~ EXINT4 的配置
这几个外部中断的寄存器中存在不可位寻址的,且这几个外部中断不可以配置中断源类型和中断优先级,默认是最低优先级和只能下降沿触发。
配置步骤:
- 使能外部中断
- 使能总中断
- 编写中断服务函数
@使能外部中断
需要操作 INT_CLKO 寄存器,也叫 AUXR2 寄存器,该寄存器不可位寻址。
各 bit 定义如下:
将 EX 位写 1 使能外部中断。
AUXR2 |= 0x10; // EXINT2 使能
AUXR2 |= 0x20; // EXINT3 使能
AUXR2 |= 0x40; // EXINT4 使能
如果头文件没有 AUXR2 寄存器,则可能是用了该寄存器的另外一个名字 —— INT_CLKO,改一下寄存器名字就好:
INT_CLKO |= 0x10; // EXINT2 使能
INT_CLKO |= 0x20; // EXINT3 使能
INT_CLKO |= 0x40; // EXINT4 使能
@使能总中断
直接操作 EA(Enable) 位,EA 写 1 开启总中断
EA = 1; // 开启总中断
@中断服务函数的编写
void INT2_ISR(void) interrupt 10 // EXINT2 的中断服务函数
{
/* 编写中断触发后需要执行的代码 */
}
中断服务函数的函数名可以任意写,后面的 interrupt 关键字加上中断服务号不能少,这是识别中断的标志
STC15W4K58S4 中断服务号的定义如下:
#define INT0_VECTOR 0
#define TIMER0_VECTOR 1
#define INT1_VECTOR 2
#define TIMER1_VECTOR 3
#define UART1_VECTOR 4
#define ADC_VECTOR 5
#define LVD_VECTOR 6
#define PCA_VECTOR 7
#define UART2_VECTOR 8
#define SPI_VECTOR 9
#define INT2_VECTOR 10
#define INT3_VECTOR 11
#define TIMER2_VECTOR 12
#define INT4_VECTOR 16
#define UART3_VECTOR 17
#define UART4_VECTOR 18
#define TIMER3_VECTOR 19
#define TIMER4_VECTOR 20
#define CMP_VECTOR 21
#define PWM_VECTOR 22
#define PWMFD_VECTOR 23
EXINT4的中断优先级问题
芯片手册提到 EXINT2 ~ EXINT4 的中断优先级不可更改,都是最低优先级,但是在 IP2 寄存器中发现了 PX4 这个位,既然无法配置中断优先级为什么还有一个中断优先级配置位?
所以进行了下面实验:
- EXINT0 设置为低优先级, EXINT4 设置为高优先级时
- 双方都无法打断对方的中断服务函数
- 两个都设置为高优先级时
- 双方都无法打断对方中断服务函数
- EXINT0 设置为高优先级,EXINT4 设置为低优先级时:
- EXINT0 的中断服务函数可以打断 EXINT4 的中断服务函数
- EXINT4 的中断服务函数无法打断 EXINT0 的中断服务函数
所以将 EXINT4 写成最高优先级,可以不被任何外部中断打断,但是也无法打断 EXINT0 和 EXINT1,处于一个很特殊的优先级
标签:使能,优先级,STC15,中断,编程,笔记,EXINT0,VECTOR,define From: https://www.cnblogs.com/Sound-Sleep/p/51EXINT.html