STC8H8K64U 外部中断

⚡ STC8H8K64U 外部中断

外部中断应用开发指南 · 寄存器详解 · C代码示例

INT0 INT1 INT2 INT3 INT4

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响应中断后

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支持上升沿和下降沿中断

本站所有文章、数据、图片来源于网络,仅供学习使用,如有侵权,联系删除!