单片机——神奇的中断嵌套实验

这篇博客介绍了如何在单片机中进行中断嵌套实验,涉及INT0和INT1中断,其中INT1优先级高于INT0。博主通过设置寄存器调整中断优先级,并利用定时器和外部中断实现LED流水灯和闪烁功能。实验重点在于处理中断之间的优先级关系,以及避免低优先级中断被阻塞。代码分为多个模块,包括主程序、中断初始化和服务函数等,展示了详细的实现过程和思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目要求:

①INT0、INT1同时存在,INT1优先级高于INT0,均为电平触发;

②主程序8个led轮动12轮,再闪烁12次;INT0的中断服务程序控制8个led闪烁13次,INT1的中断服务程序控制8个led轮动10轮(所有计数通过数码管显示,且只能用数字显示,不能用字母(16进制)计数显示)。其中,led流动一下的时间为100ms,闪烁一次所用时间为50ms,所有的定时用中断处理,不允许使用软件定时。

//========================================================================

题目分析:这个题目纯粹没事搞事,这个题目纯粹没事搞事,这个题目纯粹没事搞事。

//========================================================================

题目分析:因为不能用软件延时,因此我的考虑是开两个定时器,一个定时器走主程序,另外一个定时器就负责在外部中断来的时候走外部中断的对应功能。解决这个题目的关键在于处理好各个中断之间的优先级关系,要使INT1优先级高于INT0,就需要对相关的寄存器标志位做调整,即PX1=1,同时,因为中断优先级调整后其实最多是同级关系,比如外部中断1调高了优先级,而外部中断0本身就是最高优先级,这是物理电路制作时的默认关系,是客观存在的,是不以人的意志为转移的,所以外部中断0和外部中断1最多也就是平级,因此还需要通过PX0=0,把外部中断0的优先级调低,这样外部中断1才可能打断外部中断0。

同时,需要注意的是,定时器1的优先级在外部中断0、定时器0、外部中断1,在这几个老哥当中,他的优先级是最低的,因此我们外部中断需要实现的功能是不能直接写在外部中断里面服务函数里面的,不然led不会闪烁、流水灯不会流动,因为定时器1是进不去这两个中断的,优先级不够。所以我们的一种操作可以是,外部中断触发时,产生相应的标志位,定时器1定时检测标志位的状态,以此决定要不要执行相应的外部中断功能事件。

单片机开发平台:普中科技HC6800-EM3-V2.2

接线:JP8-J12、JP10-JP1、P32-K1、P33-K3、P35-A、P36-B、P37-C

 

代码实现:

把代码分成了不同的模块,公开如下:

//===========main.c=====================

#include <reg51.h>
#include <intrins.h>
#include "fun.h"
#include "timer0.h"
#include "int0.h"
#include "int1.h"
#include "timer1.h"

//所有功能由定时器和外部中断完成,四个中断相互配合,分别完成主程序,一号中断程序,二号中断程序
//主程序:8个发光二极管上下轮动12轮,再闪烁12次
//一号中断:8个led闪烁13次
//二号中断:led上下轮动10轮
//定时器0执行主程序,外部中断0执行1号中断,外部中断1执行2号中断,通过调整,PX1 = 1,将外部中断1优先级调整为最高级
//注意:当一个中断到来的时候,记得先关闭其他中断,执行完这个中断后,再打开别的中断继续执行

void main()
{
    T0_init();           //定时器0初始化
    INT0_init();    //外部中断0初始化
    INT1_init();    //外部中断1初始化
    Timer1Init();   //定时器1初始化
    while(1);
}

//=============================fun.c==================================

#include <reg51.h>
#include <intrins.h>
#include "fun.h"
#include "timer0.h"
#include "int0.h"
#include "int1.h"
#include "timer1.h"
/***********************************第4题***************************************************************/
//用定时器0完成主程序,定时器1配合两个外部中断完成剩余功能
uchar num=0; //流水灯程序中使用的计数变量,num=8时表明完成1次正或者反的流水
uchar flag=0;  //flag=0时运行正向流水灯,flag=1反向,flag=2闪烁
uchar count2=0;  //count2作为流水次数计数的中间变量,每流水1次产生变化后赋值给seg_num,满12清0
uint  count3=0;        //用于主程序led闪烁次数的计数变量
uchar seg_num=0;  //根据seg_num的返回值对应到数组tab[],从而显示出相应的数字
uchar temp1=0;    //定时器0为1ms定时器,temp1是用于选择数码管的变量
uchar temp2=0;    //定时器1为1ms定时器,temp2是用于选择数码管的变量
uint  count1=0; //count1是配合定时器0使用的计数变量,满50或者100清0
uint  count_T0=0; //count_T0是配合定时器1,外部中断0使用的计数变量
uint  count_T0_n=0;  //用于记录外部中断0中led闪烁次数的计数变量
uint  count_T1=0;  //count_T0是配合定时器1,外部中断1使用的计数变量
uchar flag_T0=1; //外部中断0对应标志位,flag_T0=0执行中断
uchar flag_T1=1; //外部中断1对应标志位,flag_T1=0执行中断
uchar code tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//========================================================================================================
//=============LED的work4,work5函数=========
void work4()   &

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值