2440裸机程序——按键中断

工程当中需要添加 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屏蔽位
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
看门狗(Watchdog)是一种硬件定时器,用于监视系统是否正常运行。如果系统正常运行,那么看门狗会在设定的时间间隔内被定期喂狗;如果系统出现异常,看门狗就会在时间间隔到达后触发中断或复位操作,以恢复系统的正常运行。 在Mini2440上,看门狗的控制寄存器位于WTDAT、WTCON和WTCNT中。其中,WTDAT用于设置看门狗的计数器初始值,WTCON用于配置看门狗的工作模式和计数器时钟源,WTCNT则是看门狗的计数器。 下面是一个简单的示例代码,用于启动看门狗并设置其定时时间为5秒钟: ```c #include "s3c2440_soc.h" void delay(int count) { while(count--); } int main() { /* 设置看门狗定时时间为5秒钟 */ WTCON = (0x1 << 5) | (0x3 << 3) | (0x1 << 0); /* 启动看门狗 */ WTCNT = 0x10000; while(1) { /* 喂狗 */ WTCNT = 0x10000; delay(100000); /* 业务处理 */ // ... } return 0; } ``` 在上述代码中,我们首先设置了看门狗的定时时间为5秒钟。然后在主循环中,我们每隔一段时间就喂狗一次,以保证看门狗不会触发中断或复位操作。同时,我们还可以在喂狗的时间间隔内进行业务处理。 需要注意的是,在实际应用中,我们通常不会像上述代码一样简单地启动一个看门狗并喂狗。实际上,我们需要在系统正常运行时定期喂狗,以确保看门狗不会触发中断或复位操作;同时,我们还需要在系统出现异常时及时处理异常并复位系统,以防止系统陷入死循环或其他错误状态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值