通用定時器(TIMx)
4.1 使得PB5-TIM3通道2產生頻率為12.5Hz的方波,該方波控制LED1的閃爍
4.2 周期控制通用定時器3的2通道,實現1KHz的不同占空比波形,控制LED實現呼吸燈
通用定時器是一個通過可編程預分頻器驅動的16位自動裝載計數器構成。它適用於多種場合,包括測量輸入信號的脈沖長度(輸入捕獲)或者產生輸出波形(輸出比較和PWM)。使用定時器預分頻器和RCC時鍾控制器預分頻器,脈沖長度和波形周期可以在幾個微秒到幾個毫秒間調整。每個定時器都是完全獨立的,沒有互相共享任何資源。它們可以一起同步操作。[正版請搜索:beautifulzzzz(看樓主博客園官方博客,享高質量生活)嘻嘻!!!]
通用TIMx (TIM2、 TIM3、 TIM4和TIM5)定時器功能包括:
● 16位向上、向下、向上/向下自動裝載計數器
● 16位可編程(可以實時修改)預分頻器,計數器時鍾頻率的分頻系數為1 ~65536之間的任意數值
● 4個獨立通道:
─ 輸入捕獲
─ 輸出比較
─ PWM生成(邊緣或中間對齊模式)
─ 單脈沖模式輸出
● 使用外部信號控制定時器和定時器互連的同步電路
● 如下事件發生時產生中斷/DMA:
─ 更新:計數器向上溢出/向下溢出,計數器初始化(通過軟件或者內部/外部觸發)
─ 觸發事件(計數器啟動、停止、初始化或者由內部/外部觸發計數)
─ 輸入捕獲
─ 輸出比較
● 支持針對定位的增量(正交)編碼器和霍爾傳感器電路
● 觸發輸入作為外部時鍾或者按周期的電流管理

圖1 通用定時器框圖
注:
Reg:根據控制位的設定,在U事件時傳送預加載寄存器的內容至工作寄存器
斜向下的箭頭:事件
斜向上的箭頭:中斷和DMA輸出
可編程通用定時器的主要部分是一個16位計數器和與其相關的自動裝載寄存器。這個計數器可以向上計數、向下計數或者向上向下雙向計數。此計數器時鍾由預分頻器分頻得到。計數器、自動裝載寄存器和預分頻器寄存器可以由軟件讀寫,在計數器運行時仍可以讀寫。
時基單元包含:
● 計數器寄存器(TIMx_CNT)
● 預分頻器寄存器 (TIMx_PSC)
● 自動裝載寄存器 (TIMx_ARR)
自動裝載寄存器是預先裝載的,寫或讀自動重裝載寄存器將訪問預裝載寄存器。根據在TIMx_CR1 寄存器中的自動裝載預裝載使能位(ARPE)的設置,預裝載寄存器的內容被立即或在每次的更新事件UEV時傳送到影子寄存器。當計數器達到溢出條件(向下計數時的下溢條件)並當TIMx_CR1 寄存器中的UDIS位等於’0’時,產生更新事件。更新事件也可以由軟件產生。隨后會詳細描述每一種配置下更新事件的產生。
計數器由預分頻器的時鍾輸出CK_CNT驅動,僅當設置了計數器TIMx_CR1 寄存器中的計數器使能位(CEN)時, CK_CNT才有效。
注:真正的計數器使能信號CNT_EN是在CEN的一個時鍾周期后被設置。
預分頻器可以將計數器的時鍾頻率按1 到65536之間的任意值分頻。它是基於一個(在TIMx_PSC寄存器中的)16位寄存器控制的16位計數器。這個控制寄存器帶有緩沖器,它能夠在工作時被改變。新的預分頻器參數在下一次更新事件到來時被采用。(圖2和圖3給出了在預分頻器運行時,更改計數器參數的例子。)

圖2 當預分頻器的參數從1 變到2時,計數器的時序圖
圖3 當預分頻器的參數從1 變到4時,計數器的時序圖
3.2.1 向上計數模式
在向上計數模式中,計數器從0計數到自動加載值(TIMx_ARR計數器的內容),然后重新從0開始計數並且產生一個計數器溢出事件。
每次計數器溢出時可以產生更新事件,在TIMx_EGR寄存器中(通過軟件方式或者使用從模式控制器)設置UG位也同樣可以產生一個更新事件。
設置TIMx_CR1 寄存器中的UDIS位,可以禁止更新事件;這樣可以避免在向預裝載寄存器中寫入新值時更新影子寄存器。在UDIS位被清’0’之前,將不產生更新事件。但是在應該產生更新事件時,計數器仍會被清’0’,同時預分頻器的計數也被請0(但預分頻系數不變)。此外,如果設置了 TIMx_CR1 寄存器中的URS位(選擇更新請求),設置UG位將產生一個更新事件UEV,但硬件不設置UIF標志(即不產生中斷或DMA請求);這是為了避免在捕獲模式下清除計數器時,同時產生更新和捕獲中斷。
當發生一個更新事件時,所有的寄存器都被更新,硬件同時(依據 URS 位)設置更新標志位(TIMx_SR寄存器中的UIF位)。
● 預分頻器的緩沖區被置入預裝載寄存器的值(TIMx_PSC寄存器的內容)。
● 自動裝載影子寄存器被重新置入預裝載寄存器的值(TIMx_ARR)。
下圖給出一些例子,當TIMx_ARR=0x36時計數器在不同時鍾頻率下的動作。

