STC15 外部中断编程笔记
以 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,处于一个很特殊的优先级
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App