三十四.通过按键玩中断

1.中断 :向CPU发出请求停止当前任务处理发出请求的外设的事件。另外一种CPU和外设交互的方式是轮询,效率太低了。

2.中断生命周期:
     (1)信号产生(中断源)
     (2)信号过滤(中断控制器)
     (3)信号处理(CPU)

3.不同的CPU可以处理的中断源数目不一样

4关于中断过滤,分为有无子中断,见下图

     


5.中断处理,2440是采用非向量方式,每次都有固定的入口地址,然后用软件来判断中断源,效率比较低


6.6410和210是采用向量方式,由于在初始化的时候就已经将各种中断源的处理程序的入口地址和硬件的中断标志一一匹配了,所以是有硬件直接决定当某个中断发生的时候执行某个具体的中断处理函数,效率高

7.软件任务

(1)对中断源初始化
(2)对中断控制器初始化(先是子中断控制器,再是中断控制器),打开中断(因为之前屏蔽了)
(3)针对是否是采用向量方式编写相应的CPU处理函数。
(4)中断清0,比较特殊,是写1清0 
(5)对中断模式下的SP指针做初始化

8.在start.s里面,跳转到中断处理函数用的是相对跳转,不是绝对跳转

9. start.s栈初始化

@初始化栈
init_stack:
	mrs	r0,	cpsr@用读-修改-写 的方式设置CPU的工作模式(CPSR寄存器)
	bic	r0,r0,#0x1F
	orr	r0,r0,#0xD2
	msr	cpsr,	r0
	
	ldr	sp,	=0x5F700000 @设置IRQ模式的堆栈
	
	mrs	r0,	cpsr
	bic	r0,r0,#0x1F
	orr	r0,r0,#0xD3
	msr	cpsr,	r0
	
	ldr	sp,	=0x5F000000@设置SVC模式的堆栈
	
	mov	pc,	lr
	

10 .中断源初始化

/****************************
@File:key.c
@
@Tiny6410裸机下学期代码
@按键初始化文件
@Author:小君君
@****************************/

#include "common.h"

/************************
*8颗按键都初始化为中断模式
*
***********************/
void button_init()
{
	(vi KEYCON) &= ~((K1_MSK)|(K2_MSK)|(K3_MSK)|(K4_MSK)|(K5_MSK)|(K6_MSK));
	(vi KEYCON) |= ((K1_OK)|(K2_OK)|(K3_OK)|(K4_OK)|(K5_OK)|(K6_OK));
	
	(vi KEYCON1) &= ~(K7_MSK | K8_MSK);
	(vi KEYCON1) |= (K7_OK | K8_OK);
}

11. 中断控制器初始化

/****************************
@File:common.h
@
@Tiny6410裸机下学期代码
@中断文件
@Author:小君君
@****************************/

#include "common.h"


/*按键1-4处理函数*/
void key1_4handle()
{
	printf("x is: %d\ty is : %d\n",1,1);
	/*1.现场保护*/
	__asm__( 
    
	    "sub lr, lr, #4\n"  
	    "stmfd sp!, {r0-r12, lr}\n"       
	    : 
	    : 
	   );	
	   
	 /*2.响应中断,中断处理函数*/
	 switch((vi EXT_INT_0_PEND)){
	 	case (1 << 0 ):
	 		led1_on();
	 		break;
	 	case (1 << 1 ):
	 		led2_on();
	 		break;
	 	case (1 << 2 ):
	 		led3_on();
	 		break;
	 	case (1 << 3 ):
	 		led4_on();
	 		break;
	 	default:
	 		break; 
	 }	 
	 /*3.清除中断标志位*/
	 (vi EXT_INT_0_PEND) = ~0x0;  
    	 (vi VIC0ADDRESS) = 0; 
    	 (vi VIC1ADDRESS) = 0;
	 /*4.恢复现场*/
	 __asm__( 
	    "ldmfd sp!, {r0-r12, pc}^ \n"       
	    : 
	    : 
	  );
}