圖4 計數器時序圖,內部時鍾分頻因子為1

圖5 計數器時序圖,內部時鍾分頻因子為2

圖6 計數器時序圖,內部時鍾分頻因子為4

圖7 計數器時序圖,內部時鍾分頻因子為N

圖8 計數器時序圖,當ARPE=0時的更新事件(TIMx_ARR沒有預裝入)

圖9 計數器時序圖,當ARPE=1 時的更新事件(預裝入了TIMx_ARR)
3.2.2 向下計數模式
在向下模式中,計數器從自動裝入的值(TIMx_ARR計數器的值)開始向下計數到0,然后從自動裝入的值重新開始並且產生一個計數器向下溢出事件。
每次計數器溢出時可以產生更新事件,在TIMx_EGR寄存器中(通過軟件方式或者使用從模式控制器)設置UG位,也同樣可以產生一個更新事件。
設置TIMx_CR1 寄存器的UDIS位可以禁止UEV事件。這樣可以避免向預裝載寄存器中寫入新值時更新影子寄存器。因此UDIS位被清為’0’之前不會產生更新事件。然而,計數器仍會從當前自動加載值重新開始計數,同時預分頻器的計數器重新從0開始(但預分頻系數不變)。
此外,如果設置了 TIMx_CR1 寄存器中的URS位(選擇更新請求) ,設置UG位將產生一個更新事件UEV但不設置UIF標志(因此不產生中斷和DMA請求),這是為了避免在發生捕獲事件並清除計數器時,同時產生更新和捕獲中斷。
當發生更新事件時,所有的寄存器都被更新,並且(根據URS位的設置)更新標志位(TIMx_SR寄存器中的UIF位)也被設置。
● 預分頻器的緩存器被置入預裝載寄存器的值(TIMx_PSC寄存器的值)。
● 當前的自動加載寄存器被更新為預裝載值(TIMx_ARR寄存器中的內容)。
注:自動裝載在計數器重載入之前被更新,因此下一個周期將是預期的值。
以下是一些當TIMx_ARR=0x36時,計數器在不同時鍾頻率下的操作例子。

圖10 計數器時序圖,內部時鍾分頻因子為1

圖11 計數器時序圖,內部時鍾分頻因子為2

圖12 計數器時序圖,內部時鍾分頻因子為4

圖13 計數器時序圖,內部時鍾分頻因子為N

圖14 計數器時序圖,當沒有使用重復計數器時的更新事件
3.2.3 中央對齊模式(向上/向下計數)
在中央對齊模式,計數器從0開始計數到自動加載的值(TIMx_ARR寄存器)−1 ,產生一個計數器溢出事件,然后向下計數到1 並且產生一個計數器下溢事件;然后再從0開始重新計數。
在這個模式,不能寫入TIMx_CR1 中的DIR方向位。它由硬件更新並指示當前的計數方向。可以在每次計數上溢和每次計數下溢時產生更新事件;也可以通過(軟件或者使用從模式控制器)設置TIMx_EGR寄存器中的UG位產生更新事件。然后,計數器重新從0開始計數,預分頻器也重新從0開始計數。
設置TIMx_CR1 寄存器中的UDIS位可以禁止UEV事件。這樣可以避免在向預裝載寄存器中寫入新值時更新影子寄存器。因此UDIS位被清為’0’之前不會產生更新事件。然而,計數器仍會根據當前自動重加載的值,繼續向上或向下計數。
此外,如果設置了 TIMx_CR1 寄存器中的URS位(選擇更新請求) ,設置UG位將產生一個更新事件UEV但不設置UIF標志(因此不產生中斷和DMA請求),這是為了避免在發生捕獲事件並清除計數器時,同時產生更新和捕獲中斷。
當發生更新事件時,所有的寄存器都被更新,並且(根據URS位的設置)更新標志位(TIMx_SR寄存器中的UIF位)也被設置。
● 預分頻器的緩存器被加載為預裝載(TIMx_PSC寄存器)的值。
● 當前的自動加載寄存器被更新為預裝載值(TIMx_ARR寄存器中的內容)。
注:如果因為計數器溢出而產生更新,自動重裝載將在計數器重載入之前被更新,因此下一個周期將是預期的值(計數器被裝載為新的值)。
以下是一些計數器在不同時鍾頻率下的操作的例子:

圖15 計數器時序圖,內部時鍾分頻因子為1 , TIMx_ARR=0x6

圖16 計數器時序圖,內部時鍾分頻因子為2

圖17 計數器時序圖,內部時鍾分頻因子為4, TIMx_ARR=0x36

圖18 計數器時序圖,內部時鍾分頻因子為N

