×
单片机 > 单片机程序设计 > 详情

2440test中按键的分析

发布时间:2020-08-27 发布时间:
|
这里分析了4个按键,还有 ENIT8 和 EINT19没有,不过原理一样的。 
4个按键,分别是
EINT11 / GPG3
EINT13 / GPG5
EINT14 / GPG6
EINT15 / GPG7
外部上拉电阻。 
EINT 8-23 共用一个IRQ向量。 

初始化步骤
1,设置IO的功能,00 输入 01输出 02 第二功能 P292
设置的方法是
 rGPGCON &= ~(3<<3*2 | 3<<5*2 | 3<<6*2 | 3<<7*2); 
 rGPGCON |=  (2<<3*2 | 2<<5*2 | 2<<6*2 | 2<<7*2); 
2,设置 EXTINT 系列寄存器,设定中断触发的类型 P301
其中这次用到的 EINT11 13-15是分布在 EXTINT1 中
触发类型
000 低电平 001 高电平 01x 下降弦 10x 上升弦 11x 边缘触发 
 rEXTINT1 &= ~(7<<12 | 7<<20 | 7<<24 | 7<<28);
 rEXTINT1 |=  (2<<12 | 2<<20 | 2<<24 | 2<<28); 
3,设置 EINTPEND,P306
如果发生中断,该寄存器对应的位置一,没有中断则为0
清零的办法比较特殊,对对应位置一的话表示清零。
所以这里要这样做:
 rEINTPEND |= (1<<11)|(1<<13)|(1<<14)|(1<<15); 
4,设置 EINTMASK 寄存器,P305
0表示允许对应位中断,1表示禁止对应位中断,默认是禁止的
 rEINTMASK &= ~((1<<11)|(1<<13)|(1<<14)|(1<<15)); 
5,先清一下IRQ中断
作为初始化,需要先清一下,注意,刚才 EINTPEND 是清次中断,
EXTINT 8-23 都递属于 IRQ的中断号 5,所以这里清的是主IRQ中断 
ClearPending(BIT_EINT8_23); 
其中 ClearPending(); 是一个内联函数,原型在 2440addr.h
由于在头文件里面不适宜放函数的实现,所以这次移植将函数体放到
2440lib.c 里面,而 2440addr.h 保留函数的定义 
__inline void ClearPending(int bit)
{
 register i;
 rSRCPND = bit;
 rINTPND = bit;
 i = rINTPND;

函数很简单,跟前面一样,在 INTPND对应位置1就能清除该位的中断
标志了。SRCPND可以有多位置1表示多个发生中断,INTPND 表示经过
优先级裁决之后,所以同一时间只能有1位是置一的。
参考 datasheet P391
#define BIT_EINT8_23 (0x1<<5) 
初始化的时候有必要将这两个东西都清一下 

6,设置 IRQ Handleer执行中断任务
#define pISR_EINT8_23 (*(unsigned *)(_ISR_STARTADDRESS+0x34))
pISR_EINT8_23 = (U32)Key_ISR;
这部分的原理在中断移植的时候已经分析过了。这里可以简单的理解为
当外部中断8-23发生的时候,执行中断服务程序  Key_ISR 。
注意这个函数的原型,中断服务程序,所以不能有参数,也不能返回。
 void Key_ISR(void) 
7,允许中断
EnableIrq(BIT_EINT8_23);
这个宏也在刚才的 2440addr.h 里面,原型是:
#define EnableIrq(bit)  rINTMSK &= ~(bit) 
很简单,就是设置 INTMSK 对应的位而已。 
8,分析按键中断处理函数 Key_ISR
首先
EnterCritical(&r); 看名字也大概猜出是什么东西了,玩过uCOS应该很
熟悉,进入临界区,临界区这里的意思是不允许其他中断,也就是说在
处理的过程中禁止其他的IRQ中断,也就是说IRQ中断不能嵌套,这样做
的话就方便很多了。 
   .global EnterCritical
EnterCritical:   
 mrs r1, cpsr
 str r1, [r0]
 orr r1, r1, #NOINT
 msr cpsr_cxsf, r1  
 MOV_PC_LR 
在 2440slib.s 中定义汇编函数,其实功能非常简单,先读出 cpsr,保存
到R0中,因为这里是根据ATPCS的汇编和C的参数传递规则,R0中应该放的
是参数 &r,也就是说,r寄存器的地址,然后将 I 位置一(1表示禁止,
0表示开启),最后返回。
那么相对应的 ExitCritical 函数也就没啥悬念了。
 .global ExitCritical
ExitCritical:
 ldr r1, [r0]
 msr cpsr_cxsf, r1 
 MOV_PC_LR
将 r 寄存器的数值读出来,恢复到 cpsr中
至于 cpsr_cxsf 是什么东西,百度一下就知道了。 

if(rINTPND==BIT_EINT8_23)
首先判断当前的 IRQ 中断是否 EINT 8-23,是的话再根绝 EINTPEND 分析
是哪个外部中断源。
ClearPending(BIT_EINT8_23); 每次中断都要清一下的,以便能接受下一次
中断,
 if(rEINTPEND&(1<<11))
这里就很简单了,判断 EINTPEND 对应的位是否为1则能判断出是否该路
 rEINTPEND |= 1<< 11;
同样了,知道是哪个中断还得清一下标志位。  

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
ARM 汇编的必知必会