ARM學(xué)習(xí)之定時器Timer0實驗
Project: Timer0實驗
Writer: SHOW
Time: 2011/10/16
Hareware: 硬件平臺:mini2440 , J-link.
Function: 通過定時器0實現(xiàn)LED1以1s的時間間隔閃爍。
Direction:這個實驗主要設(shè)計的知識是定時器與定時器時鐘源的設(shè)置,整個實驗思路如下:
1.設(shè)置定時器時鐘源PCLK大小。
2.設(shè)置定時器定時頻率大小。
3.定時時間到進入中斷服務(wù)函數(shù),讓lED1閃爍。
參考代碼:國嵌ARM精講第三天演示程序,JustDo的CLK實驗。
參考書籍:韋東山《嵌入式linux應(yīng)用開發(fā)完全手冊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);
//========================================================================
// 函數(shù)名稱: 延時1ms子函數(shù)
// 功能描述: 延時
// 參數(shù): times為延時的ms數(shù)。
// 返回值: void
//========================================================================
void Delay1ms(int times)
{
int i;
for( ; times > 0; times-- )
for(i=400; i>0 ; i--);
}
//========================================================================
// 函數(shù)名稱: 主函數(shù)
// 功能描述: 函數(shù)入口
// 參數(shù): void
// 返回值: void
//========================================================================
void Main(void)
{
MMU_Init();
Init_LED(); //初始化LED。
Set_TimerSourceClock_PCLK();
Init_Timer0();
while(1);
}
//========================================================================
// 函數(shù)名稱: 定時器時鐘源頻率PCLK設(shè)置子函數(shù)
// 功能描述完成對時鐘源的設(shè)置。并且確定MPLL與PCLK大小。
// 參數(shù): void
// 返回值: void
// PS->時鐘源設(shè)置步驟: 1.定時器的時鐘源由MPLL的PCLK提供。這里首先先設(shè)置MPLL為200M,通過CLKDIVN寄存器設(shè)置
// FCLK,HCLK,PCLK的的分頻比,得到需要的PCLK = 50M。
// 2.MPLL的設(shè)置方法:MPLL與FCLK的設(shè)置計算公式一樣,設(shè)置對應(yīng)的寄存器為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。
// 總結(jié): 設(shè)置定時器時鐘源是頻率,步驟(1)首先設(shè)置MPLLCON確定FCLK。(2)再設(shè)置CLKDIVN確定分頻比確定PCLK。一共需要設(shè)置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);//設(shè)置FCLK的值
//rCLKDIVN |= (1<<2 | 1<<0);//設(shè)置FCLK:HCLK:PCLK的比值
}
//========================================================================
// 函數(shù)名稱: 定時器初始化子函數(shù)
// 功能描述: 完成對定時器0的設(shè)置與開定時器中斷。
// 參數(shù): void
// 返回值: void
// PS->定時器的設(shè)置步驟: 根據(jù)格式 定時器輸出頻率= PCLK/{prescaler value+1}/{divider value}
//prescaler value = 0~255,divider value = 2,4,8,16。
//1.設(shè)置定時器配置寄存器0(TCFG0)確定prescaler value。
//2.設(shè)置定時器配置寄存器1(TGFG1)確定divider value。
//3.設(shè)置定時器0計數(shù)緩存寄存器(TCNTB0)與比較緩存寄存器(TCMPB0)確定計數(shù)初值。
//4.設(shè)置寄存器TCON,確定定時器工作方式,并且啟動定時器。
//========================================================================
void Init_Timer0(void)
{
rTCFG0 = 49; //prescaler = 49
rTCFG1 |= 0x03; //divider = 16
rTCNTB0 = 62500; //TCNTB0[15:0]=計數(shù)值 50000000/49+1/16=62500
rTCON |=(1<<1); //更新TCNTB0 和 TCMTB0的值
rTCON =0;//將TCON的值清0,注這一步很重要,如沒有,定時器將一直更新TCNTB0和TCMTB0的值導(dǎo)致無法啟動
rTCON |= (1<<3 | 1<<0);//啟動定時器0,并設(shè)置為自動裝載
ClearPending(BIT_TIMER0);
pISR_TIMER0 = (U32)IRQ_Timer0_Handle; // 中斷入口
EnableIrq(BIT_TIMER0); //開中斷
}
//========================================================================
// 函數(shù)名稱: LED初始化子函數(shù)
// 功能描述: 初始化IO口 設(shè)置GPIO為輸出口。
// 參數(shù): void
// 返回值: void
//========================================================================
void Init_LED(void)
{
//rGPBCON = 0; 復(fù)位即為0可不用先給0。
rGPBCON |= (1<<10) | (1<<12) | (1<<14) | (1<<16); // 設(shè)置GPB5~GPB8 為輸出口。
rGPBDAT |= (LED1_OFF | LED2_OFF | LED3_OFF | LED4_OFF);// 初始化熄滅。
}
//========================================================================
// 函數(shù)名稱: Timer0中斷服務(wù)函數(shù)
// 功能描述: 進入中斷后LED亮1s,滅1秒。
// 參數(shù): void
// 返回值: void
//========================================================================
void __irq IRQ_Timer0_Handle(void)
{
ClearPending(BIT_TIMER0);
LED_Run();
}
//========================================================================
// 函數(shù)名稱: LED閃爍函數(shù)
// 功能描述: 前后兩次分別執(zhí)行與或操作,使LED產(chǎn)生亮滅。
// 參數(shù): void
// 返回值: void
//========================================================================
void LED_Run(void)
{
if(rGPBDAT &(1<<5))
rGPBDAT &=~(1<<5);
else
rGPBDAT |=(1<<5);
}
評論