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

测试平台: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测试用例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值