/*按键5-6处理函数*/
void key5_6handle()
{
	printf("x is: %d\ty is : %d\n",1,1);
	/*1.现场保护*/
	__asm__( 
    
	    "sub lr, lr, #4\n"  
	    "stmfd sp!, {r0-r12, lr}\n"       
	    : 
	    : 
	   );	
	   
	 /*2.响应中断,中断处理函数*/
	 if((vi EXT_INT_0_PEND) & (1 << 4))
	 	led5_on();
	 else if((vi EXT_INT_0_PEND) & (1 << 5))
	 	led6_on();
	 /*3.清除中断标志位*/
	 (vi EXT_INT_0_PEND) = ~0x0;  
    	 (vi VIC0ADDRESS) = 0; 
    	 (vi VIC1ADDRESS) = 0;
	 /*4.恢复现场*/
	 __asm__( 
	    "ldmfd sp!, {r0-r12, pc}^ \n"       
	    : 
	    : 
	  );
}


/*按键7处理函数*/
void key7_handle()
{
	printf("x is: %d\ty is : %d\n",1,1);
	/*1.现场保护*/
	__asm__( 
    
	    "sub lr, lr, #4\n"  
	    "stmfd sp!, {r0-r12, lr}\n"       
	    : 
	    : 
	   );	
	   
	 /*2.响应中断,中断处理函数*/
	 led7_on();
	 	 
	 /*3.清除中断标志位*/
	 (vi EXT_INT_0_PEND) = ~0x0;  
    	 (vi VIC0ADDRESS) = 0; 
    	 (vi VIC1ADDRESS) = 0;
	 /*4.恢复现场*/
	 __asm__( 
	    "ldmfd sp!, {r0-r12, pc}^ \n"       
	    : 
	    : 
	  );
}

/*按键8处理函数*/
void key8_handle()
{
	printf("x is: %d\ty is : %d\n",1,1);
	/*1.现场保护*/
	__asm__( 
    
	    "sub lr, lr, #4\n"  
	    "stmfd sp!, {r0-r12, lr}\n"       
	    : 
	    : 
	   );	
	   
	 /*2.响应中断,中断处理函数*/
	 led8_on();
	 	 
	 /*3.清除中断标志位*/
	 (vi EXT_INT_0_PEND) = ~0x0;  
    	 (vi VIC0ADDRESS) = 0; 
    	 (vi VIC1ADDRESS) = 0;
	 /*4.恢复现场*/
	 __asm__( 
	    "ldmfd sp!, {r0-r12, pc}^ \n"       
	    : 
	    : 
	  );
}

void irq_init()
{
	/*1.设置中断触发方式*/
	(vi EXT_INT_0_CON) &= ~((0x7 << 0) | (0x7 << 4) | (0x7 << 8));/*K1-K6双边沿触发*/
	(vi EXT_INT_0_CON) |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8));
	
	(vi EXT_INT_1_CON) &= ~((0x7 << 4) | (0x7 << 8));/*K7-K8下降沿触发*/
	(vi EXT_INT_1_CON) |= ((0x2 << 4) | (0x2 << 8));
	
	/*2.使能外部中断,要用到VICINT控制寄存器*/
	(vi EXT_INT_0_MASK) = 0; /*使能EINT0--EINT27所有的外部中断*/
	
	(vi VIC0INTENABLE) |= 0x3; /* bit0: eint0~3, bit1: eint4~11 */
	(vi VIC1INTENABLE) |= 0x3; /* bit0: eint12~19, bit1: eint20~27 */
	
	/*3.注册中断处理函数*/
	(vi EINT0_VECTADDR) = (int)key1_4handle;           /* 用户按下key时,CPU就会自动的将VIC0VECTADDR0的值赋给VIC0ADDRESS并跳转到这个地址去执 */  
    	(vi EINT1_VECTADDR) = (int)key5_6handle; 
    	
    	
    	
    	(vi EINT19_VECTADDR) = (int)key7_handle;  	
    	(vi EINT20_VECTADDR) = (int)key8_handle;
	
	/*4.开启向量中断模式*/
	__asm__( 
    
	    "mrc p15,0,r0,c1,c0,0\n"
	    "orr r0,r0,#(1<<24)\n"
	    "mcr p15,0,r0,c1,c0,0\n"
	
	    "mrs r0,cpsr\n"
	    "bic r0, r0, #0x80\n"
	    "msr cpsr, r0\n"            
	    : 
	    : 
  	);
	
}
12.测试文件

/****************************
@File:main.c
@
@Tiny6410裸机上学期代码
@按键中断文件
@Author:小君君
@****************************/

#include "common.h"

int main(void)
{
	
	//mmu_init();//MMU初始化,这里不使用MMU
	
	led_init();//LED的GPIO初始化
	
	button_init();//按键初始化
	
	irq_init();//中断初始化
	
	led_on();//点亮4颗LED
	
	while(1)
	;
	return 0;	
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值