PWM、、英語好的人估計又知道這三個大寫字母表明哪三個英語單詞了、小弟不才,就說中文意思好了:脈衝寬度調製,玩過飛思卡爾的人估計對PWM很是的不陌生吧、電機驅動須要PWM,控制舵機的轉向須要PWM,總之、能夠說,PWM,you are so good。html
好了、、言歸正傳,廣大的互聯網的網友們,我們又見面了,你們早上晚上中午好好好、額、、好像也沒見過面,STM32的PWM,可謂是小強中的小強,STM32的PWM,就是由定時器產生的,可是奇怪的是除了定時器TIM6和TIM7不能產生PWM外,其餘的定時器均可以產生,並且還有多路之分,「高級官員」TIM1和TIM8說:老子能夠產生多達7路,而其餘的定時器默默的哀傷,由於本身最多隻能產生4路(四個通道)。函數
上篇博客介紹了幾位寄存器大神(http://www.cnblogs.com/alvis-jing/p/3691901.html),請把他們的腳步繼續留下,由於還需用到,如不願留,給他們最殘酷的懲罰:金錢美女伺候、好了,言歸正傳,接下來,爲了誕生PWM,咱們還將有請如下的幾位寄存器大神(因爲大神們都比較低調,在此就不隆重介紹了,你們有興趣的找下「葵花兄」)學習
注:對於寄存器,本博客就再也不深刻的講解,你們也能夠參照STM32的參考手冊,由於本博客講解的是思路和用庫函數,因此就再也不細講寄存器,請見諒spa
一、捕獲/比較模式寄存器1(TIMx_CCMR1)code
二、捕獲/比較使能寄存器(TIMx_CCER)htm
三、捕獲/比較寄存器2(TIMx_CCR2)blog
那好,咱們該怎麼利用定時器來產生PWM呢??再此以前,咱們來了解產生PWM的背後那鮮爲人知的祕密:ip
脈衝寬度調製模式能夠產生一個由TIMx_ARR寄存器肯定頻率、由TIMx_CCRx寄存器肯定佔空比的信號。博客
在TIMx_CCMRx寄存器中的OCxM位寫入’110’(PWM模式1)或’111’(PWM模式2),可以獨立地設置每一個OCx輸出通道產生一路PWM。必須設置TIMx_CCMRx寄存器OCxPE位以使能相應的預裝載寄存器,(請注意這句話!!!!)最後還要設置TIMx_CR1寄存器的ARPE位,(在向上計數或中心對稱模式中)使能自動重裝載的預裝載寄存器。it
在PWM模式(模式1或模式2)下,TIMx_CNT和TIMx_CCRx始終在進行比較,(依據計數器的計數方向)以肯定是否符合TIMx_CCRx≤TIMx_CNT或者TIMx_CNT≤TIMx_CCRx。
因此,該寄存器的值一直與CNT比較,根據比較結果產生相應的動做,利用這裏一點,咱們經過修改這個寄存器的值,就能夠控制PWM的輸出脈寬了,(在這裏有專門的庫函數能夠操做,因此是至關方便)
那怎麼操做呢??在這裏,咱們經過一直沒有提過的很是重要的概念:重映射,把TIM3_CH2的PA7重映射到PB5,而PB5是鏈接LED的,因此咱們能夠經過觀察LED的亮度才體驗PWM、、也難爲了LED君,總是被觀察,臉也不紅下、、
所謂的重映射,就是把本來默認的引腳給誘惑到另外一個引腳上,專業上給的是重映射,可是我以爲並不是這麼簡單、果真,它還有一個功能:複用、、因此第一步:
咱們要打開復用的時鐘和把IO口設成複用推輓輸出,固然也要打開TIM3的時鐘,見代碼:(映射有部分映射和所有映射,都有可用的函數,在這裏咱們是部分映射,可是,映射了一個引腳,另外的引腳也被牽扯下來了,哎)
注意紅色代碼
1 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE); 2 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); 3 4 GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); 5 6 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; 7 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 8 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 9 GPIO_Init(GPIOB, &GPIO_InitStructure);
接下來: 通用計時器的初始化:(因爲上篇博客已講解,在這就不細講了哈,請見諒哈http://www.cnblogs.com/alvis-jing/p/3691901.html)請看代碼:
1 TIM_TimeBaseStructure.TIM_Period = arr; 2 TIM_TimeBaseStructure.TIM_Prescaler = psc; 3 TIM_TimeBaseStructure.TIM_ClockDivision = 0; 4 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 5 TIM_TimeBaseInit(TIM3, & TIM_TimeBaseStructure);
接下來,就是PWM的重頭戲了,在這裏,咱們要設置TIM3_CH2爲PWM模式,(注意,因爲TIM3能夠產生四路PWM,每路都有不一樣的但相似的函數來控制)在這裏,咱們是經過
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)來實現的
打開"stm32f10x_tim.h"能夠看到,在這裏,咱們只顯示一些跟咱們有用的參數:
TIM_OCMode輸出模式;—>PWM2
TIM_OutputState輸出使能;—>使能PWM
TIM_OCPolarity輸出極性;—>極性爲高 代碼以下:
1 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; 2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 3 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 4 TIM_OC2Init(TIM3, &TIM_OCInitStructure);
接下來,最關鍵的一步也是最容易遺漏的:就是使能預裝載寄存器,在這裏咱們經過庫函數
TIM_OC2PreloadConfig 使能或者失能TIMx在CCR2上的預裝載寄存器 請看代碼:
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
好了,最後一步,咱們開啓定時器TIM3,這個你們也不陌生了吧、、仍是老規矩;知道的,來人,賞美女十個,還不知道的,拉出去調戲十分鐘
1 /* Enables the TIM3 counter */ 2 TIM_Cmd(TIM3, ENABLE);
親、、在這裏、、你以爲你能看到LED從暗到亮了嗎??你想看,LED君還不願呢、沒錯了、、但這是爲何呢??
緣由就是這裏設置產生的PWN是固定脈寬的、、那咱們怎麼來改變它呢??咦、庫函數爲咱們提供了這樣的一個好機會:
TIM_SetCompare2 設置TIMx捕獲比較2寄存器值
經過這個函數咱們就能夠設置脈衝寬度,從而控制PWM了、、代碼以下:
1 TIM_SetCompare2(TIM3, temp);
好了,咱們來總結下步驟:
一、開啓TIM3定時器的時鐘,若是有複用,也要打開復用的時鐘。
二、初始化TIM3
三、設置TIM3_CH2的PWM模式,並使能其輸出(注:要使能預裝載寄存器)
四、開啓TIM3
五、改變脈衝寬度,從而改變PWM
少了一些自認爲是幽默風趣的語言、、爲了是讓本身再也不顯得那麼吊兒郎當、、這篇博客在這又到了尾聲、、本人也在學習階段、、儘可能把本身當成讀者,讓讀者看得懂、、有寫錯之處望指出來、不勝感激、、但願能對你有理解上的幫助、、