色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

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

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

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

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

          本文引用地址:http://cafeforensic.com/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

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

          遇到的問題:就是我采用低電平觸發(fā)的時候,每次按鍵一次都會進入兩次中斷,這個有點沒明白,也就是說當(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);//中斷使能,其實就是關(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ā),這個程序都要進入兩次中斷,就算我采用下降沿,

                      //我一直按著按鍵,程序就會一直執(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燈的運行效果選擇
          */
          /*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以二進制方式計數(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);//沒運行一次,第5位加1進位
          }
          }



          評論


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

          關(guān)閉