【单片机NEW01】外部中断、闲时模式和掉电模式(带代码模板)

学习目标:

  • 理解掌握,通过实例验证学习掌握情况

学习内容:

  1. 外部中断程序
  2. 如何设置闲时模式和掉电模式
  3. 唤醒机制
  4. 完整代码示例

正文:

一、外部中断程序

在51单片机(如STC89C52RC)中,外部中断是一种重要的功能,用于响应外部事件(如按键按下、传感器触发等)。以下是关于51单片机外部中断的详细说明:


外部中断概述

51单片机通常支持 2个外部中断

  • INT0:对应P3.2引脚
  • INT1:对应P3.3引脚

每个外部中断可以配置为 电平触发边沿触发,并通过中断服务函数(ISR)处理事件。


寄存器配置

51单片机的外部中断相关寄存器如下:

1. TCON寄存器(定时器/计数器控制寄存器)

名称功能描述
BIT7TF1定时器1溢出标志
BIT6TR1定时器1运行控制位
BIT5TF0定时器0溢出标志
BIT4TR0定时器0运行控制位
BIT3IE1外部中断1(INT1)触发标志
BIT2IT1外部中断1触发方式控制(0=电平,1=边沿)
BIT1IE0外部中断0(INT0)触发标志
BIT0IT0外部中断0触发方式控制(0=电平,1=边沿)
  • IT0/IT1
    • 0:低电平触发
    • 1:下降沿触发

2. IE寄存器(中断使能寄存器)

名称功能描述
BIT7EA总中断使能(1=使能,0=禁止)
BIT6-保留
BIT5ET2定时器2中断使能
BIT4ES串口中断使能
BIT3ET1定时器1中断使能
BIT2EX1外部中断1(INT1)使能
BIT1ET0定时器0中断使能
BIT0EX0外部中断0(INT0)使能
  • EX0/EX1
    • 1:使能外部中断
    • 0:禁止外部中断

外部中断配置步骤

  1. 设置触发方式
    • 配置TCON寄存器的IT0IT1位,选择电平触发或边沿触发。
  2. 使能中断
    • 配置IE寄存器的EX0EX1位,使能外部中断。
    • 配置IE寄存器的EA位,开启总中断。
  3. 编写中断服务函数
    • 使用interrupt关键字定义中断服务函数。

代码示例

1. 外部中断初始化

void Init_External_Interrupt() {
    IT0 = 1;    // 设置INT0为下降沿触发
    IT1 = 1;    // 设置INT1为下降沿触发
    EX0 = 1;    // 使能INT0中断
    EX1 = 1;    // 使能INT1中断
    EA = 1;     // 开启总中断
}

2. 中断服务函数

// INT0中断服务函数
void INT0_ISR() interrupt 0 {
    // 处理INT0事件
}

// INT1中断服务函数
void INT1_ISR() interrupt 2 {
    // 处理INT1事件
}

触发方式详解

1. 电平触发

  • 配置IT0 = 0IT1 = 0
  • 特点
    • 当引脚为低电平时,持续触发中断。
    • 需要在中断服务函数中清除外部信号,否则会重复触发。

2. 边沿触发

  • 配置IT0 = 1IT1 = 1
  • 特点
    • 当引脚电平从高到低变化时,触发一次中断。
    • 适用于按键等短时信号。

注意事项

  1. 消抖处理

    • 按键等机械开关会产生抖动,需在硬件或软件中消抖。
    • 硬件消抖:在按键两端并联0.1μF电容。
    • 软件消抖:在中断服务函数中加入延时检测。
  2. 中断优先级

    • 51单片机的中断优先级固定为:INT0 > T0 > INT1 > T1 > UART
    • 若需修改优先级,可使用IP寄存器。
  3. 中断标志位

    • 电平触发时,需在中断服务函数中清除外部信号,避免重复触发。
    • 边沿触发时,硬件会自动清除标志位。

示例:按键控制LED

功能描述

  • 按下按键1(INT0)时,LED状态翻转。
  • 按下按键2(INT1)时,LED熄灭。

代码实现

/*********************************************************************************************/

#include <REG51.h> //51头文件
#include <intrins.h>

sbit 	LED 	= 	P1 ^ 0; //定义LED灯

//注:外部中断固定与P3.2和P3.3复用,无需定义这两个接口。

