tiny6410裸机实验第8章--------------中断(中断向量寄存器)
来源:互联网 发布:windows xp 独木成林 编辑:程序博客网 时间:2024/05/21 22:51
【说明】
前面我们的按键程序已经能工作了,但是有一个缺点。我们发现中断有64组,那就假设我们这64组全用了,当发生中断的时候,我们需要用64个IF 语句来判别到底是哪个中断组发生了,麻烦不说,还浪费时间,那有什么办法改进吗?有!6410中断控制器有个机制叫“中断向量寄存器”
【中断控制器】
1)6410有2个中断控制器,每个有31组中断,上图是0-31组的示意图
2)每一组有一个寄存器,里面可以存放该组对应的中断处理函数
3)当发生中断的时候,对应组的寄存器值会自动复制到VICxADDRESS,X指对应的控制器,比如第30组就复制给VIC0ADDRESS,32组个给VIC1ADDRESS
4)我们在初始化中断的时候就初始化对应组寄存器的处理函数,当发生中断时,软件上我们判断VICxADDRESS是不是为0,如果不是就调用它
5)调用完后我们将VICxADDRESS清为0,防止后续的中断处理出错。
6)这样就不需要判别是哪组放生了中断,很方便,但是由于一组中断又分为好多中断源,所以在某一组中断处理函数中还是需要简单得判别一下。
【源代码】
#include "stdio.h"#define GPNCON (*((volatile unsigned long *)0x7F008830))#define GPNDAT (*((volatile unsigned long *)0x7F008834))#define EINT0CON0 (*((volatile unsigned long *)0x7F008900))#define EINT0MASK (*((volatile unsigned long *)0x7F008920))#define EINT0PEND (*((volatile unsigned long *)0x7F008924))#define PRIORITY (*((volatile unsigned long *)0x7F008280))#define SERVICE (*((volatile unsigned long *)0x7F008284))#define SERVICEPEND (*((volatile unsigned long *)0x7F008288))#define VIC0IRQSTATUS (*((volatile unsigned long *)0x71200000))#define VIC0FIQSTATUS (*((volatile unsigned long *)0x71200004))#define VIC0RAWINTR (*((volatile unsigned long *)0x71200008))#define VIC0INTSELECT (*((volatile unsigned long *)0x7120000c))#define VIC0INTENABLE (*((volatile unsigned long *)0x71200010))#define VIC0INTENCLEAR (*((volatile unsigned long *)0x71200014))#define VIC0PROTECTION (*((volatile unsigned long *)0x71200020))#define VIC0SWPRIORITYMASK (*((volatile unsigned long *)0x71200024))#define VIC0PRIORITYDAISY (*((volatile unsigned long *)0x71200028))#define VIC0VECTADDR0 (*((volatile unsigned long *)0x71200100))#define VIC0VECTADDR1 (*((volatile unsigned long *)0x71200104))#define VIC0ADDRESS (*((volatile unsigned long *)0x71200f00))void eint0_3_irq(void){ int i; printf("eint0_3_irq\n\r"); /* K1~K4 */ for (i = 0; i < 4; i ++) { if (EINT0PEND & (1<<i)) { if (GPNDAT & (1<<i)) { printf("K%d released\n\r", i+1); } else { printf("K%d pressed\n\r", i+1); } } }}void eint4_11_irq(void){ int i; printf("eint4_11_irq\n\r"); /* K5~K6 */ for (i = 4; i < 6; i ++) { if (EINT0PEND & (1<<i)) { if (GPNDAT & (1<<i)) { printf("K%d released\n\r", i+1); } else { printf("K%d pressed\n\r", i+1); } } }}void irq_init(void){ /* 配置GPN0~5引脚为中断功能 */ GPNCON &= ~(0xfff); GPNCON |= 0xaaa; /* 设置中断触发方式为: 双边沿触发 */ EINT0CON0 &= ~(0xfff); EINT0CON0 |= 0x777; /* 禁止屏蔽中断 */ EINT0MASK &= ~(0x3f); /* 在中断控制器里使能这些中断 */ VIC0INTENABLE |= (0x3); /* bit0: eint0~3, bit1: eint4~11 */ // 设置中断处理函数 VIC0VECTADDR0 = (unsigned long)eint0_3_irq; VIC0VECTADDR1 = (unsigned long)eint4_11_irq;}void do_irq(void){ void (*the_isr)(void); // 读VICxADDRESS寄存器获得目前正在发生的中断的处理函数 the_isr = VIC0ADDRESS; // 调用中断处理函数 the_isr(); // 清中断 EINT0PEND = 0x3f; VIC0ADDRESS = 0;}
0 0
- tiny6410裸机实验第8章--------------中断(中断向量寄存器)
- tiny6410裸机实验第8章--------------中断(中断版UART)
- tiny6410裸机实验第8章--------------中断(原理及代码)
- 《tiny6410裸机程序》第八章:S3C6410外部中断控制寄存器
- 《tiny6410裸机程序》第八章:S3C6410总中断控制寄存器
- 中断处理(中断向量寄存器)
- tiny6410裸机实验第4章--------------UART(原理分析)
- tiny6410裸机实验第4章--------------UART(源代码分析)
- tiny6410裸机实验第4章--------------UART(printf, scanf)
- tiny6410裸机实验第5章--------------DDR(链接脚本)
- tiny6410裸机实验第5章--------------DDR(初始化原理)
- tiny6410裸机实验第5章--------------DDR(代码)
- tiny6410裸机实验第6章--------------NAND(初始化原理)
- tiny6410裸机实验第7章--------------异常(原理)
- tiny6410裸机实验第7章--------------异常(代码)
- tiny6410裸机实验第9章--------------LCD(显示字母)
- tiny6410裸机实验第4章--------------UART(原理分析)
- tiny6410裸机实验第5章--------------DDR(初始化原理)
- execve的使用方法
- hdu 1241:Oil Deposits
- 如何查看域名的历史使用记录,以前注册信息,whois,是否有被K记录
- 集合排列脑图
- try catch包含多个异常时会怎么执行
- tiny6410裸机实验第8章--------------中断(中断向量寄存器)
- sql server2008 分页语句
- C++大随机整数的产生,排序和查找
- 关于 C语言中typedef struct 和 struct
- 将php数组或者对象传递给javascript的方法
- hdu 1213:How Many Tables
- C语言中的int类型的范围是由什么决定的
- struts2文件下载示例
- Maven 及其在Eclipse 中的插件的安装