單片機(jī)開發(fā)中,電機(jī)的控制與定時(shí)器有著密不可分的關(guān)系,無論是直流電機(jī),步進(jìn)電機(jī)還是舵機(jī),都會(huì)用到定時(shí)器,比如最常用的有刷直流電機(jī),會(huì)使用定時(shí)器產(chǎn)生PWM波來調(diào)節(jié)轉(zhuǎn)速,通過定時(shí)器的正交編碼器接口來測量轉(zhuǎn)速等。
本篇先介紹定時(shí)器的基礎(chǔ)知識(shí),然后對照這些知識(shí)介紹一下定時(shí)器輸出PWM的基本原理,以及編程實(shí)現(xiàn)與代碼分析。
首先來看一下定時(shí)器的基礎(chǔ)介紹。
11 定時(shí)器基礎(chǔ)知識(shí)
1.1 定時(shí)器種類
以STM32F4為例,一共有14個(gè)定時(shí)器:
高級定時(shí)器(TIM1、TIM8)
通用定時(shí)器(TIM2~TIM5,TIM9~TIM14)
TIM2~TIM5(通用定時(shí)器里功能較多的)
TIM9/TIM12
TIM10/TIM11和TIM13/TIM14
基本定時(shí)器 (TIM6、TIM7)
1.2 各種定時(shí)器的特性
1.2.1 高級定時(shí)器與通用定時(shí)器
這里列舉高級定時(shí)器的特性,在此基礎(chǔ)上,對比添加其與通用定時(shí)器的不同之處:
16 位遞增、遞減、遞增/遞減自動(dòng)重載計(jì)數(shù)器(TIM2 和 TIM5為32位)
16 位可編程預(yù)分頻器,用于對計(jì)數(shù)器時(shí)鐘頻率進(jìn)行分頻(即運(yùn)行時(shí)修改),分頻系數(shù)介于 1 到 65536 之間。
多達(dá) 4 個(gè)獨(dú)立通道(TIM9/TIM12有2個(gè),TIM10/TIM11,TIM13/TIM14只有1個(gè)),可用于:
輸入捕獲
輸出比較
PWM 生成(邊沿和中心對齊模式)(高級定時(shí)器和TIM2~TIM5特有,其它是只有邊沿對齊模式)
單脈沖模式輸出
帶可編程死區(qū)的互補(bǔ)輸出(高級定時(shí)器特有)。
使用外部信號控制定時(shí)器且可實(shí)現(xiàn)多個(gè)定時(shí)器互連的同步電路(TIM10/TIM11,TIM13/TIM14沒有)。
重復(fù)計(jì)數(shù)器,用于僅在給定數(shù)目的計(jì)數(shù)器周期后更新定時(shí)器寄存器(高級定時(shí)器特有)。
用于將定時(shí)器的輸出信號置于復(fù)位狀態(tài)或已知狀態(tài)的斷路輸入(高級定時(shí)器特有)。
發(fā)生如下事件時(shí)生成中斷/DMA 請求:
更新:計(jì)數(shù)器上溢/下溢、計(jì)數(shù)器初始化(通過軟件或內(nèi)部/外部觸發(fā))
觸發(fā)事件(計(jì)數(shù)器啟動(dòng)、停止、初始化或通過內(nèi)部/外部觸發(fā)計(jì)數(shù))(TIM10/TIM11和TIM13/TIM14沒有此功能)
輸入捕獲
輸出比較
斷路輸入(高級定時(shí)器特有)
支持定位用增量(正交)編碼器和霍爾傳感器電路(高級定時(shí)器和TIM2~TIM5特有)。
外部時(shí)鐘觸發(fā)輸入或逐周期電流管理(高級定時(shí)器和TIM2~TIM5特有)。
1.2.2 基本定時(shí)器
基本定時(shí)器 (TIM6、TIM7)的功能比較單一,所具有的功能如下:
16 位自動(dòng)重載遞增計(jì)數(shù)器
只能定時(shí),沒有外部 IO
16 位可編程預(yù)分頻器,用于對計(jì)數(shù)器時(shí)鐘頻率進(jìn)行分頻(即運(yùn)行時(shí)修改),分頻系數(shù)介于 1 和 65536 之間
用于觸發(fā) DAC 的同步電路
發(fā)生如下更新事件時(shí)會(huì)生成中斷/DMA 請求:計(jì)數(shù)器上溢
1.3 定時(shí)器使用配置
使用定時(shí)器,一般需要配置如下:
時(shí)基:也就是計(jì)數(shù)器的計(jì)數(shù)時(shí)鐘
自動(dòng)重裝載值:每次計(jì)數(shù)的最大值
輸出通道:當(dāng)需要使用定時(shí)器輸出某種波形時(shí)(如PWM)
輸入通道:當(dāng)需要使用定時(shí)器接收某種波形時(shí)(如電機(jī)編碼器信號)
先來看一下定時(shí)器的原理框圖,對定時(shí)器的內(nèi)部原理有一個(gè)整體直觀的感受:
1.3.1 時(shí)鐘源
從上圖可以看出,計(jì)數(shù)器的時(shí)鐘源可以為:
由RCC的內(nèi)部時(shí)鐘分頻得到
由定時(shí)器的TIMx_ETR引腳得到
由其他定時(shí)器通過TRGO輸出得到
一般使用RCC的內(nèi)部時(shí)鐘CK_INT,也即定時(shí)器時(shí)鐘TIMxCLK,經(jīng)APB1或APB2預(yù)分頻器后分頻提供。
關(guān)于定時(shí)器時(shí)鐘源的具體細(xì)節(jié),可以來看一下STM32F4的時(shí)鐘樹:
從STM32F4的內(nèi)部時(shí)鐘樹可知:
高級定時(shí)器timer1, timer8以及通用定時(shí)器timer9, timer10, timer11的時(shí)鐘來源是APB2總線(84MHZ)
通用定時(shí)器timer2~timer5,通用定時(shí)器timer12~timer14以及基本定時(shí)器timer6,timer7的時(shí)鐘來源是APB1總線(42MHZ)
另外:
當(dāng)APB1和APB2分頻數(shù)為1的時(shí)候,各定時(shí)器的時(shí)鐘就是對應(yīng)的APB1或APB2的時(shí)鐘;
如果APB1和APB2分頻數(shù)不為1,那么各定時(shí)器的時(shí)鐘就是對應(yīng)的APB1或APB2的時(shí)鐘的2倍;
由于庫函數(shù)中 APB1 預(yù)分頻的系數(shù)默認(rèn)是 2,所以,所以TIM1、TIM8~TIM11的時(shí)鐘為APB2時(shí)鐘的兩倍即168MHz,TIM2~TIM7、TIM12~TIM14的時(shí)鐘為APB1的時(shí)鐘的兩倍即84MHz。
1.3.2 計(jì)數(shù)器時(shí)鐘
由于定時(shí)器時(shí)鐘的提供的可以頻率較高,計(jì)數(shù)器不需要這么高的頻率來計(jì)數(shù),所以會(huì)進(jìn)行降頻,使用一個(gè)合適的低頻時(shí)鐘來計(jì)數(shù)。
定時(shí)器時(shí)鐘經(jīng)過PSC 預(yù)分頻器之后,即 CK_CNT,用來驅(qū)動(dòng)計(jì)數(shù)器計(jì)數(shù)。PSC 是一個(gè)16 位的預(yù)分頻器,可以對定時(shí)器時(shí)鐘TIMxCLK 進(jìn)行 1~65536 之間的任何一個(gè)數(shù)進(jìn)行分頻。
具體計(jì)算方式為:CK_CNT=TIMxCLK/(PSC+1)。
比如,使用STM32F4的通用定時(shí)器2(TIM2CLK為APB1的時(shí)鐘的兩倍即84MHz),PSC設(shè)置為83,則計(jì)數(shù)時(shí)鐘為84MHz/(83+1)=1MHz,即1ms計(jì)一個(gè)數(shù)。
1.3.3 計(jì)數(shù)器
計(jì)數(shù)器 CNT 是一個(gè) 16 位的計(jì)數(shù)器,只能往上計(jì)數(shù),最大計(jì)數(shù)值為 65535。當(dāng)計(jì)數(shù)達(dá)到自動(dòng)重裝載寄存器的時(shí)候產(chǎn)生更新事件,并清零從頭開始計(jì)數(shù)。
1.3.4 自動(dòng)重裝載寄存器
自動(dòng)重裝載寄存器 ARR 是一個(gè) 16 位的寄存器,這里面裝著計(jì)數(shù)器能計(jì)數(shù)的最大數(shù)值。當(dāng)計(jì)數(shù)到這個(gè)值的時(shí)候,如果使能了中斷的,定時(shí)器就產(chǎn)生溢出中斷。
2定時(shí)器輸出PWM原理
如下圖是PWM輸出的原理示意圖:
假設(shè)定時(shí)器工作模式設(shè)置為向上計(jì)數(shù) PWM模式,且當(dāng) CNT《CCRx 時(shí),輸出 1,當(dāng) CNT》=CCRx 時(shí)輸出 0,則:
當(dāng) CNT 值小于 CCRx 的時(shí)候, IO 輸出高電平 (1)
當(dāng) CNT 值大于等于 CCRx 的時(shí)候,IO 輸出低電平 (0)
當(dāng) CNT 達(dá)到 ARR 值的時(shí)候,重新歸零,然后重新向上計(jì)數(shù),依次循環(huán)。
因此,改變 CCRx 的值,就可以改變 PWM 輸出的占空比,改變 ARR 的值,就可以改變 PWM 輸出的周期(頻率),這就是利用定時(shí)器輸出PWM 的基本原理。
3定時(shí)器常用的寄存器
使用定時(shí)器來輸出PWM時(shí),需要對其寄存器進(jìn)行相應(yīng)的設(shè)置。定時(shí)器的寄存器有好多個(gè),這里先介紹幾個(gè)與輸出PWM相關(guān)的幾個(gè)寄存器,其它是寄存器以后用到時(shí)再介紹。
3.1 控制寄存器CR1
控制寄存器,就是來設(shè)置定時(shí)的工作模式:
位 15:10 保留,必須保持復(fù)位值。
位 9:8 CKD:時(shí)鐘分頻 (Clock division)此位域指示定時(shí)器時(shí)鐘 (CK_INT) 頻率與數(shù)字濾波器所使用的采樣時(shí)鐘(ETR、TIx)之間的分頻比,
位 7 ARPE:自動(dòng)重載預(yù)裝載使能 (Auto-reload preload enable)
0:TIMx_ARR 寄存器不進(jìn)行緩沖
1:TIMx_ARR 寄存器進(jìn)行緩沖
位 6:5 CMS:中心對齊模式選擇 (Center-aligned mode selection),包括1種邊沿對齊模式與3種中心對齊模式
位 4 DIR:計(jì)數(shù)器方向 (Direction),0為遞增計(jì)數(shù),1為遞減計(jì)數(shù)。
注:當(dāng)定時(shí)器配置為中心對齊模式或編碼器模式時(shí),該位為只讀狀態(tài)。
位 3 OPM:單脈沖模式 (One-pulse mode)
位 2 URS:更新請求源 (Update request source)
此位由軟件置 1 和清零,用以選擇 UEV 事件源。
位 1 UDIS:更新禁止 (Update disable)此位由軟件置 1 和清零,用以使能/禁止 UEV 事件生成。
位 0 CEN:計(jì)數(shù)器使能 (Counter enable),0為禁止計(jì)數(shù)器,1為使能計(jì)數(shù)器
只有事先通過軟件將 CEN 位置 1,才可以使用外部時(shí)鐘、門控模式和編碼器模式。而觸發(fā)模式可通過硬件自動(dòng)將 CEN 位置 1。在單脈沖模式下,當(dāng)發(fā)生更新事件時(shí)會(huì)自動(dòng)將 CEN 位清零。
3.2 捕獲/比較模式寄存器CCMR1
這些通道可用于輸入(捕獲模式)或輸出(比較模式)模式。通道方向通過配置相應(yīng)的 CCxS 位進(jìn)行定義。此寄存器的所有其它位在輸入模式和輸出模式下的功能均不同。對于任一給定位
OCxx 用于說明通道配置為輸出時(shí)該位對應(yīng)的功能
ICxx 則用于說明通道配置為輸入時(shí) 該位對應(yīng)的功能
因此,必須注意同一個(gè)位在輸入階段和輸出階段具有不同的含義。
這里僅先介紹輸出模式下的功能:
位 15 OC2CE:輸出比較 2 清零使能 (Output compare 3 clear enable)
位 14:12 OC2M[2:0]:輸出比較 2 模式 (Output compare 2 mode)
位 11 OC2PE:輸出比較 2 預(yù)裝載使能 (Output compare 2 preload enable)
位 10 OC2FE:輸出比較 2 快速使能 (Output compare 2 fast enable)
位 9:8 CC2S[1:0]:捕獲/比較 2 選擇 (Capture/Compare 2 selection)參考下面的CC1S通道1
位 7 OC1CE:輸出比較 1 清零使能 (Output compare 3 clear enable)
OC1CE:輸出比較 1 清零使能 (Output Compare 1 Clear Enable)
0:OC1Ref 不受 ETRF 輸入影響
1:ETRF 輸入上檢測到高電平時(shí), OC1Ref 立即清零。
位 6:4 OC1M:輸出比較 1 模式 (Output compare 1 mode)一共可配置位7種模式,這里僅介紹2種:
110:PWM 模式 1––在遞增計(jì)數(shù)模式下,只要 TIMx_CNT《TIMx_CCR1,通道 1 便為有效狀態(tài),否則為無效狀態(tài)。在遞減計(jì)數(shù)模式下,只要 TIMx_CNT》TIMx_CCR1,通道 1 便為無效狀態(tài) (OC1REF=0),否則為有效狀態(tài) (OC1REF=1)。
111:PPWM 模式 2––在遞增計(jì)數(shù)模式下,只要 TIMx_CNT《TIMx_CCR1,通道 1 便為無效狀態(tài),否則為有效狀態(tài)。在遞減計(jì)數(shù)模式下,只要 TIMx_CNT》TIMx_CCR1,通道 1 便為有效狀態(tài),否則為無效狀態(tài)。
位 3 OC1PE:輸出比較 1 預(yù)裝載使能 (Output compare 1 preload enable)
0:禁止與 TIMx_CCR1 相關(guān)的預(yù)裝載寄存器。可隨時(shí)向 TIMx_CCR1 寫入數(shù)據(jù),寫入后將立即使用新值。
1:使能與 TIMx_CCR1 相關(guān)的預(yù)裝載寄存器。可讀/寫訪問預(yù)裝載寄存器。TIMx_CCR1 預(yù)裝載值在每次生成更新事件時(shí)都會(huì)裝載到活動(dòng)寄存器中。
位 2 OC1FE:輸出比較 1 快速使能 (Output compare 1 fast enable)
此位用于加快觸發(fā)輸入事件對 CC 輸出的影響(僅當(dāng)通道配置為 PWM1 或 PWM2 模式時(shí),OCFE 才會(huì)起作用)。
0:即使觸發(fā)開啟,CC1 也將根據(jù)計(jì)數(shù)器和 CCR1 值正常工作。觸發(fā)輸入出現(xiàn)邊沿時(shí),激活CC1 輸出的最短延遲時(shí)間為 5 個(gè)時(shí)鐘周期。
1:觸發(fā)輸入上出現(xiàn)有效邊沿相當(dāng)于 CC1 輸出上的比較匹配。隨后,無論比較結(jié)果如何,OC 都設(shè)置為比較電平。采樣觸發(fā)輸入和激活 CC1 輸出的延遲時(shí)間縮短為 3 個(gè)時(shí)鐘周期。
位 1:0 CC1S[1:0]:捕獲/比較 1 選擇 (Capture/Compare 1 selection)
此位域定義通道方向(輸入/輸出)以及所使用的輸入。
00:CC1 通道配置為輸出。
01:CC1 通道配置為輸入,IC1 映射到 TI1 上。
10:CC1 通道配置為輸入,IC1 映射到 TI2 上。
11:CC1 通道配置為輸入,IC1 映射到 TRC 上。此模式僅在通過 TS 位(TIMx_SMCR 寄存器)選擇內(nèi)部觸發(fā)輸入時(shí)有效
注:僅當(dāng)通道關(guān)閉時(shí)(TIMx_CCER 中的 CC1E = 0),才可向 CC1S 位寫入數(shù)據(jù)。
3.3 計(jì)數(shù)器CNT
計(jì)數(shù)器的功能很單一,就是計(jì)數(shù):
位 15:0 CNT[15:0]:計(jì)數(shù)器值 (Counter value)
3.4 預(yù)分頻器PSC
預(yù)分頻器的功能也很單一,就是分頻:
位 15:0 PSC[15:0]:預(yù)分頻器值 (Prescaler value)
計(jì)數(shù)器時(shí)鐘頻率 CK_CNT 等于 fCK_PSC / (PSC[15:0] + 1)。
PSC 包含在每次發(fā)生更新事件時(shí)要裝載到實(shí)際預(yù)分頻器寄存器的值。
3.5 自動(dòng)重裝載寄存器ARR
自動(dòng)重裝載寄存器的功能也很單一,就是保存一個(gè)數(shù),在計(jì)數(shù)滿的時(shí)候,重新開始計(jì)數(shù)
位 15:0 ARR[15:0]:自動(dòng)重載值 (Auto-reload value)
ARR 為要裝載到實(shí)際自動(dòng)重載寄存器的值。
當(dāng)自動(dòng)重載值為空時(shí),計(jì)數(shù)器不工作。
3.6 捕獲/比較寄存器CCR
自動(dòng)重裝載寄存器的功能也很單一,也是保存一個(gè)數(shù),用于與當(dāng)前的CNT進(jìn)行比較,注意 TIM2 和 TIM5是32位計(jì)數(shù)。
以CCR1寄存器(一共有CCR1~CCR4這4個(gè)通道)為例:
位31:16 CCR1[31:16]:捕獲/比較 1 的高 16 位(對于 TIM2 和 TIM5)。
位15:0 CCR1[15:0]:捕獲/比較 1 的低 16 位 (Low Capture/Compare 1 value)
如果通道 CC1 配置為輸出:CCR1 是捕獲/比較寄存器 1 的預(yù)裝載值。如果沒有通過 TIMx_CCMR寄存器中的OC1PE 位來使能預(yù)裝載功能,寫入的數(shù)值會(huì)被直接傳輸至當(dāng)前寄存器中。否則只在發(fā)生更新事件時(shí)生效(拷貝到實(shí)際起作用的捕獲/ 比較寄存器1)。實(shí)際捕獲/比較寄存器中包含要與計(jì)數(shù)器 TIMx_CNT進(jìn)行比較并在 OC1 輸出上發(fā)出信號的值。
如果通道 CC1 配置為輸入:CCR1 為上一個(gè)輸入捕獲 1 事件 (IC1) 發(fā)生時(shí)的計(jì)數(shù)器值。
44代碼實(shí)現(xiàn)與分析
上面介紹了定時(shí)器的基礎(chǔ)知識(shí)與PWM的輸出原理,下面就來實(shí)際看一下,如何編寫對應(yīng)的代碼(以STM32F407為例)。
4.1 定時(shí)器初始化
定時(shí)器的初始化,因?yàn)樾枰玫綄?yīng)的引腳輸出PWM,因此要先初始化GPIO引腳,然后,還要初始化定時(shí)器的時(shí)基(計(jì)數(shù)的時(shí)鐘)以及輸出通道(用于配置PWM的輸出模式)。
4.1.1 復(fù)用引腳初始化
這里用到的是定時(shí)器3,根據(jù)STM32F407的數(shù)據(jù)手冊“3 Pinouts and pin description”中的“Table 9. Alternate function mapping”復(fù)用引腳說明表,可以看到定時(shí)器3通道1對應(yīng)的引腳位A6:
因此程序中對A6引腳可以這樣配置,注意一定要配置引腳的復(fù)用功能:
GPIO_InitTypeDef GPIO_InitStructure; /*引腳配置 結(jié)構(gòu)體*/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能PORTA時(shí)鐘GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_TIM3); /*GPIOA6復(fù)用為定時(shí)器3*/
/*復(fù)用引腳配置*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //GPIOA6GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; /*復(fù)用功能*/GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHzGPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽復(fù)用輸出GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA6
4.1.2 時(shí)基初始化
時(shí)基初始化,主要是配置定時(shí)器的計(jì)數(shù)頻率(psc)和自動(dòng)重裝置值(每次計(jì)數(shù)的周期,arr),比如TIM3_PWM_Init(500-1,84-1);
(關(guān)于psc與arr的知識(shí)點(diǎn),可以再回顧一下上面1.3節(jié)的知識(shí))
這里將arr的值設(shè)置為500,即計(jì)數(shù)器每計(jì)夠500個(gè)數(shù)就會(huì)重新從0開始計(jì)數(shù),這個(gè)500再乘以計(jì)數(shù)器計(jì)數(shù)的周期,就是PWM真正的周期,那計(jì)數(shù)器計(jì)數(shù)的頻率是多少呢(頻率的倒數(shù)為周期)?
這里將psc的值設(shè)置為84-1,即TIM3的輸入頻率為84MHz再將頻率降低1/84,即使用1MHz的頻率計(jì)數(shù)(1s能計(jì)1,000,000個(gè)數(shù),也即1us計(jì)1個(gè)數(shù)),那么PWM的真正周期就是500*1us=500us(0.5ms),通過改變占空比的值(ccr),就可以調(diào)節(jié)PWM的輸出占空比。
時(shí)基初始化配置如下:
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; /*時(shí)基 結(jié)構(gòu)體*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //TIM3時(shí)鐘使能
/*時(shí)基初始化*/TIM_TimeBaseStructure.TIM_Period=arr; /*ARR 自動(dòng)重裝載值(周期),例如500*/TIM_TimeBaseStructure.TIM_Prescaler=psc; /*PSC 定時(shí)器分頻,例如84*/TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; /*時(shí)鐘分割*/TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; /*向上計(jì)數(shù)模式*/TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure); /*初始化定時(shí)器3*/
最后一句的時(shí)基初始化,起始就是對定時(shí)的寄存器進(jìn)行配置,該函數(shù)的內(nèi)部實(shí)現(xiàn)如下:
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct){ uint16_t tmpcr1 = 0; tmpcr1 = TIMx-》CR1;
if((TIMx == TIM1) || (TIMx == TIM8)|| /*高級定時(shí)器TIM和TIM8*/ (TIMx == TIM2) || (TIMx == TIM3)||(TIMx == TIM4) || (TIMx == TIM5)) /*通用定時(shí)器中的TIM2~TIM5*/ { /* 設(shè)置為計(jì)數(shù)器模式 */ tmpcr1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS)); tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct-》TIM_CounterMode; } if((TIMx != TIM6) && (TIMx != TIM7)) /*基本定時(shí)器TIM6和TIM7無此功能*/ { /* 設(shè)置時(shí)鐘分頻 */ tmpcr1 &= (uint16_t)(~TIM_CR1_CKD); tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct-》TIM_ClockDivision; }
/* 配置CR1寄存器 */ TIMx-》CR1 = tmpcr1;
/* 配置ARR寄存器,設(shè)置自動(dòng)重轉(zhuǎn)載值 */ TIMx-》ARR = TIM_TimeBaseInitStruct-》TIM_Period ; /* 配置PSC寄存器,設(shè)置預(yù)分頻值 */ TIMx-》PSC = TIM_TimeBaseInitStruct-》TIM_Prescaler; if ((TIMx == TIM1) || (TIMx == TIM8)) /*高級定時(shí)器TIM和TIM8*/ { /* 配置RCR寄存器,設(shè)置重復(fù)計(jì)數(shù)值 */ TIMx-》RCR = TIM_TimeBaseInitStruct-》TIM_RepetitionCounter; }
/* 生成一個(gè)更新事件來立即重新加載預(yù)分頻器和重復(fù)計(jì)數(shù)器(僅針對高級定時(shí)器TIM1和TIM8)值 */ TIMx-》EGR = TIM_PSCReloadMode_Immediate; }
4.1.3 輸出通道初始化
輸出通道初始化,主要是配置輸出的一些參數(shù),這里主要關(guān)注TIM_OCMode(模式)與TIM_OCPolarity(極性),這兩個(gè)參數(shù)是配合使用的:
PWM模式1
向上計(jì)數(shù)時(shí),一旦TIMx_CNT《TIMx_CCR1時(shí)通道1為有效電平,否則為無效電平;
向下計(jì)數(shù)時(shí),一旦TIMx_CNT》TIMx_CCR1時(shí)通道1為無效電平,否則為有效電平。
PWM模式2
向上計(jì)數(shù)時(shí),一旦TIMx_CNT《TIMx_CCR1時(shí)通道1為無效電平,否則為有效電平;
向下計(jì)數(shù)時(shí),一旦TIMx_CNT》TIMx_CCR1時(shí)通道1為有效電平,否則為無效電平。
這里的有效電平又是什么意思呢?怎么算有效電平?它就是通過極性來配置的:
輸出High模式:有效電平為高電平
輸出Low模式:有效電平為低電平
對比著再來看這張圖:
當(dāng)CNT的計(jì)數(shù)值小于CCR時(shí),即t1這個(gè)時(shí)間段,輸出有效電平(TIM_OCMode_PWM1模式),而有效電平是高電平(極性為TIM_OCPolarity_High),所以PWM的IO邏輯在t1這個(gè)時(shí)間段輸出了高電平。
輸出通道的配置如下:
TIM_OCInitTypeDef TIM_OCInitStructure; /*輸出通道 結(jié)構(gòu)體*//*輸出通道初始化,初始化TIM3 Channel1 PWM模式*/ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; /*選擇定時(shí)器模式:TIM脈沖寬度調(diào)制模式1*/TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; /*輸出極性:TIM輸出比較極性高*/TIM_OC1Init(TIM3, &TIM_OCInitStructure); //根據(jù)指定的參數(shù)初始化外設(shè)TIM3 OC1
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); /*使能TIM3在CCR1上的預(yù)裝載寄存器*/TIM_ARRPreloadConfig(TIM3,ENABLE);/*ARPE使能:使能控制寄存器CR的第8位:ARPR, Auto-reload preload enable*/TIM_Cmd(TIM3, ENABLE); /*使能TIM3:使能控制寄存器CR的第0位:CEN, counter enable*/
關(guān)于配置CCMR1、CCER寄存器
CCMR1:
CCER:
TIM_OC1Init函數(shù)對應(yīng)于輸入通道的初始化,其實(shí)就是操作CCMR1、CCER等寄存器:
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct){ uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0; TIMx-》CCER &= (uint16_t)~TIM_CCER_CC1E;/* 關(guān)閉通道1: 復(fù)位CC1E位 */ tmpccer = TIMx-》CCER;/* 獲取 TIMx CCER 寄存器的值 */ tmpcr2 = TIMx-》CR2; /* 獲取 TIMx CR2 寄存器的值 */
tmpccmrx = TIMx-》CCMR1;/* 獲取TIMx CCMR1 寄存器的值 */ tmpccmrx &= (uint16_t)~TIM_CCMR1_OC1M; /* 復(fù)位輸出比較模式OC1M位 */ tmpccmrx &= (uint16_t)~TIM_CCMR1_CC1S; tmpccmrx |= TIM_OCInitStruct-》TIM_OCMode;/* 設(shè)置為輸出比較模式 */ tmpccer &= (uint16_t)~TIM_CCER_CC1P; /* 復(fù)位輸出極性CC1P */ tmpccer |= TIM_OCInitStruct-》TIM_OCPolarity; /* 設(shè)置輸出極性 */ tmpccer |= TIM_OCInitStruct-》TIM_OutputState; /* 設(shè)置輸出狀態(tài) */ if((TIMx == TIM1) || (TIMx == TIM8)) /*高級定時(shí)器的特殊配置*/ { //省略。。。 } TIMx-》CR2 = tmpcr2; /* 寫數(shù)據(jù)到TIMx的CR2寄存器 */ TIMx-》CCMR1 = tmpccmrx; /* 寫數(shù)據(jù)到TIMx的CCMR1寄存器 */ TIMx-》CCR1 = TIM_OCInitStruct-》TIM_Pulse;/* 設(shè)置CCR1寄存器 */ TIMx-》CCER = tmpccer; /* 寫數(shù)據(jù)到TIMx的CCER寄存器 */}
4.2 動(dòng)態(tài)改變占空比
占空比是通過修改CCR寄存器的值進(jìn)行修改的,如果定時(shí)器初始化時(shí)只設(shè)置了1次CCR的值,那么會(huì)輸出恒定占空比的PWM波;如果在定時(shí)器運(yùn)行的時(shí)候,動(dòng)態(tài)修改CCR的值,則可以實(shí)現(xiàn)PWM占空比的動(dòng)態(tài)調(diào)整。
如下程序,實(shí)現(xiàn)了每隔10ms對占空比進(jìn)行一次修改,每次將高電平計(jì)數(shù)值增加5,當(dāng)增大道500(占空比100%)時(shí),再逐漸減小到0(占空比0%),不斷循環(huán)。
u16 led0pwmval=0; u8 dir=1;TIM3_PWM_Init(500-1,84-1); //84M/84=1Mhz的計(jì)數(shù)頻率,重裝載值500,所以PWM頻率為 1M/500=2Khz. while(1) //實(shí)現(xiàn)比較值從0-500遞增,到500后從500-0遞減,循環(huán){ delay_ms(10);
if(dir) { led0pwmval+=5; //dir==1 led0pwmval遞增 } else { led0pwmval-=5; //dir==0 led0pwmval遞減 } if(led0pwmval》500) { dir=0; //led0pwmval到達(dá)500后,方向?yàn)檫f減 } if(led0pwmval==0) { dir=1; //led0pwmval遞減到0后,方向改為遞增 }
TIM_SetCompare1(TIM3,led0pwmval); /*CCR 修改比較值(占空比)*/}
5 測試效果
將程序下載到板子,我用的一塊STM32F407的板,A6引腳上接了一個(gè)LED燈,實(shí)際效果的LED逐漸變亮,再逐漸變暗,依次循環(huán)。
再通過邏輯分析儀來查看實(shí)際的輸出波形,如下圖,測得的pwm周期0.5ms(頻率2kHz),與軟件中設(shè)定的一致。
在某一時(shí)刻,脈寬55us。
在另一時(shí)刻,脈寬0.365ms,即實(shí)現(xiàn)了PWM脈寬的動(dòng)態(tài)調(diào)整。
編輯:lyn
-
電機(jī)控制
+關(guān)注
關(guān)注
3528文章
1858瀏覽量
268384 -
定時(shí)器
+關(guān)注
關(guān)注
23文章
3241瀏覽量
114486 -
代碼
+關(guān)注
關(guān)注
30文章
4751瀏覽量
68358
發(fā)布評論請先 登錄
相關(guān)推薦
評論