/*********************************************************************************************
函数名:外部中断INT初始化函数
调  用:INT_init();
参  数:无
返回值:无
结  果:启动外部中断INT1、INT0中断,设置中断方式
备  注:
/**********************************************************************************************/
void INT_init (void){
	EA = 1;	//中断总开关
	EX1 = 1; //允许外部中断1中断    
	EX0 = 1; //允许外部中断0中断
	IT1 = 1; //1:下沿触发  0:低电平触发
	IT0 = 1; //1:下沿触发  0:低电平触发
}
/**********************************************************************************************/


/*********************************************************************************************
函数名:外部中断INT1中断处理程序
调  用:[外部引脚INT1中断处理]
参  数:无
返回值:无
结  果:用户处理外部中断信号
备  注:
/**********************************************************************************************/
void INT_1 (void) interrupt 2  using 2{ //切换寄存器组到2

	LED = 1; //关灯

}	
/**********************************************************************************************/

/*********************************************************************************************
函数名:外部中断INT0中断处理程序
调  用:[外部引脚INT0中断处理]
参  数:无
返回值:无
结  果:用户处理外部中断信号
备  注:
/**********************************************************************************************/
void INT_0 (void) interrupt 0  using 2{ //切换寄存器组到2

	LED = 0; //开灯

}	
/**********************************************************************************************/

/*********************************************************************************************/
void main(void){
	INT_init(); //外部中断初始化
	while(1){

	    PCON |= 0x01;   // 设置IDL位进入空闲模式 (PCON |= 0x02;进入掉电模式)
       _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();        // 唤醒后继续执行此处
       _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();	
 
	}
}

二、空闲模式 vs 掉电模式

特性空闲模式(Idle Mode)掉电模式(Power Down Mode)
功耗较低(CPU停止,外设和时钟仍运行)极低(CPU和外设均停止,时钟关闭)
唤醒方式任何中断(外部中断、定时器中断、串口中断等)仅外部中断(INT0/INT1)或复位信号(RST)
唤醒后执行位置从进入空闲模式的下一条指令继续执行从进入掉电模式的下一条指令继续执行
时钟状态系统时钟继续运行系统时钟停止
外设状态外设保持运行状态外设停止运行
唤醒时间较短(仅需恢复CPU运行)较长(需重新启动时钟和外设)
典型应用场景短时低功耗,需快速唤醒长时间低功耗,仅需外部事件唤醒
寄存器配置`PCON= 0x01;`(设置IDL位)
唤醒后外设恢复无需恢复,外设保持运行需重新初始化外设(如定时器、串口等)
电流消耗约1-5mA(取决于外设运行状态)约0.1μA-1μA(极低功耗)

代码示例对比

空闲模式代码

void Enter_Idle_Mode() {
    PCON |= 0x01;   // 设置IDL位进入空闲模式
    _nop_();        // 唤醒后继续执行此处
    _nop_();
}

掉电模式代码

void Enter_PowerDown_Mode() {
    PCON |= 0x02;   // 设置PD位进入掉电模式
    _nop_();        // 唤醒后继续执行此处
    _nop_();
}

三、唤醒机制对比

空闲模式唤醒

  • 唤醒源
    • 任何中断(如外部中断、定时器中断、串口中断等)。
  • 唤醒流程
    • 中断触发后,CPU立即恢复运行,从进入空闲模式的下一条指令继续执行。

掉电模式唤醒

  • 唤醒源
    • 仅外部中断(INT0/INT1)或复位信号(RST)。
  • 唤醒流程
    • 中断触发后,系统时钟重新启动,CPU从进入掉电模式的下一条指令继续执行。

功耗对比

模式典型电流消耗(3.3V供电)
空闲模式1-5mA
掉电模式0.1μA-1μA

四、完整代码示例(以51单片机为例)

  • 空闲模式适合需要快速唤醒且外设需保持运行的场景,功耗相对较高。
#include <reg52.h>
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int

sbit LED = P1^0;        // LED指示灯(低电平点亮)
sbit KEY_IDLE = P3^2;   // 空闲模式按键(INT0)
sbit KEY_WAKEUP = P3^3;  // 唤醒按键(INT1)

bit idle_flag = 0;       // 空闲模式标志位
bit wakeup_flag = 0;     // 唤醒标志位

/* 延时函数 */
void delay_ms(uint ms) {
    uint i, j;
    for(i=0; i<ms; i++)
        for(j=0; j<114; j++);
}

/* 进入空闲模式 */
void enter_idle_mode() {
    LED = 1;            // 熄灭LED
    PCON |= 0x01;       // 设置IDL位进入空闲模式
    _nop_();            // 等待唤醒后继续执行
    _nop_();
    LED = 0;            // 唤醒后点亮LED
}