圖19 計數器時序圖, ARPE=1 時的更新事件(計數器下溢)

圖20 計數器時序圖, ARPE=1 時的更新事件(計數器溢出)
計數器時鍾可由下列時鍾源提供:
● 內部時鍾(CK_INT)
● 外部時鍾模式1 :外部輸入腳(TIx)
● 外部時鍾模式2:外部觸發輸入(ETR)
● 內部觸發輸入(ITRx):使用一個定時器作為另一個定時器的預分頻器,如可以配置一個定時器Timer1 而作為另一個定時器Timer2的預分頻器。
3.3.1 內部時鍾源(CK_INT)
如果禁止了從模式控制器(TIMx_SMCR寄存器的SMS=000),則CEN、 DIR(TIMx_CR1 寄存器)和UG位(TIMx_EGR寄存器)是事實上的控制位,並且只能被軟件修改(UG位仍被自動清除)。只
要CEN位被寫成’1’,預分頻器的時鍾就由內部時鍾CK_INT提供。
下圖顯示了控制電路和向上計數器在一般模式下,不帶預分頻器時的操作。

圖21 一般模式下的控制電路,內部時鍾分頻因子為1
3.3.2 外部時鍾源模式1
當TIMx_SMCR寄存器的SMS=111 時,此模式被選中。計數器可以在選定輸入端的每個上升沿或下降沿計數。

圖22 TI2外部時鍾連接例子
例如,要配置向上計數器在T12輸入端的上升沿計數,使用下列步驟:
1. 配置TIMx_CCMR1 寄存器CC2S=’01’,配置通道2檢測TI2輸入的上升沿
2. 配置TIMx_CCMR1 寄存器的IC2F[3:0],選擇輸入濾波器帶寬(如果不需要濾波器,保持IC2F=0000)
注: 捕獲預分頻器不用作觸發,所以不需要對它進行配置
3. 配置TIMx_CCER寄存器的CC2P=’0’,選定上升沿極性
4. 配置TIMx_SMCR寄存器的SMS=’111’,選擇定時器外部時鍾模式1
5. 配置TIMx_SMCR寄存器中的TS=’110’,選定TI2作為觸發輸入源
6. 設置TIMx_CR1 寄存器的CEN=’1’,啟動計數器
當上升沿出現在TI2,計數器計數一次,且TIF標志被設置。在TI2的上升沿和計數器實際時鍾之間的延時,取決於在TI2輸入端的重新同步電路。

圖23 外部時鍾模式1 下的控制電路
3.3.3 外部時鍾源模式2
選定此模式的方法為:令TIMx_SMCR寄存器中的ECE=1
計數器能夠在外部觸發ETR的每一個上升沿或下降沿計數(下圖是外部觸發輸入的框圖)

圖24 外部觸發輸入框圖
例如,要配置在ETR下每2個上升沿計數一次的向上計數器,使用下列步驟:
1. 本例中不需要濾波器,置TIMx_SMCR寄存器中的ETF[3:0]=0000
2. 設置預分頻器,置TIMx_SMCR寄存器中的ETPS[1:0]=01
3. 設置在ETR的上升沿檢測,置TIMx_SMCR寄存器中的ETP=0
4. 開啟外部時鍾模式2,置TIMx_SMCR寄存器中的ECE=1
5. 啟動計數器,置TIMx_CR1 寄存器中的CEN=1
計數器在每2個ETR上升沿計數一次。
在ETR的上升沿和計數器實際時鍾之間的延時取決於在ETRP信號端的重新同步電路。

圖25 外部時鍾模式2下的控制電路
每一個捕獲/比較通道都是圍繞着一個捕獲/比較寄存器(包含影子寄存器),包括捕獲的輸入部分(數字濾波、多路復用和預分頻器),和輸出部分(比較器和輸出控制)。(下面幾張圖是一個捕獲/比較通道概覽。)
輸入部分對相應的TIx輸入信號采樣,並產生一個濾波后的信號TIxF。然后,一個帶極性選擇的邊緣檢測器產生一個信號(TIxFPx),它可以作為從模式控制器的輸入觸發或者作為捕獲控制。該信號通過預分頻進入捕獲寄存器(ICxPS)。

圖26 捕獲/比較通道(如:通道1 輸入部分)
輸出部分產生一個中間波形OCxRef(高有效)作為基准,鏈的末端決定最終輸出信號的極性。

圖27 捕獲/比較通道1 的主電路

