C51 中断

1.外部中断

外部中断由单片机外部引脚的电平或边沿变化触发,适用于按键、传感器等外部事件响应。


1. 外部中断资源(8051 内核)


INT0:对应引脚 P3.2,中断号 0
INT1:对应引脚 P3.3,中断号 2
触发方式:电平触发(低电平有效)或边沿触发(下降沿 / 上升沿)


2. 外部中断配置步骤


步骤 1:配置触发方式(TCON 寄存器)
IT0(INT0 触发方式):IT0=0→电平触发;IT0=1→边沿触发(下降沿)
IT1(INT1 触发方式):IT1=0→电平触发;IT1=1→边沿触发(下降沿)


步骤 2:使能中断(IE 寄存器)
EX0=1(允许 INT0 中断);EX1=1(允许 INT1 中断)
EA=1(允许总中断,必须开启)


步骤 3:编写中断服务函数
格式:void 函数名() interrupt 中断号 { ... }
INT0 中断号:0;INT1 中断号:2


3. 外部中断实战:按键控制 LED 翻转


硬件连接:按键接 P3.2(INT0),LED 接 P2.0。

#include "reg52.h"

typedef unsigned int u16;
typedef unsigned char u8;

sbit LED = P2^0;    // LED引脚
sbit KEY_INT0 = P3^2;  // INT0按键引脚

// 延时函数(用于消抖)
void delay(u16 i) {
    while(i--);
}

// INT0初始化函数
void Int0Init() {
    IT0 = 1;  // 边沿触发(下降沿)
    EX0 = 1;  // 允许INT0中断
    EA = 1;   // 允许总中断
}

// INT0中断服务函数
void Int0Handler() interrupt 0 {
    delay(1000);  // 消抖(约10ms)
    if(KEY_INT0 == 0) {  // 确认按键按下
        LED = ~LED;  // LED状态翻转
    }
}

void main() {
    Int0Init();  // 初始化中断
    while(1) {
        // 主程序可执行其他任务,中断自动响应
    }
}

2.定时器中断

定时器中断(以 T0 为例)
定时器中断由内部定时器计数溢出触发,适用于定时任务(如时钟、周期性采样)。


1. 定时器资源(8051 内核)


T0:定时器 0,中断号 1
T1:定时器 1,中断号 3
核心原理:通过计数内部机器周期,溢出时触发中断(可计算定时时间)


2. 定时器中断配置步骤


步骤 1:设置定时器模式(TMOD 寄存器)
选择工作模式(常用模式 1:16 位定时器,需手动重装初值)
TMOD &= 0xF0; TMOD |= 0x01;(配置 T0 为模式 1)


步骤 2:计算并装载初值
机器周期 = 12 / 晶振频率(如 11.0592MHz 晶振,机器周期≈1.085μs)
定时时间 =(65536 - 初值)× 机器周期 → 初值 = 65536 - 定时时间 / 机器周期
装载初值到 TH0(高 8 位)和 TL0(低 8 位)


步骤 3:使能中断(IE 寄存器)
ET0=1(允许 T0 中断);ET1=1(允许 T1 中断)
EA=1(允许总中断)


步骤 4:启动定时器并编写中断服务函数
TR0=1(启动 T0);TR1=1(启动 T1)
中断服务函数:T0 中断号 1;T1 中断号 3


3. 定时器中断实战:LED 周期性闪烁


需求:LED 每 1 秒翻转一次(晶振 11.0592MHz)。
 

#include "reg52.h"

typedef unsigned int u16;
typedef unsigned char u8;

sbit LED = P2^0;

u16 cnt = 0;  // 计数变量(记录中断次数)

// 定时器0初始化(定时10ms)
void Timer0Init() {
    TMOD &= 0xF0;  // 清除T0配置
    TMOD |= 0x01;  // T0模式1(16位定时器)
    
    // 初值计算:10ms = (65536 - 初值) × (12/11.0592MHz) → 初值≈55536
    TH0 = 0xFC;  // 高8位:55536 / 256 = 217 → 0xFC
    TL0 = 0x18;  // 低8位:55536 % 256 = 24 → 0x18
    
    ET0 = 1;  // 允许T0中断
    EA = 1;   // 允许总中断
    TR0 = 1;  // 启动T0
}

// T0中断服务函数
void Timer0Handler() interrupt 1 {
    // 重新装载初值(模式1需手动重装)
    TH0 = 0xFC;
    TL0 = 0x18;
    
    cnt++;  // 每10ms计数+1
    if(cnt >= 100) {  // 10ms × 100 = 1000ms = 1s
        cnt = 0;
        LED = ~LED;  // 每秒翻转LED
    }
}

void main() {
    Timer0Init();  // 初始化定时器
    while(1) {
        // 主程序无需干预,定时器自动定时
    }
}

### C51 单片机中断函数的使用方法 在 C51 编程环境中,中断函数是一种特殊的函数形式,用于响应硬件产生的中断事件。以下是关于如何定义和使用 C51 单片机中的中断函数的相关说明。 #### 定义中断函数的关键要素 1. **关键字 `interrupt`** 在 C51 中,中断函数通过 `interrupt n` 关键字声明,其中 `n` 表示中断号,对应于单片机的特定中断源。例如,外部中断 0 对应中断0,定时器 0 溢出中断对应中断号 1 等[^2]。 2. **中断优先级控制(可选)** 如果需要设置中断优先级,则可以附加 `using m` 参数,其中 `m` 是寄存器组编号 (0~3)[^3]。这允许开发者指定该中断使用的寄存器组,从而减少上下文切换开销。 #### 示例代码 以下是一个典型的 C51 中断函数实现: ```c #include <reg51.h> // 外部中断 0中断服务程序 void ExternalInterrupt0(void) interrupt 0 using 1 { // 清除中断标志位(具体操作取决于硬件) EX0 = 0; // 执行中断处理逻辑 P1 ^= 0xFF; // 切换端口 P1 的状态作为测试输出 // 可能还需要重新使能中断 EA = 1; } // 主函数初始化并启动中断系统 void main() { // 初始化外设配置 IT0 = 1; // 设置为下降沿触发模式 EX0 = 1; // 启用外部中断 0 EA = 1; // 开启全局中断 while (1); // 进入无限循环等待中断发生 } ``` 上述代码展示了如何编写一个针对外部中断 0中断服务程序 (ISR),并通过适当配置启用它[^3]。 #### 注意事项 - **清除中断标志**:进入 ISR 后通常要手动清除相应的中断标志位,否则可能会导致重复触发中断。 - **保护现场与恢复现场**:虽然现代编译器会自动完成部分工作,但在复杂场景下仍需注意保存重要数据以防丢失。 - **时间敏感性**:由于 ISRs 应尽可能短小精悍以降低延迟影响其他任务执行,因此不应在此类函数体内加入耗时较长的操作。 ### 总结 利用 C51 提供的功能强大的工具集——包括但不限于本征库函数以及灵活多样的语法特性,能够极大地方便开发人员构建高效可靠的嵌入式应用软件体系结构[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chem4111

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值