Mini2440 裸机实验之LED程序、按键、中断

来源:互联网 发布:网络语小饼干什么意思 编辑:程序博客网 时间:2024/04/27 20:54

测试平台:Mini2440 Win7 64 ADS开发环境测试

此程序主要考虑按键、LED点亮、中断模式(IRQ)之间的联系

以下为main.c代码部分,其他请参考三星提供的2440用例代码

#defineGLOBAL_CLK1#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"//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-15while(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){//每一个引脚设为输出端口,初始化为01rGPBCON &= ~( (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<<i+5);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;elserGPBDAT |= LED4_OFF;if(data&0x04)rGPBDAT &= LED3_ON;elserGPBDAT |= LED3_OFF;if(data&0x02)rGPBDAT &= LED2_ON;elserGPBDAT |= LED2_OFF;if(data&0x01)rGPBDAT &= LED1_ON;elserGPBDAT |= 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测试用例