圖28 捕獲/比較通道的輸出部分(通道1)
捕獲/比較模塊由一個預裝載寄存器和一個影子寄存器組成。讀寫過程僅操作預裝載寄存器。
在捕獲模式下,捕獲發生在影子寄存器上,然后再復制到預裝載寄存器中。
在比較模式下,預裝載寄存器的內容被復制到影子寄存器中,然后影子寄存器的內容和計數器進行比較。
在輸入捕獲模式下,當檢測到ICx信號上相應的邊沿后,計數器的當前值被鎖存到捕獲/比較寄存器(TIMx_CCRx)中。當捕獲事件發生時,相應的CCxIF標志(TIMx_SR寄存器)被置’1’,如果使能了中斷或者DMA操作,則將產生中斷或者DMA操作。如果捕獲事件發生時CCxIF標志已經為高,那么重復捕獲標志CCxOF(TIMx_SR寄存器)被置’1’。寫CCxIF=0可清除CCxIF,或讀取存儲在TIMx_CCRx寄存器中的捕獲數據也可清除CCxIF。寫CCxOF=0可清除CCxOF。
以下例子說明如何在TI1 輸入的上升沿時捕獲計數器的值到TIMx_CCR1 寄存器中,步驟如下:
● 選擇有效輸入端: TIMx_CCR1 必須連接到TI1 輸入,所以寫入TIMx_CCR1 寄存器中的CC1S=01 ,只要CC1S不為’00’,通道被配置為輸入,並且TM1_CCR1 寄存器變為只讀。
● 根據輸入信號的特點,配置輸入濾波器為所需的帶寬(即輸入為TIx時,輸入濾波器控制位是TIMx_CCMRx寄存器中的ICxF位)。假設輸入信號在最多5個內部時鍾周期的時間內抖動,我們須配置濾波器的帶寬長於5個時鍾周期。因此我們可以(以fDTS頻率)連續采樣8次,以確認在TI1 上一次真實的邊沿變換,即在TIMx_CCMR1 寄存器中寫入IC1F=0011 。
● 選擇TI1 通道的有效轉換邊沿,在TIMx_CCER寄存器中寫入CC1P=0(上升沿)。
● 配置輸入預分頻器。在本例中,我們希望捕獲發生在每一個有效的電平轉換時刻,因此預分頻器被禁止(寫TIMx_CCMR1 寄存器的IC1PS=00)。
● 設置TIMx_CCER寄存器的CC1E=1 ,允許捕獲計數器的值到捕獲寄存器中。
● 如果需要,通過設置TIMx_DIER寄存器中的CC1IE位允許相關中斷請求,通過設置TIMx_DIER寄存器中的CC1DE位允許DMA請求。
當發生一個輸入捕獲時:
● 產生有效的電平轉換時,計數器的值被傳送到TIMx_CCR1 寄存器。
● CC1IF標志被設置(中斷標志)。當發生至少2個連續的捕獲時,而CC1IF未曾被清除,CC1OF也被置’1’。
● 如設置了CC1IE位,則會產生一個中斷。
● 如設置了CC1DE位,則還會產生一個DMA請求。
為了處理捕獲溢出,建議在讀出捕獲溢出標志之前讀取數據,這是為了避免丟失在讀出捕獲溢出標志之后和讀取數據之前可能產生的捕獲溢出信息。
注:設置TIMx_EGR寄存器中相應的CCxG位,可以通過軟件產生輸入捕獲中斷和/或DMA請求。
3.6 PWM輸入模式
該模式是輸入捕獲模式的一個特例,除下列區別外,操作與輸入捕獲模式相同:
● 兩個ICx信號被映射至同一個TIx輸入。
● 這2個ICx信號為邊沿有效,但是極性相反。
● 其中一個TIxFP信號被作為觸發輸入信號,而從模式控制器被配置成復位模式。
例如,你需要測量輸入到TI1 上的PWM信號的長度(TIMx_CCR1 寄存器)和占空比(TIMx_CCR2寄存器),具體步驟如下(取決於CK_INT的頻率和預分頻器的值)
● 選擇TIMx_CCR1 的有效輸入:置TIMx_CCMR1 寄存器的CC1S=01(選擇TI1)。
● 選擇TI1FP1 的有效極性(用來捕獲數據到TIMx_CCR1 中和清除計數器):置CC1P=0(上升沿有效)。
● 選擇TIMx_CCR2的有效輸入:置TIMx_CCMR1 寄存器的CC2S=10(選擇TI1)。
● 選擇TI1FP2的有效極性(捕獲數據到TIMx_CCR2):置CC2P=1(下降沿有效)。
● 選擇有效的觸發輸入信號:置TIMx_SMCR寄存器中的TS=101(選擇TI1FP1)。
● 配置從模式控制器為復位模式:置TIMx_SMCR中的SMS=100。
● 使能捕獲:置TIMx_CCER寄存器中CC1E=1 且CC2E=1 。

