CC2541藍牙學習——定時器3和定時器4


定時器3和定時器4與定時器1功能類似,都有三種模式:自由運行模式、模模式、正計數/倒計數模式,都有輸入捕獲和輸出比較功能,不同的是定時器3和定時器4是8位計數器,而定時器1是16位的,另外定時器3和定時器4只有2個通道,定時器多了一個模式:倒計數模式。由於定時器3和定時器4相似,下面以定時器3為例說明。

定時器3和定時器4是兩個8位定時器,每個定時器有兩個獨立的捕獲/比較通道,每一通道使用一個I/O引腳。

定時器3/4有以下特點:

  • 兩個捕獲/比較通道;
  • 設置,清除或切換輸出比較;
  • 每時鍾可以被以下分頻:1、2、4、8、16、32、64、128;
  • 在每次捕獲/比較和最終計數事件發生時產生中斷請求;
  • DMA觸發功能。

定時器3的計數器在時鍾的邊沿遞增或遞減,活動時鍾邊沿的周期由寄存器位CLKCONCMD.TICKSPD[2:0]定義,並且由T3CTL.DIV[2:0]設置分頻值。T3CTL寄存器定義如下:

我們可以看到,定時器3對比與定時器1多了一個倒計數模式:從T3CC0到0x00反復計數。

另外定時器3還有一個啟動定時器位,當TxCTL.START寫入1,則定時器計數器開始計數,當TxCTL.START寫入0,計數器暫停在當前值

還有一個位TxCTL.CLR,當寫入1,計數器清0並且初始化相關通道的所有輸出引腳

開始、暫停、清零功能都有了,是不是很像秒表,呵呵。

定時器3的計數器為寄存器T3CNT,展示的當前的計數值,是只讀的。

定時器3的四種模式:

自由運行模式:從0x00開始在每個時鍾沿遞增,直到0xff,再回到0x00,再遞增,周而復始,當計數值到達0xff時,溢出中斷標志位TIMIF.T3OVFIF置1。

倒計數模式:T3CNT計數值裝入初值T3CC0,從T3CC0開始在每個時鍾沿遞減,直到0x00,定時器發生溢出中斷,溢出中斷標志位TIMIF.T3OVFIF置1。

注意:倒計數模式是一次事件的定時,什么意思呢?當TxCTL.START寫入1時,從T3CC0開始在每個時鍾沿遞減,到達0x00時TxCTL.START位變為0,如果需要再定時就需要繼續啟動START,即TxCTL.START置1.

定時器3的倒計數模式初始化程序:

 1 /******************************************************************************
 2 *函 數 名:InitT3
 3 *功    能:定時器3初始化
 4 *入口參數:無
 5 *出口參數:無
 6 ******************************************************************************/
 7 void InitT3(void)
 8 {
 9   T3CTL  = 0xed;     //定時器3 128分頻,倒計數模式,溢出中斷使能,計數器清0
10   T3CC0 = 0x80;      //定時器3通道0捕獲/比較值
11   IEN1  |= (1<<3);   //定時器3中斷使能
12   EA = 1;            //開總中斷
13   T3CTL |= 0x10;     //啟動定時器3
14 }

中斷服務程序:實現LED燈閃爍功能。注意第12行,再次啟動定時器3,沒有這句,中斷程序只執行一次。另外10行和11行可以不要,因為中斷標志位會自動硬件清0,但是如果通過查詢方式實現定時器的功能時必須要軟件清0,為了保持一致,每次寫程序時,都軟件清0!

 1 /******************************************************************************
 2 *函 數 名:Timer3_ISR
 3 *功    能:定時器3中斷服務程序
 4 *入口參數:無
 5 *出口參數:無
 6 ******************************************************************************/
 7 #pragma vector = T3_VECTOR 
 8 __interrupt void Timer3_ISR(void) 
 9 { 
10   IRCON &= ~0x08;       //定時器3中斷標志位清0
11   TIMIF &= ~0x01;       //定時器3溢出中斷標志位清0
12   T3CTL |= 0x10;        //再次啟動定時器3
13   if(count++ > 250)
14   {
15     count = 0;
16     LED1 = ~LED1; 
17   }
18 }

 

模計數模式:從0x00開始在每個時鍾沿遞增,直到T3CC0,再回到0x00,再遞增,周而復始,如果計數值初值大於T3CC0,則計數值遞增到0xff,計數器溢出,溢出中斷標志位TIMIF.T3OVFIF置1。與定時器1一樣,使用定時器3的模模式必須要開啟通道0的輸出比較功能,注意兩點

1) 模模式需要開啟通道0的輸出比較模式,否則計數器到了0xFF時,才會產生溢出中斷,也就是說如果沒有設置通道0的輸出比較模式,計數器的值到了T3CC0設置的比較值后也不會產生溢出中斷。

2) T3的模模式不是普通的溢出中斷,和連續計數模式不同,它必須設置通道0的輸出比較功能,使能中斷時,也是使能通道0的輸出比較中斷屏蔽位。產生中斷時的中斷標志也是通道0的輸出比較中斷標志,而不是計數溢出標志

正計數/倒計數模式:從0X00遞增到TxCC0里設置的值,然后遞減到0X00,溢出中斷標志位TIMIF.T3OVFIF置1。

注意:TIMIF.TxOVFIF 和 TIMIF.TxCHnIF不管中斷使能位(屏蔽位)是否為1,當定時器計數值溢出或通道0、1發生中斷都會置1,也就是說,TIMIF.TxOVFIF 和 TIMIF.TxCHnIF位置1不受是否開中斷影響。

