定時器中斷---那些年我們一起玩mini2440(arm9)裸機(jī)
(時鐘體系)
時鐘概念:
★時鐘脈沖:一個按一定電壓幅度,一定時間間隔連續(xù)發(fā)出的脈沖信號;
★時鐘頻率:在單位時間(如:1秒)內(nèi)產(chǎn)生的時鐘秒沖數(shù);
時鐘的作用:
時鐘信號是時序邏輯的基礎(chǔ),它用于決定邏輯單元中的狀態(tài)何時更新。數(shù)字芯片中眾多的晶體管都工作在開關(guān)狀態(tài),它們的導(dǎo)通和關(guān)斷動作無不是按照時鐘信號的節(jié)奏進(jìn)行的。
時鐘的作用(簡潔版)
系統(tǒng)中的設(shè)備需要有個時間來和它進(jìn)行同步—即靠時鐘!
時鐘的產(chǎn)生-晶振
晶振:晶體振蕩器,是用石英晶體精密切割做成。
優(yōu)點(diǎn):振蕩頻率非常穩(wěn)定;振蕩頻率很準(zhǔn)確;結(jié)構(gòu)簡單、噪聲低。
缺點(diǎn):生產(chǎn)成本高,交貨周期較長,不利于客戶加快產(chǎn)品上市時間,而且難以獲得非常標(biāo)準(zhǔn)的頻率。
時鐘產(chǎn)生-PLL
PLL:(鎖相環(huán))合成器是一種更為復(fù)雜的系統(tǒng)時鐘源。通過PLL合成器需要一個外部晶體并包含一個能夠?qū)w的特定頻率加倍或分頻的集成鎖相環(huán)PLL電路。
S3C2440時鐘體系
S3C2440的主時鐘晶振來自外部晶振(XTIPLL),或者是外部時鐘(EXTCLK)。時鐘生成器包含了一個振蕩器(振蕩放大器),其連接外部晶振,可以產(chǎn)生需要的高頻,通過引腳OM[3:2]來決定時鐘源時Crystal還是EXTCLK.
S3C2440時鐘體系
S3C2440有兩個PLL:(1)MPLL和(2)UPLL,
UPLL專用于USB設(shè)備。
MPLL用于CPU及其他外圍器件。
通過MPLL會產(chǎn)生三個部分的時鐘頻率:FCLK、HCLK、PLCK.
FCLK:用于CPU核;
HCLK:用于AHB(常用于高速外設(shè))總線的設(shè)備,比如:SDRAM;
PCLK:用于APB(常用于低速外設(shè))總線的設(shè)備,比如:UART.
時鐘啟動流程:
1.上電幾毫秒后,外部晶振輸出穩(wěn)定,F(xiàn)CLK=外部晶振頻率(12MHZ),nRESET
信號恢復(fù)高電平后,CPU開始執(zhí)行命令。
2.在設(shè)置MPLL的幾個寄存器后,需要等待一段時間(Lock Time),MPLL的輸出才穩(wěn)定。在這段時間(Lock Time)內(nèi),F(xiàn)CLK停振,CPU停止工作。
Lock Time的長短由寄存器LOCKTIME設(shè)定。
3.Lock Time之后,MPLL輸出正常,CPU工作在新的FCLK(如:400MHZ)下。
寄存器:
設(shè)置S3C2440的時鐘頻率就是設(shè)置相關(guān)的幾個寄存器:
1.LOCKTIME寄存器
2.MPLLCON寄存器
3.CLKDIVN寄存器
寄存器-LOCKTIME
MPLL啟動后需要等待一段時間(Lock Time),使得其輸出穩(wěn)定。
位[31:16]用于UPLL,
位[15:0]用于MPLL.
使用缺省值0xffff ffff
寄存器-MPLLCON
該寄存器用于設(shè)置FCLK(cpu的時鐘頻率)與Fin的倍數(shù)(Fin:輸入的時鐘頻率)
位[19:12]的值稱為MDIV
位[9:4]的值稱為PDIV
位[1:0]的值稱為SDIV
FCLK與Fin的計(jì)算關(guān)系式如下:
MPLL(FCLK) = (2*m*Fin)/(p*2^s)
其中:m= MDIV+8 ,p=PDIV+2 , s= SDIV
寄存器-CLKDIVN
該寄存器用于設(shè)置FCLK、HCLK、PCLK三者的比例
★HDIVN:位[2:1],用來設(shè)置HCLK與FCLK比例關(guān)系
★PDIVN:位[0],用來設(shè)置PCLK與HCLK比例關(guān)系
例如:
FCLK:HCLK:PCLK=4:2:1
FCLK=400MHZ(主頻)
HCLK=200M
PCLK=100M
巧計(jì),速記2圖:
圖1:
圖2:
S3C2440定時器
S3C2440共有5個16位的定時器。其中定時器0、1、2、3有PWM功能,他們都有一個輸出引腳,可以通過定時器來控制引腳周期性的高、低電平變化;
定時器4沒有輸出引腳。
S3C2440定時器
定時器部件的時鐘源為--PCLK,(經(jīng)過兩次分頻)
首先通過兩個8位的預(yù)分頻器降低頻率:定時器0、1共用第一預(yù)分頻器,
定時器2、3、4公用第二個預(yù)分頻器。
再次預(yù)分頻器的輸出將進(jìn)入第二級分頻器,它們輸出5種頻率的時鐘:2分頻、4分頻、8分頻、16分頻或者外部時鐘TCLK0、TCLK1,每個定時器的工作時鐘也可以從這5種頻率中選擇。
定時器初始化:步驟:
1.定時器時鐘頻率
(定時器的時鐘頻率需要經(jīng)過兩次的分頻)例如:定時器的時鐘頻率50--表示:每一秒鐘把定時器的初始值減去50;
2.設(shè)置定時器計(jì)數(shù)值;
--即設(shè)置定時器的初始值(比較值為0)
3.設(shè)置中斷處理函數(shù);--即定時器到時間時去處理什么函數(shù)
定時器輸出時鐘頻率=PCLK/{prescalervalue+1} /{divider value}
{prescaler value} =0 ~255(第一次預(yù)分頻通過TCFG0設(shè)置)
{divider value} = 2, 4, 8, 16(第二次預(yù)分頻通過TCFG1設(shè)置)
TCMPB0:定時器n的比較值
TCNTB0:初始計(jì)數(shù)值(放到TCNT0后TCNT0會自動減一直到減到== TCMPB0)
之后設(shè)置TCON會自動重新裝載TCMPB0和TCNTB0再次重新計(jì)數(shù)
定時器工作流程
1.程序初始化,設(shè)置TCMPBn、TCNTBn這兩個寄存器,它們表示定時器n的比較值、初始計(jì)數(shù)值。
2.設(shè)置TCON寄存器定時器n,這時TCMPBn、TCNTBn的值將被裝入其內(nèi)部寄存器TCMPn、TCNTn中。在定時器n的工作頻率下,TCNTn開始減一計(jì)數(shù),其值可以通過讀取TCNTOn寄存器得知。
3.當(dāng)TCNTn的值等于TCMPn的值時,定時器n的輸出管腳TOUTn反轉(zhuǎn);TCNTn繼續(xù)減一計(jì)數(shù)。
4.當(dāng)TCNTn的值到達(dá)0時,器輸出管腳TOUTn再次反轉(zhuǎn),并觸發(fā)定時器n的中斷。
5.當(dāng)TCNTn的值到達(dá)0時,如果TCON寄存器中將定時器n設(shè)為“自動加載”,則TCMPB0和TCNTB0寄存器的值被自動裝入TCMP0和TCNT0寄存器中,下一個計(jì)數(shù)流程開始。
#defineGLOBAL_CLK1
#include
#include
#include"def.h"
#include"option.h"
#include"2440addr.h"
#include"2440lib.h"
#include"2440slib.h"
#include"mmu.h"
#include"profile.h"
#include"memtest.h"
voidTimer0_init(void);
staticvoid__irqIRQ_Timer0_Handle(void);
voidSet_Clk(void);
staticvoidcal_cpu_bus_clk(void);
voidLed1_init(void);
voidLed1_run(void);
/*************************************************
Functionname:delay
Parameter:times
Description:延時函數(shù)
Return:void
Argument:void
Autor&date:
**************************************************/
voiddelay(inttimes)
{
inti,j;
for(i=0;i for(j=0;j<400;j++); } /************************************************* Functionname:Main Parameter:void Description:主功能函數(shù) Return:void Argument:void Autor&date:Daniel **************************************************/ voidMain(void) { Set_Clk(); MMU_Init(); //Uart_Init(0,115200); //Uart_Select(0); Led1_init(); Timer0_init(); while(1); } /************************************************* Functionname:Timer0_init(void) Parameter:void Description:定時器的初始化 Return:void Argument:void Autor&date:Daniel **************************************************/ voidTimer0_init(void) { //Timer0init rTCFG0=49;//pclk/(49+1) rTCFG1=0x03;//16分頻=62500HZ rTCNTB0 = 6250