圖29 PWM輸入模式時序
由於只有 TI1FP1 和 TI2FP2 連到了從模式控制器,所以 PWM 輸入模式只能使用 TIMx_CH1/TIMx_CH2信號。
在輸出模式(TIMx_CCMRx寄存器中 CCxS=00)下,輸出比較信號(OCxREF和相應的OCx)能夠直接由軟件強置為有效或無效狀態,而不依賴於輸出比較寄存器和計數器間的比較結果。
置TIMx_CCMRx寄存器中相應的OCxM=101 ,即可強置輸出比較信號(OCxREF/OCx)為有效狀態。這樣OCxREF被強置為高電平(OCxREF始終為高電平有效),同時OCx得到CCxP極性位相反的值。
例如: CCxP=0(OCx高電平有效),則OCx被強置為高電平。
置TIMx_CCMRx寄存器中的OCxM=100,可強置OCxREF信號為低。
該模式下,在TIMx_CCRx影子寄存器和計數器之間的比較仍然在進行,相應的標志也會被修改。因此仍然會產生相應的中斷和DMA請求。這將會在下面的輸出比較模式一節中介紹。
此項功能是用來控制一個輸出波形,或者指示一段給定的的時間已經到時。
當計數器與捕獲/比較寄存器的內容相同時,輸出比較功能做如下操作:
● 將輸出比較模式(TIMx_CCMRx寄存器中的OCxM位)和輸出極性(TIMx_CCER寄存器中的CCxP位)定義的值輸出到對應的引腳上。在比較匹配時,輸出引腳可以保持它的電平(OCxM=000)、被設置成有效電平(OCxM=001)、被設置成無效電平(OCxM=010)或進行翻轉(OCxM=011)。
● 設置中斷狀態寄存器中的標志位(TIMx_SR寄存器中的CCxIF位)。
● 若設置了相應的中斷屏蔽(TIMx_DIER寄存器中的CCxIE位),則產生一個中斷。
● 若設置了相應的使能位(TIMx_DIER寄存器中的CCxDE位, TIMx_CR2寄存器中的CCDS位選擇DMA請求功能),則產生一個DMA請求。
TIMx_CCMRx中的OCxPE位選擇TIMx_CCRx寄存器是否需要使用預裝載寄存器。
在輸出比較模式下,更新事件UEV對OCxREF和OCx輸出沒有影響。
同步的精度可以達到計數器的一個計數周期。輸出比較模式(在單脈沖模式下)也能用來輸出一個單脈沖。
輸出比較模式的配置步驟:
1. 選擇計數器時鍾(內部,外部,預分頻器)
2. 將相應的數據寫入TIMx_ARR和TIMx_CCRx寄存器中
3. 如果要產生一個中斷請求和/或一個DMA請求,設置CCxIE位和/或CCxDE位。
4. 選擇輸出模式,例如當計數器CNT與CCRx匹配時翻轉OCx的輸出引腳, CCRx預裝載未用,開啟 OCx輸出且高電平有效,則必須設置OCxM=’011’、 OCxPE=’0’、 CCxP=’0’和CCxE=’1’。
5. 設置TIMx_CR1 寄存器的CEN位啟動計數器
TIMx_CCRx寄存器能夠在任何時候通過軟件進行更新以控制輸出波形,條件是未使用預裝載寄存器(OCxPE=’0’,否則TIMx_CCRx影子寄存器只能在發生下一次更新事件時被更新)。下圖給
出了一個例子。

圖30 輸出比較模式,翻轉OC1
脈沖寬度調制模式可以產生一個由TIMx_ARR寄存器確定頻率、由TIMx_CCRx寄存器確定占空比的信號。
在TIMx_CCMRx寄存器中的OCxM位寫入’110’(PWM模式1)或’111’(PWM模式2),能夠獨立地設置每個OCx輸出通道產生一路PWM。必須設置TIMx_CCMRx寄存器OCxPE位以使能相應的預裝載寄存器,最后還要設置TIMx_CR1 寄存器的ARPE位, (在向上計數或中心對稱模式中)使能自動重裝載的預裝載寄存器。
僅當發生一個更新事件的時候,預裝載寄存器才能被傳送到影子寄存器,因此在計數器開始計數之前,必須通過設置TIMx_EGR寄存器中的UG位來初始化所有的寄存器。
OCx的極性可以通過軟件在TIMx_CCER寄存器中的CCxP位設置,它可以設置為高電平有效或低電平有效。 TIMx_CCER寄存器中的CCxE位控制OCx輸出使能。
在PWM模式(模式1 或模式2)下, TIMx_CNT和TIMx_CCRx始終在進行比較, (依據計數器的計數方向 ) 以確 定是否符合 TIMx_CCRx≤ TIMx_CNT 或者 TIMx_CNT ≤ TIMx_CCRx 。然而為了與
OCREF_CLR的功能(在下一個PWM周期之前,ETR信號上的一個外部事件能夠清除OCxREF)一致,OCxREF信號只能在下述條件下產生:
● 當比較的結果改變
● 當輸出比較模式(TIMx_CCMRx寄存器中的OCxM位)從“凍結” (無比較, OCxM=’000’)切換到某個PWM模式(OCxM=’110’或’111’)
這樣在運行中可以通過軟件強置PWM輸出。根據TIMx_CR1 寄存器中 CMS位的狀態,定時器能夠產生邊沿對齊的PWM信號或中央對齊的PWM信號。
>_<" PWM 邊沿對齊模式 (向上計數配置當TIMx_CR1 寄存器中的DIR位為低的時候執行向上計數。)
下面是一個PWM模式1 的例子。當TIMx_CNT<TIMx_CCRx時PWM信號參考OCxREF為高,否則為低。如果TIMx_CCRx中的比較值大於自動重裝載值(TIMx_ARR),則OCxREF保持為’1’。
如果比較值為0,則OCxREF保持為’0’。 下圖為TIMx_ARR=8時邊沿對齊的PWM波形實例。

