Exynos4412裸機開發——PWM定時器
一、PWM定時器
4412時鐘為我們提供了PWM定時器,在4412中共有5個32位的定時器,這些定時器可傳送中斷訊號給ARM子系統。另外,定時器0、1、2、3包含了脈衝寬度調製(PWM),並可驅動其拓展的I/O。PWM對定時器0有可選的dead-zone功能,以支援大電流裝置。要注意的是定時器4是內建不接外部引腳的。一般用於定時器功能。
定時器0與定時器1共用一個8位預分頻器,定時器2、定時器3與定時器4共用一另一個8位預分頻器,每個定時器都有一個時鐘分頻器,時鐘分頻器有5種分頻輸出(1/2、1/4、 1/8 、1/16和外部時鐘TCLK)。另外,定時器可選擇時鐘源,定時器0-4都可以選擇外部的時鐘源,如PWM_TCLK。
當時鐘被使能後,定時器計數緩衝暫存器(TCNTBn)把計數器初始值下載到遞減計數器中。定時器比較緩衝暫存器(TCMPBn)把其初始值下載到比較暫存器中,並將該值與遞減計數器的值進行比較。當遞減計數器和比較暫存器值相同時,輸出電平翻轉。遞減計數器減至0後,輸出電平再次翻轉,完成一個輸出週期。這種基於TCNTBn和TCMPBn的雙緩衝特性使定時器在頻率和佔空比變化時能產生穩定的輸出。
每個定時器都有一個專用的由定時器時鐘驅動的16位遞減計數器。當遞減計數器的計數值達到0時,就會產生定時器中斷請求來通知CPU定時器操作完成。當定時器遞減計數器達到0的時候,如果設定了Auto-Reload 功能,相應的TCNTBn的值會自動過載到遞減計數器中以繼續下次操作。然而,如果定時器停止了,比如在定時器執行時清除TCON中定時器使能位,TCNTBn的值不會被過載到遞減計數器中。
TCMPBn 的值用於脈衝寬度調製(PWM)。當定時器的遞減計數器的值和比較暫存器的值相匹配的時候,定時器控制邏輯將改變輸出電平。因此,比較暫存器決定了PWM 輸出的開關時間。
PWM定時器的特點如下:
1)5個32位定時器;
2)2個8位PCLK分頻器提供一級預分,5個2級分頻器用來預分外部時鐘;
3)可程式設計選擇PWM獨立通道。
4)4個獨立的可程式設計的控制及支援校驗的PWM通道。
5)靜態配置:PWM停止;
6)動態配置:PWM啟動;
7)支援自動重灌模式及觸發脈衝模式;
8)一個外部啟動引腳。
9)兩個PWM輸出可帶Dead-Zone 發生器。
10)中斷髮生器。
1、定時器配置暫存器0(TFCG0)
2、定時器配置暫存器1(TCFG1)
主要用於PWM定時器的MUX輸入
4412的PWM定時器具有雙緩衝功能,能在不停止當前定時器執行的情況下,過載定時器下次執行的引數。所以儘管新的定時器的值被設定好了,但是當前操作仍能成功完成。
定時器的值可以被寫入定時器n 計數緩衝暫存器(TCNTBn),當前的計數器的值可以從定時器計數觀察暫存器(TCNTOn)讀出。讀出的TCNTBn值並不是當前的計數值,而是下次將過載的計數值。
TCNTn的值等於0的時候,自動過載操作把TCNTBn的值裝入TCNTn,只有當自動過載功能被使能並且TCNTn 的值等於0的時候才會自動過載。如果TCNTn等於0,自動過載控制位為0,則定時器停止執行。
使用手動更新位(Manual Update)和反轉位(Inverter)完成定時器的初始化。當遞減計數器的值達到0的時候會發生定時器自動過載操作,所以TCNTn的初始值必須由使用者提前定義好,在這種情況下就需要手動更新位過載初始值。一下幾個步驟給出如何啟動定時器。
1)向TCNTBn 和 TCMPBn寫入初始值。
2)置位相應定時器的手動更新為,不管是否使用翻轉功能,推薦設定反轉位。
3)置位相應定時器的啟動位啟動定時器,清除手動更新位。
如果定時器被強制停止,TCNTn保持原來的值而不是TCNTBn的過載值。如果要設定一個新的值,必須執行手動更新操作。
下面是一個例項:
控制蜂鳴器
該開發板的蜂鳴器是無源蜂鳴器,所有我們不能用該埠輸出高低電平來控制蜂鳴器的播放,必須要使用PWM定時器來控制。
標頭檔案定義:
typedef struct {
unsigned int TCFG0;
unsigned int TCFG1;
unsigned int TCON;
unsigned int TCNTB0;
unsigned int TCMPB0;
unsigned int TCNTO0;
unsigned int TCNTB1;
unsigned int TCMPB1;
unsigned int TCNTO1;
unsigned int TCNTB2;
unsigned int TCMPB2;
unsigned int TCNTO2;
unsigned int TCNTB3;
unsigned int TCMPB3;
unsigned int TCNTO3;
unsigned int TCNTB4;
unsigned int TCNTO4;
unsigned int TINT_CSTAT;
}pwm;
#define PWM (* (volatile pwm *)0x139D0000)
控制部分:
void pwm_init(void)
{
GPD0.CON = GPD0.CON & (~(0xf))| 0x2;
GPD0.PUD = GPD0.PUD & (~(0xf)) ;
PWM.TCFG0 = PWM.TCFG0 & (~(0xff))|0xf9;
PWM.TCFG1 = PWM.TCFG1 & (~(0xf)) | 0x2;
PWM.TCMPB0 = 50;
PWM.TCNTB0 = 100;
PWM.TCON = PWM.TCON & (~(0xff)) | (1 << 0) | (1 << 1) ;
//第一次要手動設定
}
void beep_on(void)
{
PWM.TCON = PWM.TCON & (~(0xff)) | (1 << 0) | (1 << 3) ;
}
void beep_off(void)
{
PWM.TCON = PWM.TCON & (~(1 << 0)) ;
}