Mini2440 裸机实验之LED程序、按键、中断
2022-10-20 来源:csdn
测试平台:Mini2440 Win7 64 ADS开发环境测试
此程序主要考虑按键、LED点亮、中断模式(IRQ)之间的联系
以下为main.c代码部分,其他请参考三星提供的2440用例代码
#define GLOBAL_CLK 1
#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' //led灯测试程序 void led_init(void); void led_close(void); void led_run(void); void disp_num(int data); void led_disp_num(int data); //按键中断程序 void key_init(void); static void __irq key_handler(void); void beep_init(void); void beep_run(void); #define LED1_ON ~(1<<5) #define LED2_ON ~(1<<6) #define LED3_ON ~(1<<7) #define LED4_ON ~(1<<8) #define LED1_OFF (1<<5) #define LED2_OFF (1<<6) #define LED3_OFF (1<<7) #define LED4_OFF (1<<8) /******延时函数******/ void delay(int n_times) { int i; for( ;n_times>0;n_times--) for(i=0;i<400;i++) ; } /*****运行主函数*****/ void Main(void) { int i=0; led_init(); //实现led灯递增亮起 //led_run(); /* //实现led灯以二进制方式显示0-15 while(i<16) { //disp_num(i++); led_disp_num(i++); delay(5000); if(i==16) { i = 0; } } */ //按键测试中断 beep_init(); MMU_Init(); key_init(); while(1) { ; //beep_run(); } } /*******对LED引脚进行初始化*******/ void led_init(void) { //每一个引脚设为输出端口,初始化为01 rGPBCON &= ~( (1<<2*5+1)|(1<<2*6+1)|(1<<2*7+1)|(1<<2*8+1) ); //rGPBCON..... } /*******关闭所有的led灯*******/ void led_close(void) { rGPBDAT |= (LED1_OFF)|(LED2_OFF)|(LED3_OFF)|(LED4_OFF); //rGPBDAT &= 0xFFFFFF0F; } /********mini2440开发板有4个引脚连接了LED发光二极管,该函数实现了流水灯*******/ void led_run(void) { int i=0; //int arr_led_on[4]={LED1_ON,LED2_ON,LED2_ON,LED2_ON}; //led_close(); led_close(); rGPBDAT &= ~(1<<5); delay(10000); /* while(1) { //第一种递增跑马灯 1000-》0100-》0010-》0001-》1000... led_close(); rGPBDAT &= ~(1< delay(50000); if( ++i == 4 ) { i = 0; } //第二种递增亮起 1000-》1100-》1110-》1111-》0000... rGPBDAT &= ~(i<<5); delay(5000); if( ++i == 16) { led_close(); i = 0; } */ //} } /********显示0000~1111数字********/ void disp_num(int data) { if(data&0x08) rGPBDAT &= LED4_ON; else rGPBDAT |= LED4_OFF; if(data&0x04) rGPBDAT &= LED3_ON; else rGPBDAT |= LED3_OFF; if(data&0x02) rGPBDAT &= LED2_ON; else rGPBDAT |= LED2_OFF; if(data&0x01) rGPBDAT &= LED1_ON; else rGPBDAT |= LED1_OFF; } /********显示0000~1111数字********/ void led_disp_num(int data) { int i = 3; for(; i>=0; i++) { //if( data & ((int)pow(2,i)) ) //肯定非0都为真 if( data & 0x0f) { delay(1000); rGPBDAT &= ~(1<<8-i); } else { rGPBDAT &= (1<<8-i); } } } /*******按键key1的初始化函数********/ void key_init(void) { //rGPGCON &= ~(0<<2*0+1); rGPGCON &= (~(0x3<<0))&(~(0x3<<2*3)); rGPGCON |= (0x2<<0)|(0x2<<2*3); //10特殊功能 //rEXTINT1 &= ~(0xf<<0);//0000 EINIT8 开启低电平 过滤关闭 rEINTPEND |= (1<<8)|(1<<11); //清除之前的中断 rEINTMASK &= (~(1<<8))&(~(1<<11));//中断不被屏蔽 pISR_EINT8_23 = (U32) key_handler; EnableIrq(BIT_EINT8_23); } /*******key1的中断服务程序*******/ static void __irq key_handler(void) { if( rINTPND == BIT_EINT8_23) { ClearPending(BIT_EINT8_23); if( rEINTPEND&(1<<8) ) { led_close(); rEINTPEND |= 1<<8; beep_run(); } if( rEINTPEND&(1<<11) ) { rEINTPEND |= 1<<11; led_run(); } //ClearPending(BIT_EINT8_23); } } /***********初始化蜂鸣器***********/ void beep_init(void) { rGPBCON &= ~(0x3<<0); rGPBCON |= 0x1<<0;//初始化为输出端 } /*********运行蜂鸣器*********/ void beep_run(void) { rGPBDAT |= 0x1<<0; delay(1000); rGPBDAT &= ~(0x1<<0); delay(1000); } LED点亮步骤(以MIni2440为参考,其他请看手册说明) 1.初始化LED配置的引脚,如mini2440 led1-》GPB5 每一个器件都有一个或者多个管脚进行驱动控制,就是设置GPBCON引脚5(两位为一个控制单位,应该是【11:10】) 2.直接点亮,还是管脚,这里有谁驱动它发光亮起来呢??就是GPBDAT,led1引脚5,此时为1位控制,即是【5】=0(低电平有效的情况下),就能驱动发亮 对于按键来说其实是一样的,只不过连接的针脚不一样,这时候参考手册就可以知道key-》GPG,然后这些针脚对应了相应的中断,当我们不使用中断控制的情况下,这时候需要读取GPGDAT的值,然后与相应的key对应的键位值进行&即可判断哪个按键被按下了,方法同上因为都是GPIO 中断控制(IRQ,非快速中断模式FIQ) 对于如何设置堆栈sp,pc....如何调转到快速中断,怎么恢复CPSR等等,暂且不谈,先看中断顺序 1. 首先要初始化中断,清除当前要中断的位,设置当前中断的位,使能当前中断, 如: 按键key1-》EINT8-》GPG0,仍然是GPIO,还是前面的方法,因为这个中断属于二级仲裁器1中的REQ1/EINT8_23, 所以还要设置EINTPEND用以判断到底是哪一个中断,先清除如key1: rEINTPEND |= (1<<8)。还得保证不被屏蔽mask位就要设为0,才是应为EINTMASK对应的位,查手册即可; 这里使用默认低电平触发方式,如果要设置电平方式,设置EXTINT1即可,额外设置的寄存器EXTINT0不能使用,请参看手册; 设置中断先后顺序,这里两个中断同级,并没有设置,如需请设置PRIORITY 2. 设置中断处理函数,先将中断处理函数映射到相应的中断地址去,本例就是key_handler 3. 接下来就可以使能相应中断了,如key1 INMASK &= (~(1<<5) )即可,本例调用三星的库函数EnableIrq(BIT_EINT8_23);使能中断 4. 处理中断,在主函数里面是一个无止境的循环,当有中断发生,即转到中断处理函数 注: 1)处理函数之前就是使用了一个循环导致不能退出,也不能相应下一个中断 2)蜂鸣中断处理函数,屏蔽蜂鸣不能使用rGPBDAT &=(0x0<<0);此时LED会全部亮起来,因为此时我只想测试蜂鸣,最好采用rGPBDAT &= ~(0x1<<0); 尤其LED部分,我调试了走马灯,各灯分别亮起,0-15循环亮起的LED实例,注销部分注释即可测试,以及未修改成功的显示0-15测试用例