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