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 = https://www.it610.com/article/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);
}

    推荐阅读