圖31 邊沿對齊的PWM波形(ARR=8)
>_<" 向下計數的配置(當TIMx_CR1 寄存器的DIR位為高時執行向下計數。)
在PWM模式1,當TIMx_CNT>TIMx_CCRx時參考信號OCxREF為低,否則為高。如果TIMx_CCRx中的比較值大於TIMx_ARR中的自動重裝載值,則OCxREF保持為’1’。該模式下不能產生0%的PWM波形。
>_<" PWM 中央對齊模式(當TIMx_CR1 寄存器中的CMS位不為’00’時,為中央對齊模式(所有其他的配置對OCxREF/OCx信號都有相同的作用)。)
根據不同的CMS位設置,比較標志可以在計數器向上計數時被置’1’、在計數器向下計數時被置’1’、或在計數器向上和向下計數時被置’1’。 TIMx_CR1 寄存器中的計數方向位(DIR)由硬件更新,不要用軟件修改它。
● TIMx_ARR=8
● PWM模式1
● TIMx_CR1 寄存器中的CMS=01 ,在中央對齊模式1 時,當計數器向下計數時設置比較標志。

圖32 中央對齊的PWM波形(APR=8)
使用中央對齊模式的提示:
● 進入中央對齊模式時,使用當前的向上/向下計數配置;這就意味着計數器向上還是向下計數取決於TIMx_CR1 寄存器中DIR位的當前值。此外,軟件不能同時修改DIR和CMS位。
● 不推薦當運行在中央對齊模式時改寫計數器,因為這會產生不可預知的結果。特別地:
─ 如果寫入計數器的值大於自動重加載的值(TIMx_CNT>TIMx_ARR),則方向不會被更新。
例如,如果計數器正在向上計數,它就會繼續向上計數。
─ 如果將0或者TIMx_ARR的值寫入計數器,方向被更新,但不產生更新事件UEV。
● 使用中央對齊模式最保險的方法,就是在啟動計數器之前產生一個軟件更新(設置TIMx_EGR 位中的UG位),不要在計數進行過程中修改計數器的值。
單脈沖模式(OPM)是前述眾多模式的一個特例。這種模式允許計數器響應一個激勵,並在一個程序可控的延時之后,產生一個脈寬可程序控制的脈沖。
可以通過從模式控制器啟動計數器,在輸出比較模式或者PWM模式下產生波形。設置TIMx_CR1寄存器中的OPM位將選擇單脈沖模式,這樣可以讓計數器自動地在產生下一個更新事件UEV時停止。
僅當比較值與計數器的初始值不同時,才能產生一個脈沖。啟動之前(當定時器正在等待觸發),必須如下配置:
向上計數方式: CNT < CCRx ≤ ARR (特別地, 0 < CCRx)
向下計數方式: CNT > CCRx

圖33 單脈沖模式的例子
例如,你需要在從TI2輸入腳上檢測到一個上升沿開始,延遲tDELAY之后,在OC1 上產生一個長度為tPULSE的正脈沖。
4.1 使得PB5-TIM3通道2產生頻率為12.5Hz的方波,該方波控制LED1的閃爍
>_<" 主函數為:
1 int main(void) 2 { 3 RCC_Configuration(); //系統時鍾設置及外設時鍾使能 4 NVIC_Configuration(); //中斷源配置 5 time_ini(); //定時器3的初始化 6 while(1); 7 }
>_<" 配置各外設的時鍾和系統時鍾:(有些是多余的)
1 /**************************************************************************** 2 * 名 稱:void RCC_Configuration(void) 3 * 功 能:系統時鍾配置為72MHZ, 外設時鍾配置 4 ****************************************************************************/ 5 void RCC_Configuration(void){ 6 7 SystemInit(); 8 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); 9 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC 10 | RCC_APB2Periph_GPIOD| RCC_APB2Periph_GPIOE , ENABLE); 11 }
>_<" 配置中斷向量:(因為這里用到了TIM3,所以要配置其中斷向量)
1 /**************************************************************************** 2 * 名 稱:void NVIC_Configuration(void) 3 * 功 能:中斷源配置 4 ****************************************************************************/ 5 void NVIC_Configuration(void) 6 { 7 NVIC_InitTypeDef NVIC_InitStructure; 8 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); 9 10 NVIC_InitStructure.NVIC_IRQChannel =TIM3_IRQn ; //配置定時器中斷 11 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 12 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 13 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 14 NVIC_Init(&NVIC_InitStructure); 15 }
>_<" TIM3的2通道配置:(下面首先配置GPIO PB5(為Tim3的2通道),PB5引腳默認是作為通用IO口使用,為了產生特定頻率,利用了該引腳可以復用為TIM3_CH2,根據手冊,需要用到局部復用映射,才能將TIM3_CH2映射到PB5。)

