前面我们学习了ATmega8的I/O口作为通用数字输入/输出口来用时对LED数码管控制和扫描按键的应用;

但ATmega8多数的I/O口都是复用口,除了作为通用数字I/O使用,还有其第二功能,这里我们学习PD2、PD3两端口的第二功能:外部中断。

1.外部中断的特点:

  PD2端口是外部中断源0,PD3端口是外部中断源1。ATmega8的外部中断就是由这两个引脚触发的。

*要注意的是:如果设置允许外部中断产生,即使是INT0和INT1引脚设置为输出方式,外部中断还是会触发的。

外部中断的触发方式有三种可选性:

  (1)上升沿触发;

  (2)下降沿触发;

  (3)低电平触发。

具体方式是由以下三个决定的:

  (1)MCU的控制寄存器MCUCR

  (2)MCU控制

  (3)状态寄存器MCUCSR

*当允许外部中断且设置为低电平触发方式时,只要中断输入引脚保持低电平,就将一直触发产生中断;

*而对于上升沿或者下降沿的中断触发,则需要I/O时钟信号的存在。

要使用外部中断我们首先要了解几个寄存器:

  (1)AVR的状态寄存器SREG

  (2)MCU控制寄存器MCUCR

  (3)通用中断控制寄存器GICR

  (4)通用中断标志寄存器GIFR

详细信息有:

(1)AVR的状态寄存器SREG:

SREG的每一位都是一个标志位,位7(全局中断允许位)——I位;

  • 该位为1时全局中断使能允许,单独的中断使能则有对应的中断寄存器控制;
  • 该位为0时则不论单独允许位是否置1,所有中断都被禁止,系统将不响应任何中断。

(2)MCU控制寄存器MCUCR:

位0(ISC00)是外部中断0的中断方式控制位0;

位1(ISC01)是外部中断0的中断方式控制位1;

位2(ISC10)是外部中断1的中断方式控制位0;

位3(ISC11)是外部中断1的中断方式控制位1;

参考表与上图类似。

(3)通用中断控制寄存器GICR:

位6——INT0控制外部中断0的使能;

位7——INT1控制外部中断1的使能。

当状态寄存器SREG的I位(全局中断允许位)置1时,

  • INT0置1则外部引脚中断0使能;
  • INT1置1则外部引脚中断1使能。

(4)通用中断标志寄存器GIFR:

位6——INT0是外部中断0的标志位;

位7——INT1是外部中断1的标志位;

  • 当INT0 引脚上的有效事件触发一个中断请求后,INTF0位会变成1。
  • 如果全局中断使能且外部中断0 使能,则MCU将跳至相应的中断向量处开始执行中断服务程序,同时硬件自动将INTF0 标志位清零。

*当外部中断0被设置为低电平触发方式时,标志INTF0 位将始终为0。

扩展:

中断向量表:Atmega8共有18 个中断源,Flash程序存储器空间的最低位置(0x000—0x012)定义为复位和中断向量空间,也就是说把中断函数的地址保存在这里,当中断发生后就到这里找到对应函数的地址,然后去执行对应的函数。x向量表如下:

在中断向量表中,处于低地址的中断向量对应的中断优先级高,所以系统复位RESET拥有最高优先;

外部中断0高于外部中断1;系统复位REST不是中断。

编程准备:

用ICCAVR的编程,在C中只要用#pragma伪指令和中断向量说明中断服务程序入口地址即可:

  #pragma interrupt_handler <函数名>:<中断向量>

例如要定义使用INT0中断服务程序:

  #pragma interrupt_handler int0_fun:2

  void int0_fun()

  {

    ......

  }

2对应INT0的中断服务程序入口地址(由向量表中红色字体可知);

同理,3对应INT1的中断服务程序入口地址。

也可以让多个中断调用同一个函数,如:

  #pragma interrupt_handler int_fun:2

  #praama interrupt_handler int_fun:3

表示外部中断0和中断1都调用int_fun函数。

2.应用实例——中断计数器

用两个按键作为两个外部中断的触发源,再接一个LED数码管用来显示两位数的数据,电路图如下:

将外部中断0设置为下降沿触发(MCUCR的位1为1,位0为0),中断1设置为低电平触发(MCUCR的位3为0,位2为0);(MCUCR=0x02)

调用同一个中断函数,在中断中做数值加1,然后在LED数码管中显示。

代码如下:

 #include <iom8v.h>
