蓝桥杯单片机开发及应用-基础模块07-外部中断的应用

一、先前知识

使用到的74HC138译码器、74HC573锁存器、LED灯模块和独立按键模块等,在前面的基础模块的介绍中都有简单介绍,这里就不再介绍了。

  1. 按键之外部中断

蓝桥杯板子上按键部分的右下角有个J5模块,用跳帽来进行独立按键和矩阵键盘之间的切换。此次使用矩阵键盘的时候需要把跳帽接到2~3引脚。

蓝桥杯板子上外部中断的引脚是P3^2(INT0)和P3^1(INT1),因此需要把按键部分的跳帽接到2~3引脚来构成独立按键。

图一、按键模块

  1. 中断的相关基础概念的简单介绍

内核与外设之间的主要交互方式有两种:轮询和中断。轮询的方式看似很公平,所有的都兼顾到,但是实际工作效率很低,且不能及时响应紧急事件;而中断系统使得内核具备了应对突发事件的能力。比如:你正在家里做饭,这时突然有电话打了过来,如果按照轮询来说,那么你就必须炒完菜之后再去接电话;按照中断来说,那么你这时遇到了有电话进来的紧急情况,就先去处理完电话的事务再继续按照计划炒菜。

在执行CPU当前程序时,由于系统中出现了某种急需处理的情况,CPU暂停正在执行的程序,转而去执行另外一段特殊程序来处理出现的紧急事务,处理结束之后,CPU自动返回到原来暂停的程序中去继续执行。这种程序在执行过程中由于外界的原因而被中间打断的情况,称之为中断。

中断服务函数:内核响应中断后执行的相应处理程序。

中断向量:中断服务程序的入口地址。每个中断源都对应一个固定的入口地址。当内核响应中断请求时,就会暂停当前的程序执行,然后跳转到该入口地址执行代码。注意,请求不一定能够进中断,必须要打开中断之后,请求才能响应。

  1. 外部中断用到的寄存器

每个中断源都对应着一个固定的入口地址,也就是中断向量,它们分别是:

0 0x0003: INT0

1 0x000B: TF0

2 0x0013: INT1

3 0x001B: TF1

4 0x0023: RI/TI

图二、IE寄存器

图三、IP寄存器

图四、TCON寄存器

图五、SCON寄存器

总开关,总中断EA,只有当总中断EA接上之后,同时相应的中断EX0、ET0等也接上,外部中断才能控制内核。

图六、中断寄存器的顺序

  1. 关于中断服务函数程序的编写

一般情况下,中断的处理函数有两个,其一为中断初始化函数,其二为中断服务函数。并且初始化函数要放在主函数的里面while(1)的外面,服务函数不需要放在主函数里,需要用到时会直接跳转到中断服务函数。

初始化函数就是一个普通的函数,而中断服务函数有着特殊的格式:

①中断函数没有返回值,也不能对其输入参数;

②函数名后面要跟一个关键字“interrupt”,说明这是一个中断服务函数;

③在关键字“interrupt”后面要跟上中断号,说明这个中断服务函数是为哪个中断服务的。

例如:void 函数名() interrupt 中断号

以上关于中断的介绍并不像书上以及老师们讲的那么专业,都只是本人学习过程中的理解总结而已。如果读者想要了解的更完整、更精细,可以查看相关方面的书和资料。也欢迎各位给我提出意见。

二、模块控制实现过程简述

先把按键的跳帽接到2~3引脚上,然后定义所用到的引脚,再进行控制。要控制LED模块,就需要先往74HC138译码器中写入二进制数100(十进制数为4),输出就是Y4为低电平,经过一个或非门输出的Y4C就为高电平,再输入74HC573锁存器。然后控制LED灯的点亮。

三、所要实现的功能

L1指示灯不停闪烁,按键S5(外部中断INT0引脚所接)按下后会产生外部中断信号,响应后L8指示灯点亮延时一段时间后再熄灭。程序循环实现上述功能。

四、代码实现

①引脚定义

// 引脚定义
sbit INT0 = P3^2;

②138译码器通道选择函数