在定時器3的初始化中,用到了輸出比較2模式的翻轉設置。也就是當TIM3_CCR2=TIM3_CNT時,翻轉輸出的電平。以產生需要的頻率,TIM3_CCR2的值決定了翻轉的頻率。當TIM3_CCR2=TIM3_CNT時,產生一次電平翻轉,並在中斷服務程序里重新完成對TIM3_CCR2的裝載。依次往復,產生了所需要的12.5Hz的頻率。(注意注釋的第15~17行介紹如何控制輸出頻率,CCR2_Val=45000)
1 void time_ini(void){ 2 GPIO_InitTypeDef GPIO_InitStructure; 3 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //定時器3 時鍾使能 4 5 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //PB5復用為TIM3的通道2 6 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 7 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 8 GPIO_Init(GPIOB, &GPIO_InitStructure); 9 10 /* TIM3局部復用功能開啟 在TIM3的局部復用開啟時,PB5會被復用為TIM3_CH2*/ 11 GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3 , ENABLE); 12 13 /* Time Base configuration */ 14 /*------------------------------------------------------------------- 15 TIM3CLK=72MHz 預分頻系數Prescaler=63 經過分頻 定時器時鍾為1.125MHz 16 捕獲/比較寄存器2 TIM3_CCR2= CCR2_Val 17 2通道產生的更新頻率是=1.125MHz/CCR2_Val=25Hz 18 19 -------------------------------------------------------------------*/ 20 TIM3_TimeBaseStructure.TIM_Prescaler = 63; //預分頻器TIM3_PSC=63 21 TIM3_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //計數器向上計數模式 TIM3_CR1[4]=0 22 TIM3_TimeBaseStructure.TIM_Period =0xffff; //自動重裝載寄存器TIM3_APR 23 TIM3_TimeBaseStructure.TIM_ClockDivision = 0x0; //時鍾分頻因子 TIM3_CR1[9:8]=00 24 25 TIM_TimeBaseInit(TIM3,&TIM3_TimeBaseStructure); //寫TIM3各寄存器參數 26 27 TIM3_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle ; //TIM3_CCMR1[14:12]=011 翻轉 當TIM3_CCR2=TIM3_CNT時,翻轉OC2REF的電平 28 TIM3_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //輸入/捕獲2輸出允許 OC2信號輸出到對應的輸出引腳PB5 29 TIM3_OCInitStructure.TIM_Pulse =CCR2_Val; //若CC1通道配置為輸出:CCR2是裝入當前捕獲/比較2 TIM3_CCR2寄存器的值(預裝載值)。 30 //當前捕獲/比較寄存器包含了與計數器TIM3_CNT比較的值,並且在OC端口上輸出信號 31 TIM3_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //輸出極性 低電平有效 TIM3_CCER[5]=1; 32 33 TIM_OC2Init(TIM3, &TIM3_OCInitStructure); 34 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Disable); //TIM3_CCMR1[1]=0 禁止TIM3_CCR2寄存器的預裝載功能,可隨時寫入TIM3_CCR2 35 //且新值馬上起作用 36 37 TIM_Cmd(TIM3,ENABLE); //啟動定時器3 TIM3_CR1[0]=1; 38 TIM_ITConfig(TIM3,TIM_IT_CC2,ENABLE); //TIM3_DIER[2]=1 允許捕獲/比較2中斷 39 }
>_<" TIM3的中斷服務子程序(每次TIM3_CCR2=TIM3_CNT產生一次中斷,在中斷子程序中取出上一次的TIM3_CCR2加上CCR2_Val作為新的TIM3_CCR2,這樣等TIM3_CNT加到和TIM3_CCR2相等時又會觸發一次中斷)
1 void TIM3_IRQHandler(void) 2 { 3 4 if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET) //判斷狀態寄存器 TIM3_SR[2] 是否發生了捕獲/比較2 中斷 5 { 6 TIM_ClearITPendingBit(TIM3, TIM_IT_CC2); //軟件清除狀態寄存器 TIM3_SR[2] 捕獲/比較2 中斷中斷標志 7 8 capture1 = TIM_GetCapture2(TIM3); //獲取TIM3_CCR2的預裝值 9 TIM_SetCompare2(TIM3, capture1+ CCR2_Val); //和CCR2_Val累加后裝入TIM3_CCR2 這是為了配合計數器值的遞增。以在下一次作出比較。 10 11 } 12 }
4.2 周期控制通用定時器3的2通道,實現1KHz的不同占空比波形,控制LED實現呼吸燈
>_<" 主函數為:(不同於上面固定的頻率定時方法,這里在while里不斷更改CCR2_Val的值來改變占空比)
1 int main(void) 2 { 3 unsigned char a=0; 4 TIM_OCInitTypeDef TIM3_OCInitStructure; 5 RCC_Configuration(); 6 time_ini(); 7 SysTick_Config(72000); //配置SYSTICK時鍾節拍為1ms一次 8 while(1){ 9 Delay(1); //延時1ms 10 TIM3_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //PWM模式2 11 TIM3_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //輸出禁止 12 TIM3_OCInitStructure.TIM_Pulse = CCR2_Val; //確定占空比 13 TIM3_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; 14 TIM_OC2Init(TIM3, &TIM3_OCInitStructure); 15 16 /*調整CCR2_Val的值來改變占空比,逐步的控制LED1的亮度, 占空比大過一定值時, 17 亮度的變化就不明顯了,所以CCR2_VAL最大設定到17000*/ 18 if(a==0) CCR2_Val=CCR2_Val+10; 19 else CCR2_Val=CCR2_Val-10; 20 if(CCR2_Val>17000){ CCR2_Val=17000; a=1;} 21 else if(CCR2_Val<200){ CCR2_Val=200; a=0;} 22 } 23 }
>_<" 配置各外設的時鍾和系統時鍾:(同4.1有些是多余的)
1 /**************************************************************************** 2 * 名 稱:void RCC_Configuration(void) 3 * 功 能:系統時鍾配置為72MHZ, 外設時鍾配置 4 ****************************************************************************/ 5 void RCC_Configuration(void){ 6 7 SystemInit(); 8 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); 9 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC 10 | RCC_APB2Periph_GPIOD| RCC_APB2Periph_GPIOE , ENABLE); 11 }
>_<" TIM3的2通道配置:(注意,這里沒有用到中斷向量和中斷子程序!!!下面首先配置GPIO PB5(為Tim3的2通道),PB5引腳默認是作為通用IO口使用,為了產生特定頻率,利用了該引腳可以復用為TIM3_CH2,根據手冊,需要用到局部復用映射,才能將TIM3_CH2映射到PB5。)

