单片机
返回首页

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

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • PIC单片机控制的遥控防盗报警器电路

  • 红外线探测报警器

  • 短波AM发射器电路设计图

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 开关电源的基本组成及工作原理

  • 用NE555制作定时器

    相关电子头条文章