新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > ARM裸機(jī)程序設(shè)計—按鍵中斷程序設(shè)計

ARM裸機(jī)程序設(shè)計—按鍵中斷程序設(shè)計

作者: 時間:2016-11-19 來源:網(wǎng)絡(luò) 收藏
首先是按鍵中斷處理過程:

1、中斷控制器匯集各類外設(shè)發(fā)出的中斷信號,然后告訴CPU
2、CPU保存當(dāng)前程序的運(yùn)行環(huán)境(各個寄存器等),調(diào)用中斷服務(wù)程序(ISR,Interrupt Service Routine)
3、在ISR中通過讀中斷控制器、外設(shè)的相關(guān)寄存器來識別這是哪個中斷,并進(jìn)行相應(yīng)的處理
4、清楚中斷:通過讀寫中斷控制器和外設(shè)的相關(guān)寄存器來實(shí)現(xiàn)
5、最好恢復(fù)中斷程序的運(yùn)行環(huán)境(即上面保存的各個寄存器等),繼續(xù)執(zhí)行

本文引用地址:http://butianyuan.cn/article/201611/318240.htm

按鍵中斷程序設(shè)計流程:
1、按鍵以及按鍵中斷初始化
1)對按鍵中斷端口初始化,設(shè)置為特殊功能模式(10)
2)設(shè)置外部中斷觸發(fā)方式(EXTINTn低電平觸發(fā)000、高電平觸發(fā)001、上升沿觸發(fā)11x、下降沿觸發(fā)01x)
3)清外部中斷掛起寄存器(EINTPEND)、源掛起寄存器(SRCPND)、中斷掛起寄存器(INTPND),對其寫1清零,防止原有中斷產(chǎn)生的干擾
4)中斷入口函數(shù),也就是把中斷服務(wù)子程序賦給對應(yīng)的中斷入口地址(pISR_EINT8_23)
5)關(guān)閉外部中斷屏蔽寄存器(EINTMASK)和中斷屏蔽寄存器(INTMSK),也就是使能中斷,0使能,1屏蔽
2、按鍵中斷服務(wù)子程序
1)清源掛起寄存器(SRCPND)和中斷掛起寄存器(INTPND)
2)通過判斷EINTPEND相應(yīng)的位來確定是那個按鍵產(chǎn)生了中斷,然后執(zhí)行相應(yīng)的程序,并且對EINTPEND寫1清除相應(yīng)位,防止反復(fù)發(fā)生中斷

源程序:

//Main.c

/*
實(shí)驗(yàn)環(huán)境:mini2440開發(fā)板
完成日期:2011.4.13
作者:阿龍
實(shí)現(xiàn)功能:用中斷方式,當(dāng)按下K1時全亮,按下K2時計數(shù),按下K3時流水燈,按下K4時全滅

遇到的問題:就是我采用低電平觸發(fā)的時候,每次按鍵一次都會進(jìn)入兩次中斷,這個有點(diǎn)沒明白,也就是說當(dāng)執(zhí)行流水燈的時候,會循環(huán)6次。但是當(dāng)執(zhí)行流水燈的時候我按下計數(shù)的按鍵之后,一切都正常,很怪異。

我采用低電平觸發(fā)的時候,計數(shù)正常,流水燈有問題。這個問題等待以后解決。
*/
#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"

/*
函數(shù)聲明
*/
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);
/*
主函數(shù)
*/
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));//設(shè)置外部中斷觸發(fā)方式為下降沿觸發(fā)
rEXTINT1 &=~((0xf<<0)|(0xf<<12)|(0xf<<20)|(0xf<<24));//設(shè)置外部中斷觸發(fā)方式為低電平有效
rEINTPEND |=(1<<8)|(1<<11)|(1<<13)|(1<<14);//清外部中斷掛起寄存器
ClearPending(BIT_EINT8_23);//清源中斷掛起寄存器和中斷掛起寄存器,防止干擾

pISR_EINT8_23 =(U32)keyhandl;//中斷入口函數(shù)
rEINTMASK &= ~((1<<8)|(1<<11)|(1<<13)|(1<<14));//關(guān)閉外部中斷屏蔽(也就是使能中斷)
EnableIrq(BIT_EINT8_23);//中斷使能,其實(shí)就是關(guān)閉中斷屏蔽
}
/*
按鍵中斷服務(wù)子程序
*/
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;//清外部中斷掛起寄存器,防止反復(fù)發(fā)生中斷
//LED_qm();
LED_ql();
}
if(rEINTPEND &(1<<11))//當(dāng)我采用下降沿觸發(fā)的時候,這個程序執(zhí)行正常
{
rEINTPEND |= 1<<11;
//LED_qm();
LED_js();
}
if(rEINTPEND &(1<<13))//不管用什么觸發(fā),這個程序都要進(jìn)入兩次中斷,就算我采用下降沿,

            //我一直按著按鍵,程序就會一直執(zhí)行,理論上應(yīng)該沒有下降沿就會執(zhí)行程序一次
{
rEINTPEND |= 1<<13;
//LED_qm();
LED_lsd();
}
if(rEINTPEND &(1<<14))
{
rEINTPEND |= 1<<14;
LED_qm();
}
}
}
/*
延時函數(shù)
*/
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設(shè)置為保留不用
rGPBCON |= ((0x1<<10)|(0x1<<12)|(0x1<<14)|(0x1<<16));//設(shè)置GPB5,GPB6,GPB7,GPB8,為輸入模式(rGPBCON對應(yīng)位為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燈的運(yùn)行效果選擇
*/
/*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--)//流水燈循環(huán)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以二進(jìn)制方式計數(shù)(0-15)
*/
void LED_js(void)
{
int i;
rGPBDAT=~0x02f;//最后四位設(shè)為1的目的主要是把蜂鳴器屏蔽掉,前面設(shè)為保留也不管用,只能這里設(shè)置
for(i=0;i<15;i++)
{
delay(60000);
//rGPBDAT=~rGPBDAT; //如果采用這個去取反,當(dāng)我單步調(diào)試的時候,蜂鳴器會發(fā)出響聲,所以我直接在下面語句中直接取反
rGPBDAT=~(~rGPBDAT+0x020);//沒運(yùn)行一次,第5位加1進(jìn)位
}
}



評論


技術(shù)專區(qū)

關(guān)閉