但是,IRCON.T3IF 和IRCON.T4IF位必須在中斷使能位為1的情況下,發生中斷才會置1.定時器3和定時器4中斷使能有三個地方需要設置:IEN1.TxIEN 、 IEN0.EA、通道中斷使能TxCCTLn.IM

定時器3和定時器4沒有寄存器T3STAT和T4STAT

定時器3和定時器4的程序與定時器1的程序相似,詳見我的博客關於定時器1的介紹,感覺倒計數模式沒什么用,和模模式實現的功能是一樣的,區別只是一個正計數,一個倒計數,建議用模計數代替倒計數模式。這里給出定時器3模模式的程序,和定時器1一樣,需要設置設置通道0的輸出比較功能

定時器3的模模式初始化程序:

 1 /******************************************************************************
 2 *函 數 名:InitT3
 3 *功    能:定時器3初始化
 4 *入口參數:無
 5 *出口參數:無
 6 ******************************************************************************/
 7 void InitT3(void)
 8 {
 9   T3CTL  = 0xee;     //定時器3 128分頻,模計數器模式,溢出中斷使能,計數器清0
10   T3CCTL0 = 0x44;    //通道0比較功能,並且開通道0中斷
11   T3CC0 = 0xff;      //定時器3通道0捕獲/比較值
12   IEN1  |= (1<<3);   //定時器3中斷使能
13   EA = 1;            //開總中斷
14   T3CTL |= 0x10;     //啟動定時器3
15 }

 

整個程序如下,實現功能:LED燈定時閃爍。

 1 /******************************************************************************
 2 *文 件 名:Timer3.c
 3 *作    者:陳照
 4 *時    間:2015-05-15
 5 *版    本:1.0
 6 *描    述:定時器3模模式中斷
 7 ******************************************************************************/
 8 #include <iocc2541.h>
 9 
10 typedef unsigned char uchar;
11 typedef unsigned int  uint;
12 
13 #define LED1 P1_0
14 uint count = 0;          //定時器計數溢出次數
15 
16 /****************************************************************
17 *函 數 名:SysStartXOSC
18 *功    能:系統時鍾初始化
19 *入口參數:無
20 *出口參數:無
21 *****************************************************************/
22 void SysStartXOSC(void)
23 {
24     SLEEPCMD &= ~0x04;                      // 啟動所有晶振
25     while (!(SLEEPSTA & 0x40));             // 等待晶振穩定
26 
27     CLKCONCMD = (CLKCONCMD & 0x80) | 0x49;  // 使用16M晶振作為主時鍾
28     while ((CLKCONSTA & ~0x80) != 0x49 );   // 等待主時鍾切換到16M晶振
29 
30     CLKCONCMD = (CLKCONCMD & ~0x80) ;       // 使用外部32K晶振作為休眠時鍾
31     while ( (CLKCONSTA & 0x80) != 0 );      // 等待睡眠時鍾切換到外部32K晶振
32 
33     CLKCONCMD = (CLKCONCMD & 0x80) ;        // 使用32M晶振作為主時鍾
34     while ( (CLKCONSTA & ~0x80) != 0 );     // 等待主時鍾切換到32M晶振
35 
36     SLEEPCMD |= 0x04;                       // 關閉未使用的晶振
37 }
38 
39 /******************************************************************************
40 *函 數 名:InitLED
41 *功    能:LED口功能初始化
42 *入口參數:無
43 *出口參數:無
44 ******************************************************************************/
45 void InitLED(uchar On_Off)
46 {
47   P1SEL &= ~0x01;      //P1.0設置為通用I/O口
48   P1DIR |=  0x01;      //P1.0設置為輸出
49   LED1 = On_Off;       //P1.0亮滅初始化
50 }
51 
52 /******************************************************************************
53 *函 數 名:InitT3
54 *功    能:定時器3初始化
55 *入口參數:無
56 *出口參數:無
57 ******************************************************************************/
58 void InitT3(void)
59 {
60   T3CTL  = 0xee;     //定時器3 128分頻,模計數器模式,溢出中斷使能,計數器清0
61   T3CCTL0 = 0x44;    //通道0比較功能,並且開通道0中斷
62   T3CC0 = 0xff;      //定時器3通道0捕獲/比較值
63   IEN1  |= (1<<3);   //定時器3中斷使能
64   EA = 1;            //開總中斷
65   T3CTL |= 0x10;     //啟動定時器3
66 }
67 
68 /******************************************************************************
69 *函 數 名:Timer3_ISR
70 *功    能:定時器3中斷服務程序
71 *入口參數:無
72 *出口參數:無
73 ******************************************************************************/
74 #pragma vector = T3_VECTOR 
75 __interrupt void Timer3_ISR(void) 
76 { 
77   IRCON &= ~0x08;
78   TIMIF &= ~0x11;
79   if(count++ > 250)
80   {
81     count = 0;
82     LED1 = ~ LED1;  
83   }  
84 }
85 
86 /******************************************************************************
87 *程序入口函數
88 ******************************************************************************/
89 int main(void)
90 {
91   SysStartXOSC();      //配置主時鍾為32MHz,定時器時鍾32MHz
92   InitLED(0);          //LED初始化,熄滅LED1
93   InitT3();            //定時器3初始化
94    
95   while(1);
96 }

在中斷服務程序里,中斷標志位,可以不軟件清除,經過實驗,把這兩句去掉,程序運行正常,但是為了嚴謹性,還是加上吧,畢竟軟件清除中斷標志位也不會影響什么,即使中斷標志位可以自動硬件清零。

  IRCON &= ~0x08;
  TIMIF &= ~0x11;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM