STC8H8K64U 外部中断
STC8H8K64U共支持 5个外部中断源:INT0(P3.2)、INT1(P3.3)、INT2(P3.6)、INT3(P3.7)、INT4(P3.0)。 其中 INT0和INT1支持上升沿和下降沿触发, INT2/3/4仅支持下降沿触发。
一 外部中断工作流程
🔧 系统初始化阶段(以INT0为例)
📌
设置I/O口模式
P3M0/P3M1
→
⚙️
设置触发方式
IT0=1 下降沿
→
🧹
清除中断标志
IE0=0 + 3×NOP
→
✅
开启中断
EX0=1, EA=1
⚡ 中断响应阶段
🏃
主程序运行
🔍
引脚检测到指定沿
🚩
IE0硬件置1
🔄
PC→中断向量0x0003
📋
执行ISR / IE0硬件清零
↩️
RETI返回主程序
⚠️ 重要提示:
上电时INT0、INT1可能已检测到一次上升沿,中断标志会被置1。因此必须在允许中断前先清除中断标志并加3个NOP延时,否则一旦
EX0=1 就会立即误入中断。
二 外部中断相关寄存器说明
2.1 TCON(定时器/计数器控制寄存器)
地址0x88,可位寻址
| 位 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|---|---|---|---|---|---|---|---|---|
| 名称 | TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |
IT0(D0):INT0触发方式
=1 下降沿触发=0 上升沿+下降沿触发
IE0(D1):INT0中断请求标志
硬件置1 → 检测到边沿跳变
硬件清零 → CPU响应中断后
硬件置1 → 检测到边沿跳变
硬件清零 → CPU响应中断后
2.2 IE(中断允许寄存器)
地址0xA8,可位寻址
| 位 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|---|---|---|---|---|---|---|---|---|
| 名称 | EA | ELVD | EADC | ES | ET1 | EX1 | ET0 | EX0 |
EA(D7):总中断允许位
=1 CPU开放中断 | =0 屏蔽所有中断
EX0/EX1(D0/D2)
=1 允许INT0/INT1中断 | =0 禁止
2.3 INTCLKO(外部中断允许寄存器)
地址0x8F,不可位寻址——必须整体赋值
| 位 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|---|---|---|---|---|---|---|---|---|
| 名称 | — | EX4 | EX3 | EX2 | — | — | T1CLKO | T0CLKO |
设置示例(读-改-写方式):
INTCLKO |= 0x70; 同时使能INT2、INT3、INT4(EX2=EX3=EX4=1)
📋 外部中断引脚映射与向量表
| 中断源 | 中断向量号 | 固定引脚 | 触发方式 | 优先级 |
|---|---|---|---|---|
| INT0 | interrupt 0 | P3.2 | 下降沿 / 上升沿+下降沿 | 4级可设 |
| INT1 | interrupt 2 | P3.3 | 下降沿 / 上升沿+下降沿 | 4级可设 |
| INT2 | interrupt 10 | P3.6 | 仅下降沿 | 固定最低 |
| INT3 | interrupt 11 | P3.7 | 仅下降沿 | 固定最低 |
| INT4 | interrupt 16 | P3.0 | 仅下降沿 | 固定最低 |
三 C语言示例代码
💡 示例3.1:外部中断控制LED(INT0下降沿触发)
系统时钟24MHz · P3.2接按键 · P2.0接LED · 下降沿触发翻转
/*============================================================ * 文件名 : exti_interrupt.c * 芯片型号 : STC8H8K64U * 系统时钟 : 24MHz * 功能描述 : 外部中断0(INT0/P3.2)下降沿触发,控制LED翻转 *============================================================*/ #include "stc8h8k64u.h" sbit LED = P2^0; sbit KEY = P3^2; // INT0引脚 void ExtInt0_Init(void) { P_SW2 |= 0x80; // 使能访问扩展寄存器 P2M0 = 0x00; // P2口准双向口 P2M1 = 0x00; P3M0 = 0x00; // P3口准双向口 P3M1 = 0x00; IT0 = 1; // 下降沿触发 IE0 = 0; // 清除INT0中断标志(关键!) __asm__("NOP"); // 3个NOP延时 __asm__("NOP"); __asm__("NOP"); EX0 = 1; // 使能INT0中断 EA = 1; // 开启总中断 } void INT0_ISR(void) interrupt 0 { LED = ~LED; // LED状态取反 } void main(void) { LED = 1; // 初始熄灭 ExtInt0_Init(); // 外部中断初始化 while(1) { } // 主循环 }
🚀 示例3.2:同时使用INT0~INT4五个外部中断
/* 5个外部中断全部启用,各控制一个LED翻转 */ #include "stc8h8k64u.h" sbit LED0 = P2^0; sbit LED1 = P2^1; sbit LED2 = P2^2; sbit LED3 = P2^3; sbit LED4 = P2^4; void ExtInt_All_Init(void) { P_SW2 |= 0x80; P2M0 = P2M1 = 0x00; P3M0 = P3M1 = 0x00; IT0 = 1; IT1 = 1; // INT0/INT1下降沿触发 IE0 = 0; IE1 = 0; // 清除标志 INTCLKO |= 0x70; // 使能INT2/3/4 __asm__("NOP"); __asm__("NOP"); __asm__("NOP"); EX0 = 1; EX1 = 1; // 使能INT0/INT1 EA = 1; // 总中断开 } void INT0_ISR(void) interrupt 0 { LED0 = ~LED0; } void INT1_ISR(void) interrupt 2 { LED1 = ~LED1; } void INT2_ISR(void) interrupt 10 { LED2 = ~LED2; } void INT3_ISR(void) interrupt 11 { LED3 = ~LED3; } void INT4_ISR(void) interrupt 16 { LED4 = ~LED4; } void main(void) { LED0=LED1=LED2=LED3=LED4=1; ExtInt_All_Init(); while(1) { } }
🎯 示例3.3:上升/下降沿同时触发判断(IT0=0)
void INT0_ISR(void) interrupt 0 { if (P32) // P3.2为高电平 → 上升沿触发 { // 处理上升沿事件(如按键释放) } else // P3.2为低电平 → 下降沿触发 { // 处理下降沿事件(如按键按下) } }
四 常见问题与对策
❌ 问题1:上电后立即误入中断
原因:上电时INT0/INT1引脚电平从0→VCC变化被检测为上升沿,IE0/IE1被硬件置1。
✅ 解决:在
EX0=1 之前先清零 IE0 并加3个NOP延时
❌ 问题2:INT2/INT3/INT4不能触发
原因:忘记配置INTCLKO寄存器使能。
✅ 解决:INTCLKO不可位寻址,必须整体赋值:
INTCLKO |= 0x70;
🔧 问题3:中断优先级配置
INT0和INT1的优先级通过IP/IP2寄存器配置(4级可选),INT2/3/4固定为最低优先级。
如需INT0为最高优先级:
PX0 = 1; PX1 = 0;
🔌 问题4:按键抖动问题
机械按键在闭合和释放时会产生抖动,导致一次按键触发多次中断。
✅ 推荐方案:中断中仅置位标志位,由主循环进行消抖和逻辑处理
📚 参考资料
📖 官方数据手册
STC官网下载
stcmicro.com
🛠️ STC-ISP工具
内置头文件生成、范例程序
📘 参考教材
丁向荣 · 清华大学出版社
💬 官方论坛
STC爱好者社区
stcaimcu.com
STC8H8K64U · 22个中断源 · 4级中断优先级 · INT0/INT1支持上升沿和下降沿中断
本站所有文章、数据、图片来源于网络,仅供学习使用,如有侵权,联系删除!