这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 高校专区 » 坤创E-Geek/天科大新电社 » 第十一届蓝桥杯信息技术人才大赛-单片机竞赛备赛分享六——外部中断实战讲解

共5条 1/1 1 跳转至

第十一届蓝桥杯信息技术人才大赛-单片机竞赛备赛分享六——外部中断实战讲解

工程师
2020-01-17 21:56:52     打赏

哈喽哈喽大家好,我是阿飞的小蝴蝶,大家可以叫我阿飞或者小飞,我又回来啦,嘻~


昨天呢,我们详细的讲解了一下有关外部中断的基础知识,这部分知识老师上课时也有讲过,再加上昨天的复习内容,相信大家都能熟练的掌握了吧,好的,话不多说,直接来看一下我们昨天留下的那两个小练习:


1、使用外部中断0,通过按键S5来控制流水灯的方向(初始为 P1^0 -> P1^7,按下按键时改为P1^7 -> P1^0,再次按下时改为P1^0 -> P1^7... ) 


#include "stc15f2k60s2.h"
#define u8 unsigned char
#define u16 unsigned int
bit mode=1;
void HC138(u8 i)
{
 switch(i)
 {
  case 4: P2 = (P2 & 0x1f) | 0x80; break;
  case 5: P2 = (P2 & 0x1f) | 0xa0; break;
  case 6: P2 = (P2 & 0x1f) | 0xc0; break;
  case 7: P2 = (P2 & 0x1f) | 0xe0; break;
 }
}
void delayms(u16 z)  
{  
 u16 x,y;  
 for(x=z;x>0;x--)  
  for(y=845;y>0;y--);  
}  
void init_P0(void)
{
 HC138(4);
 P0 = 0xff;
 HC138(5);
 P0 = 0x00;
 HC138(6);
 P0 = 0xff;
 HC138(7);
 P0 = 0xff;
}
void main()
{
 u8 i;
 EA = 1; EX0 = 1;
 IT0 = 1;
 init_P0();
 while(1)
 {
   HC138(4);
   P0 = ~(~(0xfe) << i);
   delayms(500);
   if(mode)
   {
     i++;
    if(i == 8) i = 0;
   }
   else 
   {
    i--;
    if(i == 0xff) i = 7;
   }
 }
}
void int_0() interrupt 0
{
 EX0 = 0;
 mode = ~mode;
 EX0 = 1;
}


现在来分析一下这段程序:(题目对应蓝桥杯应该是P0端口)

这段程序我们使用的是INT0,开头定义的变量“mode”控制LED灯移动方向的标志位,因为程序中只需要两个方向的切换,所以这个标志位只需要一位(0和1)就可以控制,所以我们为了节省存储,把变量定义成了“bit”型变量,那么。。模式是怎么来切换的呢?我们来看主函数循环中那个判断语句:当“mode = 1”时,流水灯的方向为从P0^0~P0^7,当”mode == 0“时,流水灯的方向为从P0^7~P0^0,所以我们只要在触发中断的时候改变一下mode的值就可以了。

在主函数中,除了一些初始化以外,就只写了流水灯和mode对应的流水灯方向的程序,在程序最后边的中断处理函数中来改变mode的取值,这样一来,当我们按下按键S5时就会触发中断,流水灯的方向就会发生改变。(这里写的时候存在了一个问题,还是有关于按键抖动的,这个问题大家思考一下,可以把这段程序自己修改一下)

也许有的同学会问,写这个程序明明使用独立按键就可以了,为什么非要使用中断呢?大家仔细思考一下,这个程序单单使用机械按键真的可以吗?我们都知道,机械按键在使用的时候是需要程序一直扫描的,而在流水灯的程序中,我们是加了延时函数的,在执行延时函数时,程序会停在这个地方,这时候就没有办法扫描按键,即使我们按下了按键,程序也判断不到,所以这个时候我们就需要用到中断,即使是程序停在了延时函数这个地方,当触发了中断时,程序仍然会去执行中断处理函数中的程序,我们的按键也就能被检测到啦。


好的,接下来我们看下一个练习:

2、数码管任意一位显示数字0,通过LED灯来触发外部中断,让任意LED灯以一定间隔闪烁,每当灯亮起来的时候数码管显示的数字加1


#include "stc15f2k60s2.h"
#define u8 unsigned char
#define u16 unsigned int
u8 code smgdu[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
u8 shuzhi;
void HC138(u8 i)
{
 switch(i)
 {
  case 4: P2 = (P2 & 0x1f) | 0x80; break;
  case 5: P2 = (P2 & 0x1f) | 0xa0; break;
  case 6: P2 = (P2 & 0x1f) | 0xc0; break;
  case 7: P2 = (P2 & 0x1f) | 0xe0; break;
 }
}
void delayms(u16 z)  
{  
 u16 x,y;  
 for(x=z;x>0;x--)  
  for(y=845;y>0;y--);  
}  
void init_P0(void)
{
 HC138(4);
 P0 = 0xff;
 HC138(5);
 P0 = 0x00;
 HC138(6);
 P0 = 0xff;
 HC138(7);
 P0 = 0xff;
}
void main()
{
 EA = 1; EX1 = 1;
 IT1 = 1;
 init_P0();
 HC138(6);
 P0 = 0x80;
 while(1)
 {
  HC138(4);
  P0 = 0x00;
  delayms(700);
  HC138(4);
  P0 = 0xff;
  delayms(700);
 }
}
void int_1() interrupt 2
{
 EX1 = 0;
 shuzhi++;
 if(shuzhi == 10)
  shuzhi = 0;
 HC138(7);
  P0 = smgdu[shuzhi];
 EX1 = 1;
}


还是直接来分析一下这段程序:

这段程序中使用的是INT1,我们可以看到,主函数中只写了些初始化程序和LED灯闪烁的程序,这题中我们需要用LED灯的闪烁来触发中断,当LED灯点亮时需要把IO口配置成低电平,熄灭时配置成高电平,这样一来LED灯的闪烁就可以产生高低电平交错的方波,也就有了下降沿,只要把这个电平接到对应的中断输入口(P3^3引脚)就可以触发INT1啦,所以运行这个程序时需要用杜邦线把P0端口任意一个引脚与P3^3引脚接在一起就好啦,好的这段程序与上一个类型的,大家自己看一下吧,我就不再做太多介绍啦。


到现在为止外部中断部分的内容就讲完啦,明天开始我们下一节内容:定时计数器基础知识讲解,悄悄给大家透露一下:定时器的使用比外部中断跟重要哦,学会使用定时器后,很多程序写起来都会得心应手,大家是不是已经蠢蠢欲动了呢?


好啦,今天的内容到这里就结束啦,程序中有什么问题也欢迎大家指出来,预祝大家都能取得好成绩




工程师
2020-01-17 22:20:57     打赏
2楼

楼主能讲一个用中断方式来解码红外遥控器的吗? 一直对此,我不太了解。


工程师
2020-01-17 22:28:31     打赏
3楼

此范例有对应的电路原理图就更好了~


高工
2020-01-17 23:49:21     打赏
4楼

继续加油~


工程师
2020-01-23 18:55:11     打赏
5楼

接着更新呀楼主


共5条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]