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