ARM裸机程序设计—按键中断程序设计

    技术2022-05-17  34

    按键程序设计总结:

     中断处理框图:

    首先是按键中断处理过程: 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次。但是当执行流水灯的时候我按下计数的按键之后,一切都正常,很怪异。

    我采用低电平触发的时候,计数正常,流水灯有问题。这个问题等待以后解决。*********************************************************************************/#define GLOBAL_CLK  1#include <stdlib.h>#include <string.h>#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进位   }}


    最新回复(0)