/* 中断初始化 */
void init_interrupt() {
    IT0 = 1;            // 设置INT0下降沿触发
    IT1 = 1;            // 设置INT1下降沿触发
    EX0 = 1;            // 使能INT0中断(空闲模式按键)
    EX1 = 1;            // 使能INT1中断(唤醒按键)
    EA = 1;             // 开启总中断
}

/* 主函数 */
void main() {
    LED = 0;            // 初始化点亮LED
    init_interrupt();
    
    while(1) {
        // 检测模式标志位
        if(idle_flag) {
            idle_flag = 0;
            enter_idle_mode();
        }

        // 检测唤醒按键
        if (KEY_WAKEUP == 0) {
            delay_ms(10); // 消抖
            if (KEY_WAKEUP == 0) {
                wakeup_flag = 1; // 设置唤醒标志
            }
            while (KEY_WAKEUP == 0); // 等待按键释放
        }

        if (wakeup_flag) {
            wakeup_flag = 0;
            // 唤醒后的处理逻辑
            LED = 0;  // 点亮LED
            // 可以在此添加其他唤醒后的操作
        }
    }
}

/* INT0中断服务函数(空闲模式) */
void int0_isr() interrupt 0 {
    delay_ms(20);               // 消抖处理
    if(KEY_IDLE == 0) {         // 确认按键按下
        idle_flag = 1;          // 设置空闲模式标志
    }
}

/* INT1中断服务函数(唤醒按键) */
void int1_isr() interrupt 2 {
    delay_ms(20);               // 消抖处理
    if(KEY_WAKEUP == 0) {        // 确认按键按下
        wakeup_flag = 1;          // 设置唤醒标志
    }
}
  • 掉电模式适合长时间低功耗场景,功耗极低,但唤醒源有限且唤醒时间较长。
#include <reg52.h>
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int

sbit LED = P1^0;        // LED指示灯(低电平点亮)
sbit KEY_PDOWN = P3^2;  // 掉电模式按键(INT0)
sbit KEY_WAKEUP = P3^3; // 唤醒按键(INT1)

bit pd_flag = 0;         // 掉电模式标志位
bit wakeup_flag = 0;     // 唤醒标志位

/* 延时函数 */
void delay_ms(uint ms) {
    uint i, j;
    for(i=0; i<ms; i++)
        for(j=0; j<12; j++);
}

/* 进入掉电模式 */
void enter_power_down() {
    LED = 1;            // 熄灭LED
    PCON |= 0x02;       // 设置PD位进入掉电模式
    _nop_();            // 唤醒后从下一指令继续执行
    _nop_();
    LED = 0;            // 唤醒后点亮LED
}

/* 中断初始化 */
void init_interrupt() {
    IT0 = 1;            // 设置INT0下降沿触发
    IT1 = 1;            // 设置INT1下降沿触发
    EX0 = 1;            // 使能INT0中断(掉电模式按键)
    EX1 = 1;            // 使能INT1中断(唤醒按键)
    EA = 1;             // 开启总中断
}

/* 主函数 */
void main() {
    LED = 0;            // 初始化点亮LED
    init_interrupt();
    
    while(1) {
        // 检测模式标志位
        if(pd_flag) {
            pd_flag = 0;
            enter_power_down();
        }

        // 检测唤醒按键
        if (KEY_WAKEUP == 0) {
            delay_ms(10); // 消抖
            if (KEY_WAKEUP == 0) {
                wakeup_flag = 1; // 设置唤醒标志
            }
            while (KEY_WAKEUP == 0); // 等待按键释放
        }

        if (wakeup_flag) {
            wakeup_flag = 0;
            // 唤醒后的处理逻辑
            LED = 0;  // 点亮LED
            // 可以在此添加其他唤醒后的操作
        }
    }
}

/* INT0中断服务函数(掉电模式) */
void int0_isr() interrupt 0 {
    delay_ms(20);               // 消抖处理
    if(KEY_PDOWN == 0) {         // 确认按键按下
        pd_flag = 1;          // 设置掉电模式标志
    }
}

/* INT1中断服务函数(唤醒按键) */
void int1_isr() interrupt 2 {
    delay_ms(20);               // 消抖处理
    if(KEY_WAKEUP == 0) {        // 确认按键按下
        wakeup_flag = 1;          // 设置唤醒标志
    }
}

@外部中断代码参考来源于http://www.doyoung.net/DY/program/INT/index.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值