工程当中需要添加 S3C2440A.s ;2440lib.c;main.c;keyscan.c这段四个程序。
主程序:
/*********************************************************************************************
* File name: main.c
* Author: ZXL
* Description: 按下按键,相应的LED灯点亮且蜂鸣器响,由于触发了外部中断,通过串口向电脑发送是哪一个外部中断源触发了中断。
* History: 2013.5.6
*********************************************************************************************/
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
void dely(U32 tt)
{
U32 i;
for(;tt>0;tt--)
for(i=0;i<10000;i++);
}
void init()
{
U32 i;
U8 key;
U32 mpll_val=0;
i = 2 ;
switch ( i ) //设置2440的时钟频率
{
case 0: //200
key = 12;
mpll_val = (92<<12)|(4<<4)|(1);
break;
case 1: //300
key = 13;
mpll_val = (67<<12)|(1<<4)|(1);
break;
case 2: //400
key = 14;
mpll_val = (92<<12)|(1<<4)|(1);
break;
case 3: //440!!!
key = 14;
mpll_val = (102<<12)|(1<<4)|(1);
break;
default:
key = 14;
mpll_val = (92<<12)|(1<<4)|(1);
break;
}
//MDIV=92,PDIV=1,SDIV=1 通过配置MPLLCON,MPLL确定,即FCLK=400MHZ确定
ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3);
ChangeClockDivider(key, 12); //FCLK:HCLK:PCLK = 1:1/4:1/8 =400M:100M:50M
Port_Init();
Uart_Init(0,115200);
Uart_Select(0);
Uart_Printf("\nInterrupt Test Begin!\n");
}
int main(int argc, char **argv)
{
init();
beep_init();
led_port_init();
KeyScan_Test();
}
按键中断程序:
/*********************************************************************************************
* File name: keyscan.c
* Author: ZXL
* Description: 按下按键,相应的LED灯点亮且蜂鸣器响,由于触发了外部中断,通过串口向电脑发送是哪一个外部中断源触发了中断。
* History: 2013.5.6
*********************************************************************************************/
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
/******************************************************************************
MINI2440六个按键的输入引脚:
EINT8 -----( GPG0 )----INPUT K1
EINT11-----( GPG3 ) ----INPUT K2
EINT13-----( GPG5 )----INPUT K3
EINT14-----( GPG6 )---- INPUT K4
EINT15-----( GPG7 )----INPUT K5
EINT19-----( GPG11 )----INPUT K6
二级中断源:EINT8、EINT11、EINT13、EINT14、EINT15、EINT19
对应的一级中断源为:EINT8_23
二级中断源对应的寄存器:
EXTINT1、EXTINT2、EINTPEND、EINTMASK、
一级中断源对应的寄存器:
SRCPND、INTPND、INTMSK
******************************************************************************/
#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 led_port_init()
{
rGPBCON &= ~((3<<10)|(3<<12)|(3<<14)|(3<<16)); //控制寄存器清零
rGPBCON |= (1<<10)|(1<<12)|(1<<14)|(1<<16); //控制寄存器设置为输出
rGPBDAT |= (LED1_OFF)|(LED2_OFF)|(LED3_OFF)|(LED4_OFF); //LED灯全灭
}
void beep_init()
{
rGPBCON &= ~(3<<0);
rGPBCON |= (1<<0);
}
void beep_run()
{
rGPBDAT |= 0x1ff;
dely(50);
rGPBDAT &= 0x1fe;
dely(50);
}
//扫描6按键所接GPIO口,观察GPIOx电平值,键按下:低电平; 键抬起:高电平
//同时返回当前按下键所对应的键值
U8 Key_Scan()
{
// Delay( 80 ) ;
if( (rGPGDAT&(1<< 0)) == 0 ) // K1按下
{
beep_run();
rGPBDAT = rGPBDAT & (LED1_ON) | ((LED2_OFF)|(LED3_OFF)|(LED4_OFF));
return 1 ;
}
else if( (rGPGDAT&(1<< 3)) == 0 ) // K2按下
{
beep_run();
rGPBDAT = rGPBDAT & (LED2_ON) | ((LED1_OFF)|(LED3_OFF)|(LED4_OFF));
return 2 ;
}
else if( (rGPGDAT&(1<< 5)) == 0 ) // K3按下
{
beep_run();
rGPBDAT = rGPBDAT & (LED3_ON) | ((LED1_OFF)|(LED2_OFF)|(LED4_OFF));
return 3 ;
}
else if( (rGPGDAT&(1<< 6)) == 0 ) // K4按下
{
beep_run();
rGPBDAT = rGPBDAT & (LED4_ON) | ((LED2_OFF)|(LED3_OFF)|(LED1_OFF));
return 4 ;
}
/*
else if( (rGPGDAT&(1<< 7)) == 0 ) // K5按下
return 5 ;
else if( (rGPGDAT&(1<< 11)) == 0 ) // K6按下
return 6 ;
*/
else
return 0xff;
}
void __irq Key_ISR() // 按键中断处理程序
{
U8 key;
if(rINTPND==BIT_EINT8_23)
{ //如果EINT8_23触发中断,则INTPEND寄存器中对应EINT8_23位被置1,然后再判断是EINT8_23这16个中断源是哪个触发中断,
ClearPending(BIT_EINT8_23); //清空BIT_EINT8_23位中断
if(rEINTPEND&(1<<8)) // 继续比较EINTPEND寄存器,确定是外面哪个子中断源
{ //EINT8触发中断
Uart_Printf("External Interrupt Eint8 Occur\n");
rEINTPEND |= 1<< 8; // 清空EINTPEND寄存器中EINT8对应的位,原理是写入1来清除
}
if(rEINTPEND&(1<<11))
{ //EINT11触发中断
Uart_Printf("External Interrupt Eint11 Occur\n");
rEINTPEND |= 1<< 11;
}
if(rEINTPEND&(1<<13))
{ //EINT13触发中断
Uart_Printf("External Interrupt Eint13 Occur\n");
rEINTPEND |= 1<< 13;
}
if(rEINTPEND&(1<<14))
{ //EINT14触发中断
Uart_Printf("External Interrupt Eint14 Occur\n");
rEINTPEND |= 1<< 14;
}
if(rEINTPEND&(1<<15))
{ //EINT15触发中断
Uart_Printf("External Interrupt Eint15 Occur\n");
rEINTPEND |= 1<< 15;
}
if(rEINTPEND&(1<<19))
{ //EINT19触发中断
Uart_Printf("External Interrupt Eint19 Occur\n");
rEINTPEND |= 1<< 19;
}
}
key=Key_Scan(); //扫描GPGx端口,返回按键键值
if( key != 0xff )
Uart_Printf( "Interrupt occur... K%d is pressed!\n", key) ;
}
void KeyScan_Test()
{
Uart_Printf("\nKey Scan Test begin, press ESC key to exit !\n");
// 配置GPGCON,设置6按键对应的GPGx管脚功能为外部中断引脚EINT
rGPGCON = rGPGCON & (~((3<<0)|(3<<6))) | ((2<<0)|(2<<6)) ; //GPG0,3 先清零后配置为输出
rGPGCON = rGPGCON & (~((3<<10)|(3<<12))) | ((2<<10)|(2<<12)) ; //GPG5,6 先清零后配置为输出
rGPGCON = rGPGCON & (~((3<<14)|(3<<22))) | ((2<<14)|(2<<22)) ; //GPG7,11 先清零后配置为输出
rEXTINT1 &= ~(7<<0); // 设置中断触发方式,先清零,后设置为下降沿触发
rEXTINT1 |= (2<<0); //set eint8 falling edge int
rEXTINT1 &= ~(7<<12);
rEXTINT1 |= (2<<12); //set eint11 falling edge int
rEXTINT1 &= ~(7<<20);
rEXTINT1 |= (2<<20); //set eint13 falling edge int
rEXTINT1 &= ~(7<<24);
rEXTINT1 |= (2<<24); //set eint14 falling edge int
rEXTINT1 &= ~(7<<28);
rEXTINT1 |= (2<<28); //set eint15 falling edge int
rEXTINT2 &= ~(7<<12);
rEXTINT2 |= (2<<12); //set eint19 falling edge int
rINTMOD = 0x0; // 设置为IRQ模式
rEINTPEND = 0xFFFFFF; //写入1清空外部子中断所有请求
rSRCPND = BIT_EINT8_23; //写入1来清除主中断的EINT8_23位的上一次中断
rINTPND = BIT_EINT8_23; //写入1来清除中断控制寄存器的EINT8_23位的上一次中断
rEINTMASK=~( (1<<8)|(1<<11)|(1<<13)|(1<<14)|(1<<15)|(1<<19) );//打开子中断的六个外部中断对应的中断屏蔽位
rINTMSK=~(BIT_EINT8_23); //打开主中断的BIT_EINT8_23对应的中断屏蔽位
pISR_EINT8_23 = (U32)Key_ISR; // 将按键中断处理程序注册,入口地址对应EINT8_23中断IRQ
Uart_Printf("\nPlease press the Key to test !\n");
Uart_Printf("\n中断类型INTMSK=0x%x\n",rINTMSK); //显示CPU将要服务的中断的内型 1:屏蔽 0:可服务
while( Uart_GetKey() != ESC_KEY ) ; // 无限循环,直到用户键入ESC键,退出。但此时可被中断打断
Uart_Printf("\nExit Interrupt test !\n");
rEINTMASK=0xFFFFFF; // 重新设置EINTMASK屏蔽位
rINTMSK=BIT_ALLMSK; // 重新设置INTMSK屏蔽位
}