首先是按键中止处理进程:
1、中止控制器聚集各类外设宣布的中止信号,然后告知CPU
2、CPU保存当时程序的运转环境(各个寄存器等),调用中止服务程序(ISR,Interrupt Service Routine)
3、在ISR中经过读中止控制器、外设的相关寄存器来辨认这是哪个中止,并进行相应的处理
4、清楚中止:经过读写中止控制器和外设的相关寄存器来完结
5、最好康复中止程序的运转环境(即上面保存的各个寄存器等),持续履行
按键中止程序设计流程:
1、按键以及按键中止初始化
1)对按键中止端口初始化,设置为特别功用形式(10)
2)设置外部中止触发方法(EXTINTn低电平触发000、高电平触发001、上升沿触发11x、下降沿触发01x)
3)清外部中止挂起寄存器(EINTPEND)、源挂起寄存器(SRCPND)、中止挂起寄存器(INTPND),对其写1清零,避免原有中止产生的搅扰
4)中止进口函数,也便是把中止服务子程序赋给对应的中止进口地址(pISR_EINT8_23)
5)封闭外部中止屏蔽寄存器(EINTMASK)和中止屏蔽寄存器(INTMSK),也便是使能中止,0使能,1屏蔽
2、按键中止服务子程序
1)清源挂起寄存器(SRCPND)和中止挂起寄存器(INTPND)
2)经过判别EINTPEND相应的位来确定是那个按键产生了中止,然后履行相应的程序,而且对EINTPEND写1铲除相应位,避免重复产生中止
源程序:
//Main.c
/*
试验环境:mini2440开发板
完结日期:2011.4.13
作者:阿龍
完结功用:用中止方法,当按下K1时全亮,按下K2时计数,按下K3时流水灯,按下K4时全灭
遇到的问题:便是我选用低电平触发的时分,每次按键一次都会进入两次中止,这个有点没理解,也便是说当履行流水灯的时分,会循环6次。可是当履行流水灯的时分我按下计数的按键之后,一切都正常,很奇怪。
我选用低电平触发的时分,计数正常,流水灯有问题。这个问题等候今后处理。
*/
#defineGLOBAL_CLK1
#include
#include
#include “def.h”
#include “option.h”
#include “2440addr.h”
#include “2440lib.h”
#include “2440slib.h”
#include “mmu.h”
#include “profile.h”
#include “memtest.h”
/*
函数声明
*/
void delay(int times);
void LED_init(void);
void KEY_init(void);
//void LED_run(int num);
void LED_ql(void);
void LED_qm(void);
void LED_lsd(void);
void LED_js(void);
void KEYint_init(void);
static void __irq keyhandl(void);
/*
主函数
*/
void Main(void)
{
MMU_Init();
LED_init(); //LED灯初始化
KEY_init(); //按键初始化
KEYint_init(); //按键中止初始化
while(1);
}
/*
按键中止初始化
*/
void KEYint_init(void)
{
//rEXTINT1 &=~((0xa<<0)|(0xa<12)|(0xa<<20)|(0xa<<24));//设置外部中止触发方法为下降沿触发
rEXTINT1 &=~((0xf<<0)|(0xf<<12)|(0xf<<20)|(0xf<<24));//设置外部中止触发方法为低电平有用
rEINTPEND |=(1<<8)|(1<<11)|(1<<13)|(1<<14);//清外部中止挂起寄存器
ClearPending(BIT_EINT8_23);//清源中止挂起寄存器和中止挂起寄存器,避免搅扰
pISR_EINT8_23 =(U32)keyhandl;//中止进口函数
rEINTMASK &= ~((1<<8)|(1<<11)|(1<<13)|(1<<14));//封闭外部中止屏蔽(也便是使能中止)
EnableIrq(BIT_EINT8_23);//中止使能,其实便是封闭中止屏蔽
}
/*
按键中止服务子程序
*/
static void __irq keyhandl(void)
{
/*if(rINTPND == BIT_EINT8_23)
{
ClearPending(BIT_EINT8_23);
switch(rEINTPEND &0x6900)
{
case (1<<8): rEINTPEND |= 1<<8;LED_run(4);LED_run(1);break;
case (1<<11):rEINTPEND |= 1<<11;LED_run(4);LED_run(2);break;
case (1<<13):rEINTPEND |= 1<<13;LED_run(4);LED_run(3);break;
case (1<<14):rEINTPEND |= 1<<14;LED_run(4);break;
}
}*/
//方法二
if(rINTPND == BIT_EINT8_23)
{
ClearPending(BIT_EINT8_23);
if(rEINTPEND &(1<<8))
{
rEINTPEND |= 1<<8;//清外部中止挂起寄存器,避免重复产生中止
//LED_qm();
LED_ql();
}
if(rEINTPEND &(1<<11))//当我选用下降沿触发的时分,这个程序履行正常
{
rEINTPEND |= 1<<11;
//LED_qm();
LED_js();
}
if(rEINTPEND &(1<<13))//不管用什么触发,这个程序都要进入两次中止,就算我选用下降沿,
//我一向按着按键,程序就会一向履行,理论上应该没有下降沿就会履行程序一次
{
rEINTPEND |= 1<<13;
//LED_qm();
LED_lsd();
}
if(rEINTPEND &(1<<14))
{
rEINTPEND |= 1<<14;
LED_qm();
}
}
}
/*
延时函数
*/
void delay(int times)
{
int x,y;
for(x=times;x>0;x–)
for(y=500;y>0;y–);
}
/*
LED初始化
*/
void LED_init(void)
{
rGPBCON &=~((0x3<<10)|(0x3<<12)|(0x3<<14)|(0x3<<16));//GPB0设置为保存不必
rGPBCON |= ((0x1<<10)|(0x1<<12)|(0x1<<14)|(0x1<<16));//设置GPB5,GPB6,GPB7,GPB8,为输入形式(rGPBCON对应位为01)
rGPBUP =0xFFFFFFFF;
}
/*
按键初始化
*/
void KEY_init(void)
{
rGPGCON &=~((0x3<<0)|(0x3<<6)|(0x3<<10)|(0x3<<12)|(0x3<<14)|(0x3<<22));
rGPGCON |= ((0x2<<0)|(0x2<<6)|(0x2<<10)|(0x2<<12)|(0x2<<14)|(0x2<<22));
rGPGUP =0xFFFFFFFF;
rGPBDAT |= (1<<5)|(1<<6)|(1<<7)|(1<<8);//悉数让他灭,避免搅扰
}
/*
LED灯的运转作用挑选
*/
/*void LED_run(int num)
{
switch(num)
{
case 1: LED_ql();break;
case 2: LED_js();break;
case 3: LED_lsd();break;
case 4: LED_qm();break;
}
}*/
/*
LED灯全亮
*/
void LED_ql(void)
{
rGPBDAT &= (0<<5)|(0<<6)|(0<<7)|(0<<8);
}
/*
LED灯全灭
*/
void LED_qm(void)
{
rGPBDAT |= (1<<5)|(1<<6)|(1<<7)|(1<<8);
}
/*
流水灯
*/
void LED_lsd(void)
{
int i;
for(i=3;i>0;i–)//流水灯循环3次
{
rGPBDAT &= (0<<5)|(1<<6)|(1<<7)|(1<<8);
delay(40000);
rGPBDAT |= (1<<5)|(1<<6)|(1<<7)|(1<<8);
rGPBDAT &= (1<<5)|(0<<6)|(1<<7)|(1<<8);
delay(40000);
rGPBDAT |= (1<<5)|(1<<6)|(1<<7)|(1<<8);
rGPBDAT &= (1<<5)|(1<<6)|(0<<7)|(1<<8);
delay(40000);
rGPBDAT |= (1<<5)|(1<<6)|(1<<7)|(1<<8);
rGPBDAT &= (1<<5)|(1<<6)|(1<<7)|(0<<8);
delay(40000);
rGPBDAT |= (1<<5)|(1<<6)|(1<<7)|(1<<8);
}
}
/*
LED以二进制方法计数(0-15)
*/
void LED_js(void)
{
int i;
rGPBDAT=~0x02f;//最终四位设为1的意图主要是把蜂鸣器屏蔽掉,前面设为保存也不管用,只能这儿设置
for(i=0;i<15;i++)
{
delay(60000);
//rGPBDAT=~rGPBDAT; //假如选用这个去取反,当我单步调试的时分,蜂鸣器会宣布响声,所以我直接在下面句子中直接取反
rGPBDAT=~(~rGPBDAT+0x020);//没运转一次,第5位加1进位
}
}