由於TIM3計數器的時鍾頻率是72MHz,希望各通道輸出頻率為1KHZ,根據3倍預分頻后,時鍾頻率為24MHz,根據公式ftim3=TIM3CLK/(TIM3_Period+1),可得到TIM3預分頻的值為24000, 根據公式根據公式 通道輸出占空比=TIM3_CCR2/(TIM_Period+1),可以得到TIM_Pulse的計數值,逐步改變這個值,可以控制占空比, 從而獲得LED1 亮度明暗漸變的效果。(所以在main函數的while中不斷重置CCR2_Val值來控制不同占空比)
1 /**************************************************************************** 2 * 名 稱:void time_ini(void) 3 * 功 能:TIM3初始化 4 ****************************************************************************/ 5 void time_ini(void){ 6 GPIO_InitTypeDef GPIO_InitStructure; 7 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); 8 9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //PB5復用為TIM3的通道2 10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 11 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 12 GPIO_Init(GPIOB, &GPIO_InitStructure); 13 /*TIM3局部復用功能開啟 在TIM3的局部復用開啟時,PB5會被復用為TIM3_CH2*/ 14 GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3 , ENABLE); 15 16 /*------------------------------------------------------------------- 17 TIM3CLK=72MHz 預分頻系數Prescaler=2 經過分頻 定時器時鍾為24MHz 18 根據公式 通道輸出占空比=TIM3_CCR2/(TIM_Period+1),可以得到TIM_Pulse的計數值 19 捕獲/比較寄存器2 TIM3_CCR2= CCR2_Val 20 -------------------------------------------------------------------*/ 21 TIM3_TimeBaseStructure.TIM_Prescaler = 2; //預分頻器TIM3_PSC=3 22 TIM3_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //計數器向上計數模式 TIM3_CR1[4]=0 23 TIM3_TimeBaseStructure.TIM_Period =24000; //自動重裝載寄存器TIM3_APR 確定頻率為1KHz 24 TIM3_TimeBaseStructure.TIM_ClockDivision = 0x0; //時鍾分頻因子 TIM3_CR1[9:8]=00 25 TIM3_TimeBaseStructure.TIM_RepetitionCounter = 0x0; 26 27 TIM_TimeBaseInit(TIM3,&TIM3_TimeBaseStructure); //寫TIM3各寄存器參數 28 29 TIM3_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //PWM模式2 TIM3_CCMR1[14:12]=111 在向上計數時, 30 //一旦TIMx_CNT<TIMx_CCR1時通道1為無效電平,否則為有效電平 31 TIM3_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //輸入/捕獲2輸出允許 OC2信號輸出到對應的輸出引腳PB5 32 TIM3_OCInitStructure.TIM_Pulse = CCR2_Val; //確定占空比,這個值決定了有效電平的時間。 33 TIM3_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //輸出極性 低電平有效 TIM3_CCER[5]=1; 34 35 TIM_OC2Init(TIM3, &TIM3_OCInitStructure); 36 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); 37 TIM_Cmd(TIM3,ENABLE); //啟動定時器3 TIM3_CR1[0]=1; 38 }
本文正版鏈接:http://www.cnblogs.com/zjutlitao/p/4652695.html
工程4.1 TIM3-CH2鏈接:http://pan.baidu.com/s/1c0dLgAW
工程4.2 TIM3-PWM鏈接: http://pan.baidu.com/s/1dDjiMnn
上述兩個工程的說明(建議直接看我博客):http://pan.baidu.com/s/1ntkoym9
stm32幾個重要的文件:http://pan.baidu.com/s/1qW41bw4
