1、定時器1概述
定時器1 是一個支持典型的定時/計數功能的獨立16 位定時器,支持輸入捕獲,輸出比較和PWM等功能。定時器有五個獨立的捕獲/比較通道。每個通道定時器要使用一個I/O 引腳。定時器用於范圍廣泛的控制和測量應用,可用的五個通道的正計數/倒計數模式將允許諸如電機控制應用的實現。
定時器1 的功能如下:
• 五個捕獲/比較通道
• 上升沿、下降沿或任何邊沿的輸入捕獲
• 設置、清除或切換輸出比較
• 自由運行、模或正計數/倒計數操作
• 可被1,8,32 或128 整除的時鍾分頻器
• 在每個捕獲/比較和最終計數上生成中斷請求
• DMA 觸發功能
2、16 位計數器
【關於分頻,時鍾】定時器包括一個16 位計數器,在每個活動時鍾邊沿遞增或遞減。活動時鍾邊沿周期由寄存器位CLKCON.TICKSPD定義,它設置全球系統時鍾的划分,提供了從0.25MHz 到32MHz 的不同的時鍾標簽頻率(可以使用32 MHz XOSC 作為時鍾源)。這在定時器1 中由T1CTL.DIV設置的分頻器值進一步划分。這個分頻器值可以從1、8、32 或128。因此當32 MHz 晶振用作系統時鍾源時,定時器1 可以使用的最低時鍾頻率是1953.125Hz,最高是32 MHz。當16MHz RC 振盪器用作系統時鍾源時,定時器1 可以使用的最高時鍾頻率是16MHz。
【讀取定時器當前值】計數器可以作為一個自由運行計數器,一個模計數器或一個正計數/倒計數器運行,用於中心對齊的PWM。可以通過兩個8 位的SFR 讀取16 位的計數器值:T1CNTH 和T1CNTL,分別包含在高位字節和低位字節中。當讀取T1CNTL 時,計數器的高位字節在那時被緩沖到T1CNTH,以便高位字節可以從T1CNTH 中讀出。因此!!!T1CNTL 必須總是在讀取T1CNTH 之前首先讀取。對T1CNTL 寄存器的所有寫入訪問將復位16 位計數器。當達到最終計數值(溢出)時,計數器產生一個中斷請求。
【控制定時器】可以用T1CTL 控制寄存器設置啟動並停止該計數器。當一個不是00 值的寫入到T1CTL.MODE 時,計數器開始運行。如果00 寫入到T1CTL.MODE,計數器停止在它現在的值上。
3、定時器1 操作
一般來說控制寄存器T1CTL 用於控制定時器操作。狀態寄存器T1STAT 保存中斷標志。各種操作模式如下所述。
4、自由運行模式
在自由運行操作模式下,計數器從0x0000 開始,每個活動時鍾邊沿增加1。當計數器達到0xFFFF(溢出),計數器載入0x0000,繼續遞增它的值,如圖1 所示。當達到最終計數值0xFFFF,設置標志IRCON.T1IF 和T1STAT.OVFIF。如果設置了相應的中斷屏蔽位TIMIF.OVFIM 以及IEN1.T1EN,將產生一個中斷請求。自由運行模式可以用於產生獨立的時間間隔,輸出信號頻率。(0xFFFF型)
圖1 自由運行模式
5、模模式
當定時器運行在模模式,16 位計數器從0x0000 開始,每個活動時鍾邊沿增加1。當計數器達到T1CC0(溢出),寄存器T1CC0H:T1CC0L 保存的最終計數值,計數器將復位到0x0000,並繼續遞增。如果定時器開始於T1CC0 以上的一個值,當達到最終計數值(0xFFFF)時,設置標志IRCON.T1IF 和T1CTL.OVFIF。如果設置了相應的中斷屏蔽位TIMIF.OVFIM 以及IEN1.T1EN,將產生一個中斷請求。模模式可以用於周期不是0xFFFF的應用程序。計數器的操作展示在圖2 中。(自定義上限型)
圖2 模模式
6、正計數/倒計數模式
在正計數/倒計數模式,計數器反復從0x0000 開始,正計數直到達到T1CC0H:T1CC0L 保存的值。然后計數器將倒計數直到0x0000,如圖3 所示。這個定時器用於周期必須是對稱輸出脈沖而不是0xFFFF 的應用程序,因此允許中心對齊的PWM 輸出應用的實現。在正計數/倒計數模式,當達到最終計數值時,設置標志IRCON.T1IF 和T1CTL.OVFIF。如果設置了相應的中斷屏蔽位TIMIF.OVFIM 以及IEN1.T1EN,將產生一個中斷請求。(增減交替型)
圖3 正計數/倒計數模式
7、通道模式控制
通道模式隨着每個通道的控制和狀態寄存器T1CCTLn 設置。設置包括輸入捕獲和輸出比較模式。
8、 輸入捕獲模式
當一個通道配置為輸入捕獲通道,和該通道相關的I/O 引腳必須被配置為輸入。(什么是輸入捕獲模式,運作機制)在啟動定時器之后,輸入引腳的一個上升沿、下降沿或任何邊沿都將觸發一個捕獲,即把16 位計數器內容捕獲到相關的捕獲寄存器中。因此定時器可以捕獲一個外部事件發生的時間。(捕獲外部事件發生時間)
注意:在定時器可以使用一個輸入/輸出引腳之前,所需的I/O 引腳必須配置為定時器1 的外設引腳。通道輸入引腳和內部系統時鍾是同步的。因此輸入引腳上的脈沖的最低持續時間必須大於系統時鍾周期。
16 位捕獲寄存器的內容從寄存器T1CCnH:T1CCnL 中讀出。當捕獲發生時,要設置IRCON.T1IF 標志和該通道的中斷標志T1STAT.CHnIF(n 是通道號碼)。如果分別設置了相應的中斷屏蔽位T1CCTLn.IM,以及IEN1.T1EN,將產生一個中斷請求。
9、輸出比較模式(最難理解的一個,下面的邊沿對其和中心對其其實是基於輸出比較的運作核心,用上面講的幾種簡單的模式實現PWM,中心對齊是利用模模模式實現的)
在輸出比較模式中,與通道相關的IO要設置為輸出模式。(什么是輸出比較模式,運作機制)在定時器啟動后, 計數器的內容會和通道比較寄存器中的內容T1CCnH:T1CCnL做比較。如果這兩個內容(值)相等,輸出引腳根據比較輸出模式T1CCTLn.CMP的設置進行設置、復位或切換。(核心就是將T1CC0的值和每個通道寄存器中的值比較,相等了則產生中斷等)
注意:輸出引腳運行在一個給定輸出比較模式下時,它上面的所有邊沿都是無故障運行的。
寫入比較寄存器T1CCnL 將被緩沖,這樣寫入到T1CCnL 的值不起作用,直到相應的高位寄存器T1CCnH 被寫入。寫入比較寄存器T1CCnH:T1CCnL 對於輸出比較值不起作用,直到定時器達到0x00。
注意:通道0 的輸出比較模式較少,因為T1CC0H:T1CC0L 在模式6 和7 有一個特殊功能,這意味着這些模式對於通道0 是不能使用的。
當發生一個比較時,設置IRCON.T1IF 標志和該通道的中斷標志T1STAT.CHnIF(n 是通道號碼)。如果分別設置了相應的中斷屏蔽位T1CCTLn.IM,以及IEN1.T1EN,將產生一個中斷請求。
不同定時器模式下輸出比較模式的例子給定在以下圖中。
邊沿對齊:PWM 輸出信號可以使用定時器在自由運行模式下,通道1 和2 在輸出比較模式6 或7(第6和第7條線)下生成(由T1CCTLn.CMP 位定義,其中n 是1 或2),如圖4 所示。PWM 信號的周期通過設置T1CC0 確定,通道輸出的占空比由T1CCn 確定,其中n 是PWM 通道1 或2。也可以使用定時器自由運行模式。在這種情況下,T1CTL.DIV 位中的CLKCON.TICKSPD 和分頻器值設置PWM 信號的周期。PWM 信號的極性由使用的是輸出比較模式6 還是7 確定。PWM 輸出信號還可以使用圖4 所示的輸出比較模式4 和5,或通過使用圖5 所示的模模式生成。對於簡單的PWM,最好使用使用輸出比較模式4 和5 來生成。
圖4 輸出比較模式,定時器自由運行模式
圖中0、1、2...6是7種模式,左邊的波形對應每種模式
圖5 輸出比較模式,定時器模模式
中心對齊:PWM 輸出可以通過選擇定時器正計數/倒計數模式生成。根據PWM 信號所需的極性選擇通道輸出比較模式4 或5(由T1CCTLn.CMP 位定義,其中n 是1 或2)。PWM 信號的周期由T1CC0 確定,通道輸出的占空比由T1CCn 確定,其中n 是PWM 通道1 或2。某些類型的電機驅動應用程序會需要中心對齊的PWM 模式,一般地這比邊沿對齊的PWM 模式產生的噪音更少,因為I/O 引腳傳輸不集中在同一個時鍾邊沿上。
圖6 輸出比較模式,定時器正計數/倒計數模式
(附加小姿勢)在一些類型的應用程序中,需要在輸出之間定義一個延遲或死亡的時間。典型地,這用於輸出驅動一個H橋配置,以避免H 橋的一邊交叉傳導失控。延遲或死亡時間可以通過使用T1CCn 在PWM 輸出中獲得,如下所示:
假定通道1 和通道2 使用定時器正計數/倒計數模式,用於驅動輸出,且這兩個通道分別使用輸出比較模式4 和5,那么定時器周期(定時器1 的時鍾周期)是:
tP = T1CC0 x 2
死亡時間,即兩個輸出都為低電平的時間,(定時器1 的時鍾周期)是:
tD = T1CC1 – T1CC2
當下列情況發生,比較輸出引腳初始化為表9-1 所列的值:
一個值被寫入T1CNTL(所有定時器1 通道)
0x7 被寫到T1CCTLn.CMP(通道n)
表9-1 初始的比較輸出值(比較模式)
10、IR 信號產生和線性化 (*)
本節描述了CC253x 設備只需最少的SW 參與即可產生IR 的功能。
10.1、簡介(*)
為遠程控制產生IR 信號一般以下面兩種方式之一完成:
調制碼
非調制碼(C 碼,閃存代碼)
CC253x 包括靈活的定時器功能,以最少的CPU 參與,來執行這兩種類型的IR 信號的產生和線性化。大多數IR 協議每個命令只需一個CPU 干預即可實現。
10.2、調制碼(*)
調制碼可以使用定時器1(16 位)和定時器3(8 位)生成。處於調制模式的定時器3 用於產生載波。定時器3 有一個單獨的分頻器,用於它的輸入。它的周期使用T3CC0 設置。定時器3 通道1 用於PWM 輸出。載波的占空比使用T3CC1 設置。通道1 使用比較模式:“在比較設置輸出,在0xFF 清除”(T3CCTL1.CMP = 101)。
表9-2 顯示了定時器3 的38kHz 載波的頻率誤差計算。(用定時器3產生載波)
38kHz 載波的頻率誤差計算
IRCTL.IRGEN 寄存器位使得IR 產生模式處於定時器1。當設置了IRGEN 位,定時器1采用定時器3通道1的輸出比較信號作為標記,而不是采用系統標記。定時器1周期是使用T1CC0 設置的,定時器1處於調制模式(T1CTL.MODE = 10),通道0處於比較模式(T1CCTL0.MODE = 1)。通道1比較模式“在比較設置輸出,在0x0000 清除”(T1CCTL1.CMP = 011)用於輸出門控信號。
標記載波的個數由T1CC1. T1CC1 設置,需要每個定時器1 周期由DMA 或CPU 更新一次。注意T1CC1的一個更新被緩沖,在定時器1 達到0x0000 之前不起作用。
空間載波的個數由T1CC0 設置。其值必須設置為標記和空間載波周期希望的總數。比較值被緩沖直到定時器達到0x0000。
定時器1 通道1 的輸出進行定時器3 通道1 的輸出和運算,作為IR 的輸出,如圖。
圖7 定時器在IR 產生模式的方框圖
定時器3 通道1 輸出和定時器1 通道1 輸出信號的時序是同步的,這樣在IR 輸出信號上就沒有故障。當設置了IRGEN 位,IR 輸出信號被送到引腳,而不是送到一般的定時器1 通道1 輸出。下圖顯示了定時器3 被初始化為33%的占空比(T3CC0 = 3× T3CC1)的例子。定時器1 已經被初始化為3。(如果僅僅要實現一個空間周期,T1CC1 必須設置為0x00。)
圖8 調制的波形示例
10.3 非調制碼(*)
要產生非調制IR 碼,定時器1 要處於模模式。信號的周期由T1CC0 給定,脈沖寬度由T1CC1 給定。T1CC1給出標記周期的長度,T1CC0 給出標記和空間周期的總數。比較值被緩沖,直到定時器達到0x0000。如果比較值不能保持不變,必須在每個周期由DMA 或CPU 更新。
10.4 學習(*)
學習通過使用定時器1(16 位)和定時器3(8 位)的捕獲功能完成。定時器3 可以處理載波頻率檢測,定時器1 可以處理調制信代碼的學習。電路應該按照圖9 所述安裝。
圖9 IR 學習的方框圖
10.4.1 載波頻率檢測(*)
定時器3 用於捕獲和檢測直接從IR 引腳二極管輸入的載波頻率。定時器必須對載波進行一定次數的采樣。如果載波被檢測,被檢測出的頻率必須提供平均數,這會存儲在數據庫中。
10.4.2 解調碼學習(*)
IR 引腳二極管的輸出由一個合適的電路解調。這一電路的輸出用作處於捕獲模式的定時器1 其中一個通道的輸入。
10.5 其他注意事項(*)
IR 輸出引腳在復位期間必須處於三態或下拉狀態,以避免點亮IR LED 這一不必要的功耗。注意只有定時器1 通道1 的輸出P1.1 是三態的,在復位期間和復位后沒有上拉。
11、定時器1 中斷
為定時器分配了一個中斷向量。當下列定時器事件之一發生時,將產生一個中斷請求:
● 計數器達到最終計數值(溢出或回到零)
● 輸入捕獲事件
● 輸出比較事件
寄存器狀態寄存器T1STAT 包括最終計數值事件和五個通道比較/捕獲事件的中斷標志。僅當設置了相應的中斷屏蔽位和IEN1.T1EN 時,才能產生一個中斷請求。中斷屏蔽位是n 個通道的T1CCTLn.IM 和溢出事件TIMIF.OVFIM。如果有其它未決中斷,必須在一個新的中斷請求產生之前,通過軟件清除相應的中斷標志。而且,如果設置了相應的中斷標志,使能一個中斷屏蔽位將產生一個新的中斷請求。
12、定時器1 DMA 觸發
有三種DMA 觸發與定時器1 有關。這些是DMA 觸發T1_CH0,T1_CH1 和T1_CH2,分別在以下定時器比較事件上產生:
● T1_CH0 – 通道0 比較
● T1_CH1 – 通道1 比較
● T1_CH2 – 通道2 比較
通道3 和4 沒有相關的觸發。
13、定時器1 寄存器
本節描述了定時器1 的寄存器,由以下寄存器組成:
● T1CNTH – 定時器1 計數高位
● T1CNTL – 定時器1 計數低位
● T1CTL – 定時器1 控制
● T1STAT –定時器1 狀態
● T1CCTLn – 定時器1 通道n 捕獲/比較控制
● T1CCnH – 定時器1 通道n 捕獲/比較高位值
● T1CCnL – 定時器1 通道n 捕獲/比較低位值
TIMIF.OVFIM 寄存器位駐留在TIMIF 寄存器,和定時器3 和定時器4 寄存器一起描述。
14、作為數組訪問定時器1 寄存器
定時器1 捕獲/比較通道寄存器可以在XDATA 存儲空間中作為一個連續的區域被訪問。這使得可以作為一個簡單的索引結構方便地訪問寄存器。5 個捕獲/比較控制寄存器映射到0x62A0 - 0x62A4。16 位捕獲/比較值映射到0x62A6 - 0x62AF。0x62A5 不使用。
15、代碼示例
15.1、定時器輪訓方式
下面代碼展示了通過設置定時器1計數來控制LED閃爍,這里沒有采用中斷方式,而是采用普通的輪訓。關於LED的初始化我在前幾節已經介紹了。這里重點看和定時器1相關的部分:
① 第33行將T1CTL設置為0x0d=0000 1101,參考下面寄存器表可知是通過設置定時器1的控制和狀態寄存器來將定時器設置為:128分頻,自由運行,從0x0000到0xFFFF反復計數。由於系統在沒配置工作頻率時默認是2分頻,即32MHz/2=16MHz,因此定時器每次溢出的時間T=1/(16MHz/128)*65536=0.524s
② 第34行將T1STAT設置為0x21=0010 0001,參考下面的寄存器表知為使用定時器1的通道0,且中斷有效。
③ 在49行一旦IRCON>0表明發生了某個中斷,在該例程中我們僅僅用了TIMER1的中斷,因此表明TIMER1中斷發生:
因此下面整個程序實現的功能是:利用定時器1的通道0產生0.524s的周期性中斷,每次發生中斷系統會自動置IRCON的第1位為1,在main函數的輪訓中一旦檢測到該信息,則讓計數變量count加1,一旦count計數大於1時,就讓LED狀態翻轉,實現1SLED閃爍控制。
1 /**************************************************************************** 2 * 文 件 名: main.c 3 * 版 本: 1.0 4 * 描 述: 定時器T1通過查詢方式控制LED1周期性閃爍 5 ****************************************************************************/ 6 #include <ioCC2530.h> 7 8 typedef unsigned char uchar; 9 typedef unsigned int uint; 10 11 #define LED1 P1_0 // P1.0口控制LED1 12 13 /**************************************************************************** 14 * 名 稱: InitLed() 15 * 功 能: 設置LED燈相應的IO口 16 * 入口參數: 無 17 * 出口參數: 無 18 ****************************************************************************/ 19 void InitLed(void) 20 { 21 P1DIR |= 0x01; //P1.0定義為輸出 22 LED1 = 1; //使LED1燈上電默認為熄滅 23 } 24 25 /**************************************************************************** 26 * 名 稱: InitT1() 27 * 功 能: 定時器初始化,系統不配置工作時鍾時默認是2分頻,即16MHz 28 * 入口參數: 無 29 * 出口參數: 無 30 ****************************************************************************/ 31 void InitT1() 32 { 33 T1CTL = 0x0d; //128分頻,自動重裝 0x0000-0xFFFF 34 T1STAT= 0x21; //通道0,中斷有效 35 } 36 37 /**************************************************************************** 38 * 程序入口函數 39 ****************************************************************************/ 40 void main(void) 41 { 42 uchar count=0; 43 44 InitLed(); //調用初始化函數 45 InitT1(); 46 47 while(1) 48 { 49 if(IRCON > 0) 50 { 51 IRCON=0; 52 if(count++ >= 1) //約1s周期性閃爍,示波器測大約為1025MS 53 { 54 count=0; 55 LED1 = !LED1; //LED1閃爍 56 } 57 } 58 } 59 }
15.2、定時器中斷方式
上面采用輪訓的方法是比較占資源的,類似我們按鍵那節中介紹的,除了輪訓我們還可以用中斷方式!在黃色初始化部分比采用輪訓方式多了使能T1中斷和總中斷的部分(35、36行代碼)。我之前沒有加這兩句代碼,結果橙色部分的定時器1中斷回調函數無法被觸發!查datasheet發現Interrupt Overview:如果想觸發回調函數,需要將EA開關和T1IE開關打開才行!
1 /**************************************************************************** 2 * 文 件 名: main.c 3 * 版 本: 1.0 4 * 描 述: 定時器T1通過查詢方式控制LED1周期性閃爍 5 ****************************************************************************/ 6 #include <ioCC2530.h> 7 8 typedef unsigned char uchar; 9 typedef unsigned int uint; 10 11 #define LED1 P1_0 // P1.0口控制LED1 12 13 /**************************************************************************** 14 * 名 稱: InitLed() 15 * 功 能: 設置LED燈相應的IO口 16 * 入口參數: 無 17 * 出口參數: 無 18 ****************************************************************************/ 19 void InitLed(void) 20 { 21 P1DIR |= 0x01; //P1.0定義為輸出 22 LED1 = 1; //使LED1燈上電默認為熄滅 23 } 24 25 /**************************************************************************** 26 * 名 稱: InitT1() 27 * 功 能: 定時器初始化,系統不配置工作時鍾時默認是2分頻,即16MHz 28 * 入口參數: 無 29 * 出口參數: 無 30 ****************************************************************************/ 31 void InitT1() 32 { 33 T1CTL = 0x0d; //128分頻,自動重裝 0x0000-0xFFFF 34 T1STAT= 0x21; //通道0,中斷有效 35 T1IE = 1; //開總中斷和T1中斷 36 EA = 1; //開總中斷 37 } 38 39 //定時器T1中斷處理函數 40 #pragma vector = T1_VECTOR 41 __interrupt void T1_ISR(void) 42 { 43 static uchar count=0; 44 IRCON = 0x00; //清中斷標志, 也可由硬件自動完成 45 if(count++ >= 1) //約1s周期性閃爍,示波器測大約為1025MS 46 { 47 count=0; 48 LED1 = !LED1; //LED1閃爍 49 } 50 } 51 52 /**************************************************************************** 53 * 程序入口函數 54 ****************************************************************************/ 55 void main(void) 56 { 57 InitLed(); //調用初始化函數 58 InitT1(); 59 60 while(1){} 61 }
Zigbee系列文章:
[ZigBee] 3、ZigBee基礎實驗——GPIO輸出控制實驗-控制Led亮滅
PS:如果您覺得還不錯,點個贊,讓更多人受益~
@beautifulzzzz 2016-07-13 continue~
e-mail:beautifulzzzz@qq.com
sina:http://weibo.com/beautifulzzzz?is_all=1