新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > ARM裸機程序設計—按鍵中斷程序設計

        ARM裸機程序設計—按鍵中斷程序設計

        作者: 時間:2016-11-19 來源:網絡 收藏
        首先是按鍵中斷處理過程:

        1、中斷控制器匯集各類外設發出的中斷信號,然后告訴CPU
        2、CPU保存當前程序的運行環境(各個寄存器等),調用中斷服務程序(ISR,Interrupt Service Routine)
        3、在ISR中通過讀中斷控制器、外設的相關寄存器來識別這是哪個中斷,并進行相應的處理
        4、清楚中斷:通過讀寫中斷控制器和外設的相關寄存器來實現
        5、最好恢復中斷程序的運行環境(即上面保存的各個寄存器等),繼續執行

        本文引用地址:http://www.104case.com/article/201611/318240.htm

        按鍵中斷程序設計流程:
        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進位
        }
        }



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 获嘉县| 开化县| 佳木斯市| 诸暨市| 台州市| 岳池县| 荆门市| 东丰县| 左贡县| 那曲县| 板桥市| 甘德县| 土默特左旗| 潢川县| 淮阳县| 清远市| 大英县| 榆林市| 镇安县| 内乡县| 绥中县| 杂多县| 武鸣县| 白城市| 安康市| 石门县| 佛学| 武宣县| 丹阳市| 宜良县| 新民市| 天峨县| 石楼县| 磐安县| 阿坝县| 堆龙德庆县| 仪征市| 和龙市| 分宜县| 金川县| 开远市|