#include <macros.h>
#include "Delay.h" unsigned char CountNum; //全局变量用于计数 //指明中断程序入口地址
#pragma interrupt_handler int_fun:2
#pragma interrupt_handler int_fun:3
void int_fun(void)
{
if(++CountNum>=)
CountNum -= ;
} //主函数,显示数据时先关闭中断,然后再打开
void main()
{
unsigned char tempL,tempR;
unsigned char num[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//初始化端口
DDRB = 0XFF;
PORTB = 0XFF;
DDRC = 0X03;
PORTC = 0XFF;
DDRD = 0XFF;
PORTD = 0XFF; //中断配置
SEI(); //打开全局中断
MCUCR = 0X02; //外部中断0设置为下降沿触发,中断1设置为低电平触发
GICR = 0xC0; //打开INT0、INT1中断
GIFR = 0xC0; //清除INT0、INT1中断标志位 CountNum = ; //初始化全局变量
while()
{//显示数据时关闭中断
CLI(); //关闭全局中断 //显示十位数
tempL = CountNum/;
PORTC &= ~();
PORTB = num[tempL];
delay_ms(); //显示个位数
tempR = CountNum%;
PORTC &= ~();
PORTB = num[tempR]; SEI(); //打开全局中断
delay_ms();
}
}

中断计数器

3.中断触发键盘扫描

按下键盘的任意一个按键就触发一个中断,然后在中断函数中来调用键盘处理函数。

电路图中,比上一讲的实例中多了一个74S10的与非门,作用是任意一个按键按下都可以触发一个INT0中断。

要实现的内容是:

任意一个按键按下触发一个INT0中断,INT0设置为上升沿触发方式(MCUCR=0x03),在中断中做一个标志,表示有按键按下;

然后在主函数中判断该标志位,有按键按下,消除抖动干扰,再做确认哪个按键按下,最后在LED数码管上显示按键的值。

 #include <iom8v.h>
#include <macros.h>
#include "Delay.h" unsigned char KeyDown; //按键扫描函数,返回按键的值
//unsigned char ScanKey(void)函数的实现与上一实例类似 //中断函数,设置一个标志,表示按键按下
//指明中断程序入口地址
#pragma interrupt_handler int_fun:2
void int_fun(void)
{
KeyDown = ; //在中断中仅设置一个标志
} //主函数,扫描按键显示数据
void main()
{
unsigned char temp,keynum;
unsigned char num[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //初始化端口
DDRB = 0xFF;
PORTB = 0xFF;
DDRC = 0x07;
PORTC = 0x38;
DDRD &= 0x0F;
PORTD |= 0xFC; //中断配置
SEI(); //打开全局中断
MCUCR = 0x03; //INT0上升沿触发
GICR |=0x40; //打开INT0中断
GIFR = 0xC0; //清除INT0、INT1中断标志位 KeyDown = ; //初始化全局变量
while()
{
PORTB = 0x40; //没有按键时,LED默认显示-
if(KeyDown==) //检测是否有按键按下
{
//关闭中断,恢复全局变量
GICR &= 0x00;
KeyDown = ;
delay_ms(); //防抖动,再次判断是否有按键
temp = PINC&0x38;
if(temp==0x38) //没有按键
{
GICR = 0x40; //打开INT0中断
continue;
} //有按键
keynum = ScanKey(); //获得按键值
PORTB = num[keynum]; //LED显示按键值 while(temp!=0x38) //等待按键释放
temp = PINC&0x38; //退出前开启INT0中断
GICR = 0x40;
DDRC = 0x07;
PORTC = 0x38;
}
}
}

中断触发键盘扫描

ATmega8仿真——外部中断的学习的更多相关文章

  1. ATmega8仿真——键盘扫描的学习

    1.按键的使用特点 按键的应用主要是在按键闭合时改变电路的电平,但是一般情况下按键的开关都是机械弹性触点开关,即利用触点的接触和分离来实现电路的通断,所以在按键按下和释放时往往会产生抖动干扰. 消除抖 ...

  2. stm32寄存器版学习笔记03 外部中断

    stm32的每个I/O口都可以作为中断输入,要把I/O口设置为外部中断输入,必须将I/O口设置为上拉/下拉输入 或 浮空输入(但浮空的时候外部一定要带上拉或下拉电阻,否则可能导致 中断不停的触发),干 ...

  3. STM32学习笔记(九) 外部中断,待机模式和事件唤醒

    学会知识只需要不段的积累和提高,但是如何将知识系统的讲解出来就需要深入的认知和系统的了解.外部中断和事件学习难度并不高,不过涉及到STM32的电源控制部分,还是值得认真了解的,在本文中我将以实际代码为 ...

  4. stm32学习笔记——外部中断的使用

    stm32学习笔记——外部中断的使用 基本概念 stm32中,每一个GPIO都可以触发一个外部中断,但是,GPIO的中断是以组为一个单位的,同组间的外部中断同一时间只能使用一个.比如说,PA0,PB0 ...

  5. Cortex-M3学习日志(三)-- 外部中断0

    无论是哪款单片机应该都有对应的中断的功能,中断在嵌入式系统的地位毋庸置疑.LPC1768微处理器包括4个外部中断,分别是EINT0.EINT1.EINT2.EINT3对应的引脚分别是P2.10~P2. ...

  6. STM32学习笔记(三)——外部中断的使用

    开发板芯片:STM32F407ZGT6 硬件连接:PE3-KEY1 一.STM32F4的中断介绍 STM32F4的每个IO都可以作为外部中断输入,很强大的功能吧!以前学习的51只有两个外部中断. ST ...

  7. CC2540开发板学习笔记(三)——外部中断

    一.实验内容 通过外部中断方式依次按下按键S1控制LED1的亮灭 二.实验过程 1.电路原理图同上 2.中断的概念 比如说我们在执行main函数时,突然来了个指令.优先级比现在执行的main还高,那我 ...

  8. STM32本学习笔记EXTI(外部中断)

    参考资料:STM32数据表.网络信息 =========================================切割线===================================== ...

  9. STM32学习笔记之EXTI(外部中断)

    參考资料:STM32数据手冊.网络资料 =========================================切割线==================================== ...

随机推荐

  1. SQL入门之条件表达式

    where子句和having子句主要是用来筛选符合条件的元组,其后紧跟的即为条件表达式. 0.and, or条件的连接 用法和一般编程语言一样,主要用于条件的拼接.and两边都为真,则结果为真.or两 ...

  2. VS2017 Cordova Ionic2 移动开发-环境搭建

    1. 文档概述 本文档用于说明Visual Studio 2017下使用 Ionic 2进行跨平台开发的运行环境配置. 2. 安装环境 Windows10 3. 安装 Visual Studio 20 ...

  3. sql中的for xml path() 实现字符串拼接

       通常我们需要在sql中拼接字符串   ,可以用for xml path() 来进行拼接,如下实例. 同时未去掉最后一个逗号可以用LEFT函数来实现.     ) AS UserName  FRO ...

  4. 讨论LSTM和RNN梯度消失问题

      1RNN为什么会有梯度消失问题 (1)沿时间反向方向:t-n时刻梯度=t时刻梯度* π(W*激活函数的导数)  

  5. iOS多线程的三种方法

    前言 在多线程简介中,我已经说明过了,为了提高界面的流畅度以及用户体验.我们务必要把耗时的操作放到别的线程中去执行,千万不要阻塞主线程.iOS中有以下3种多线程编程方法: NSThread Grand ...

  6. Atom打造 c/c++编译环境(忙了一个上午)

    众所周知 Atom是一款非常酷炫的编辑器.因为它就像上古卷轴一样,玩家可以开发各种dlc补丁,实现自己想要的效果.所以Atom 可以被你改造成自己想要的东西,可以用来写算法竞赛题目,可以开发网页,可以 ...

  7. 纯JS单页面赛车游戏代码分享

    分享一个以前写的小游戏,纯js游戏,代码很简单.欢迎大家来喷呦! 效果图: 代码展示://直接复制到html文件即可 支持IE9+版本 <!DOCTYPE html> <html&g ...

  8. 【Uva 10498】满意值

    Description Kaykobad教授把为ACM选手买饭的任务交给了Nasa.Nasa决定买n种不同的食物.然后他询问了m名选手对每种食物的需求量.选手们当然不会给出任何符合逻辑的回答,他们只是 ...

  9. vector介绍

    vector(向量,也可称为容器): C++中的一种数据结构,确切的说是一个类.它相当于一个动态的数组,当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间的目的. 1.1  ...

  10. JQuery实现通过点击标题切换字体

    这个主要通过判断被点击的元素的子元素中是否包含了b元素来进行字体的切换,其中wrapInner函数是为了在$author元素的内部添加b标签. 切换回正常字体是通过将内容转化为纯文本形式,再替换元素内 ...