// 通道选择函数
void HC138_Init( unsigned char channel )
{
    switch( channel )
    {
        case 0:
            P2 = ( P2 & 0x1f ) | 0x00;    // 0
        break;
        case 4:
            P2 = ( P2 & 0x1f ) | 0x80;    // Y4C
        break;
        case 5:
            P2 = ( P2 & 0x1f ) | 0xa0;    // Y5C
        break;
        case 6:
            P2 = ( P2 & 0x1f ) | 0xc0;    // Y6C
        break;
        case 7:
            P2 = ( P2 & 0x1f ) | 0xe0;    // Y7C
        break;
    }
}

③初始化系统-关闭目前不需要的蜂鸣器和继电器

// 系统初始化
void Init_System(void)
{
    // 关闭LED灯
    HC138_Init( 4 );
    P0 = 0xff;
    
    // 关闭蜂鸣器和继电器
    HC138_Init( 5 );
    P0 = 0xaf;           // 1010 1111 
    
    HC138_Init( 0 );    // 关闭通道选择
    P0 = 0xff;
}

④外部中断0初始化函数

// 外部中断0初始化函数
void INT0_Init(void)
{
    IT0 = 1;    // 下降沿有效
    EX0 = 1;    // 打开IE中断控制寄存器
    EA = 1;     // 打开总中断开关
}

⑤外部中断0服务函数

// 外部中断0服务函数
void INT0_Service() interrupt 0
{
    P0 = ( P0 & 0x7f ) | 0x00;    // L8亮
    Delay_tms( 10000 );
    P0 = ( P0 & 0x7f ) | 0x80;    // L8灭
    Delay_tms( 10000 );
}

⑥控制L1闪烁的函数

// 控制L1闪烁
void LED_Control(void)
{
    HC138_Init( 4 );
    P0 = ( P0 & 0xfe ) | 0x00;    // 亮
    Delay_tms( 2000 );
    P0 = ( P0 & 0xfe ) | 0x01;    // 灭
    Delay_tms( 2000 );
}

⑦延时函数

void Delay_tms( unsigned int t )
{
    int i;
    while( t-- )
    {
        for( i=115 ; i>0 ; i-- )
        {
            
        }
    }
}

⑧整个函数展示


#include <STC15F2K60S2.H>
#include "Delay_ms.h"


// 引脚定义
sbit INT0 = P3^2;


// 通道选择函数
void HC138_Init( unsigned char channel )
{
    switch( channel )
    {
        case 0:
            P2 = ( P2 & 0x1f ) | 0x00;    // 0
        break;
        case 4:
            P2 = ( P2 & 0x1f ) | 0x80;    // Y4C
        break;
        case 5:
            P2 = ( P2 & 0x1f ) | 0xa0;    // Y5C
        break;
        case 6:
            P2 = ( P2 & 0x1f ) | 0xc0;    // Y6C
        break;
        case 7:
            P2 = ( P2 & 0x1f ) | 0xe0;    // Y7C
        break;
    }
}


// 系统初始化
void Init_System(void)
{
    // 关闭LED灯
    HC138_Init( 4 );
    P0 = 0xff;
    
    // 关闭蜂鸣器和继电器
    HC138_Init( 5 );
    P0 = 0xaf;           // 1010 1111 
    
    HC138_Init( 0 );    // 关闭通道选择
    P0 = 0xff;
}


// 外部中断0初始化函数
void INT0_Init(void)
{
    IT0 = 1;    // 下降沿有效
    EX0 = 1;    // 打开IE中断控制寄存器
    EA = 1;     // 打开总中断开关
}


// 外部中断0服务函数
void INT0_Service() interrupt 0
{
    P0 = ( P0 & 0x7f ) | 0x00;    // L8亮
    Delay_tms( 10000 );
    P0 = ( P0 & 0x7f ) | 0x80;    // L8灭
    Delay_tms( 10000 );
}


// 控制L1闪烁
void LED_Control(void)
{
    HC138_Init( 4 );
    P0 = ( P0 & 0xfe ) | 0x00;    // 亮
    Delay_tms( 2000 );
    P0 = ( P0 & 0xfe ) | 0x01;    // 灭
    Delay_tms( 2000 );
}




int main(void)
{
    Init_System();      // 系统初始化
    INT0_Init();        // 外部中断0初始化
    while(1)
    {
        LED_Control();  // 控制L1点亮
    }
}

五、运行图片

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

汽小迪

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

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

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

打赏作者

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

抵扣说明:

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

余额充值