STC15 外部中断编程笔记

发布时间 2023-08-08 14:14:35作者: Sound_Sleep

以 STC15W4K58S4 为例,可以将片上的外部中断资源分为“高级”和“低级”两类,EXINT0 和 EXINT1 属于高级的,EXINT2 ~ EXINT4 属于低级的。

“高级”的外部中断可以配置中断优先级,选择中断源;低级的则不行。


EXINT0 和 EXINT1 的配置

这两个外部中断的配置寄存器都可位寻址,因此可以直接对寄存器的某个位进行操作。

配置步骤如下:

  1. 清除中断请求标志位
  2. 选择中断源类型
  3. 设置中断优先级
  4. 使能外部中断
  5. 使能总中断
  6. 编写中断服务函数
@清除中断标志位

直接操作 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 的配置

这几个外部中断的寄存器中存在不可位寻址的,且这几个外部中断不可以配置中断源类型和中断优先级,默认是最低优先级和只能下降沿触发。

配置步骤:

  1. 使能外部中断
  2. 使能总中断
  3. 编写中断服务函数
@使能外部中断

需要操作 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,处于一个很特殊的优先级