ARM学习之定时器Timer0实验

/***************************************************
Project: Timer0实验
  Writer:  SHOW      
  Time:  2011/10/16 
  Hareware: 硬件平台:mini2440 , J-link.
  Function: 通过定时器0实现LED1以1s的时间间隔闪烁。
  Direction:这个实验主要设计的知识是定时器与定时器时钟源的设置,整个实验思路如下:
   1.设置定时器时钟源PCLK大小。
   2.设置定时器定时频率大小。
   3.定时时间到进入中断服务函数,让lED1闪烁。
           参考代码:国嵌ARM精讲第三天演示程序,JustDo的CLK实验。
           参考书籍:韦东山《嵌入式linux应用开发完全手册P166。s3c2440手册。      
              
***************************************************/
#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"
#include "def.h"
#include "mmu.h"
#include "Option.h"


#define LED1_OFF (1<<5)
#define LED2_OFF (1<<6)
#define LED3_OFF (1<<7)
#define LED4_OFF (1<<8)


#define MPLL_200MHZ ((0x5c<<12) | (0x01<<4) | (0x02))


void Init_LED(void);    
void __irq EintHandler(void);
void Set_TimerSourceClock_PCLK(void);
void Init_Timer0(void);
void __irq IRQ_Timer0_Handle(void);
void LED_Run(void);




//========================================================================
// 函数名称: 延时1ms子函数
// 功能描述: 延时      
// 参数:     times为延时的ms数。 
// 返回值:   void
//========================================================================
void Delay1ms(int times)
{
int i;
for( ;  times > 0; times-- )
for(i=400; i>0 ; i--);
}


//========================================================================
// 函数名称: 主函数
// 功能描述: 函数入口      
// 参数:     void 
// 返回值:   void
//========================================================================
void Main(void)  
{
MMU_Init();
Init_LED();                              //初始化LED。
    Set_TimerSourceClock_PCLK();
    Init_Timer0();                         

    while(1); 

}


//========================================================================
// 函数名称: 定时器时钟源频率PCLK设置子函数
// 功能描述  完成对时钟源的设置。并且确定MPLL与PCLK大小。        
// 参数:     void 
// 返回值:   void
// PS->时钟源设置步骤: 1.定时器的时钟源由MPLL的PCLK提供。这里首先先设置MPLL为200M,通过CLKDIVN寄存器设置
//    FCLK,HCLK,PCLK的的分频比,得到需要的PCLK = 50M。
//    2.MPLL的设置方法:MPLL与FCLK的设置计算公式一样,设置对应的寄存器为MPLLCON。
//   MPLLCON的[19:12]为MDIV,[9:4]为PDIV,[1:0]为SDIV。其中m=MDIV+8,p=PDIV+2,s=SDIV。
//            计算公式为MPLL(FCLK) = (2 * m * Fin)/(p * 2^s)。PS: Fin为板子外接晶振频率,MIni2440的Fin = 12M。
// 总结:               设置定时器时钟源是频率,步骤(1)首先设置MPLLCON确定FCLK。(2)再设置CLKDIVN确定分频比确定PCLK。一共需要设置MPLLCON和CLKDIVN两个寄存器。
//========================================================================
void Set_TimerSourceClock_PCLK(void)
{
rMPLLCON = 0;
rMPLLCON  |= MPLL_200MHZ;   //   MPLL = FCLK
rCLKDIVN = 0x03;           //  FCLK:HCLK:PCLK = 1:2:4 => PCLK = 50MHz. 
// rMPLLCON = 0;
// rMPLLCON |= (0x3f<<12 | 2<<4 | 2<<0);//设置FCLK的值
// rCLKDIVN |= (1<<2 | 1<<0);//设置FCLK:HCLK:PCLK的比值

}




//========================================================================
// 函数名称: 定时器初始化子函数
// 功能描述: 完成对定时器0的设置与开定时器中断。     
// 参数:     void 
// 返回值:   void
// PS->定时器的设置步骤: 根据格式 定时器输出频率= PCLK/{prescaler value+1}/{divider value}
// prescaler value = 0~255,divider value = 2,4,8,16。
// 1.设置定时器配置寄存器0(TCFG0)确定prescaler value。
// 2.设置定时器配置寄存器1(TGFG1)确定divider value。
// 3.设置定时器0计数缓存寄存器(TCNTB0)与比较缓存寄存器(TCMPB0)确定计数初值。
// 4.设置寄存器TCON,确定定时器工作方式,并且启动定时器。
//========================================================================
void Init_Timer0(void)
{
rTCFG0 = 49;             //prescaler = 49
rTCFG1 |= 0x03;          //divider = 16
rTCNTB0 = 62500;         //TCNTB0[15:0]=计数值   50000000/49+1/16=62500


rTCON |=(1<<1);   //更新TCNTB0 和 TCMTB0的值
rTCON =0; //将TCON的值清0,注这一步很重要,如没有,定时器将一直更新TCNTB0和TCMTB0的值导致无法启动
rTCON |= (1<<3 | 1<<0); //启动定时器0,并设置为自动装载
  
ClearPending(BIT_TIMER0); 
pISR_TIMER0 = (U32)IRQ_Timer0_Handle; // 中断入口 
EnableIrq(BIT_TIMER0);    //开中断
}


//========================================================================
// 函数名称: LED初始化子函数
// 功能描述: 初始化IO口 设置GPIO为输出口。     
// 参数:     void 
// 返回值:   void
//========================================================================
void Init_LED(void)
{
// rGPBCON = 0;  复位即为0可不用先给0。
rGPBCON |= (1<<10) | (1<<12) | (1<<14) | (1<<16); // 设置GPB5~GPB8 为输出口。
rGPBDAT |= (LED1_OFF | LED2_OFF | LED3_OFF | LED4_OFF);// 初始化熄灭。
}


//========================================================================
// 函数名称: Timer0中断服务函数
// 功能描述: 进入中断后LED亮1s,灭1秒。    
// 参数:     void 
// 返回值:   void
//========================================================================
void __irq IRQ_Timer0_Handle(void)
{
    ClearPending(BIT_TIMER0);
    LED_Run();


}


//========================================================================
// 函数名称: LED闪烁函数
// 功能描述: 前后两次分别执行与或操作,使LED产生亮灭。    
// 参数:     void 
// 返回值:   void
//========================================================================
void LED_Run(void)
{
if(rGPBDAT &(1<<5))  
       rGPBDAT &=~(1<<5);
    else
       rGPBDAT |=(1<<5); 
}

你可能感兴趣的:(ARM9裸机编程)