您的位置:首页 > 其它

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

2013-05-28 16:18 393 查看
测试平台:Mini2440 Win7 64 ADS开发环境测试

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

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

#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"

//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<<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;
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测试用例
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: