STM32之PWM君


     PWM、、英語好的人估計又知道這三個大寫字母代表哪三個英語單詞了、小弟不才,就說中文意思好了:脈沖寬度調制,玩過飛思卡爾的人估計對PWM非常的不陌生吧、電機驅動需要PWM,控制舵機的轉向需要PWM,總之、可以說,PWM,you are so good。

     好了、、言歸正傳,廣大的互聯網的網友們,咱們又見面了,大家早上晚上中午好好好、額、、好像也沒見過面,STM32的PWM,可謂是小強中的小強,STM32的PWM,就是由定時器產生的,但是奇怪的是除了定時器TIM6和TIM7不能產生PWM外,其他的定時器都可以產生,而且還有多路之分,“高級官員”TIM1和TIM8說:老子可以產生多達7路,而其他的定時器默默的哀傷,因為自己最多只能產生4路(四個通道

      上篇博客介紹了幾位寄存器大神(http://www.cnblogs.com/alvis-jing/p/3691901.html),請把他們的腳步繼續留下,因為還需用到,如不肯留,給他們最殘酷的懲罰:金錢美女伺候、好了,言歸正傳,接下來,為了誕生PWM,我們還將有請以下的幾位寄存器大神(由於大神們都比較低調,在此就不隆重介紹了,大家有興趣的找下“葵花兄”)

注:對於寄存器,本博客就不再深入的講解,大家也可以參照STM32的參考手冊,因為本博客講解的是思路和用庫函數,所以就不再細講寄存器,請見諒

      1、捕獲/比較模式寄存器1(TIMx_CCMR1)

      2、捕獲/比較使能寄存器(TIMx_CCER)

      3、捕獲/比較寄存器2(TIMx_CCR2)

    那好,我們該怎么利用定時器來產生PWM呢??再此之前,我們來了解產生PWM的背后那不為人知的秘密:

    脈沖寬度調制模式可以產生一個由TIMx_ARR寄存器確定頻率、由TIMx_CCRx寄存器確定占空比的信號。

    在TIMx_CCMRx寄存器中的OCxM位寫入’110’(PWM模式1)或’111’(PWM模式2),能夠獨立地設置每個OCx輸出通道產生一路PWM。必須設置TIMx_CCMRx寄存器OCxPE位以使能相應的預裝載寄存器,(請注意這句話!!!!)最后還要設置TIMx_CR1寄存器的ARPE位,(在向上計數或中心對稱模式中)使能自動重裝載的預裝載寄存器。

    在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);

    好了,我們來總結下步驟:

    1、開啟TIM3定時器的時鍾,如果有復用,也要打開復用的時鍾。

    2、初始化TIM3

    3、設置TIM3_CH2的PWM模式,並使能其輸出(注:要使能預裝載寄存器)

    4、開啟TIM3

    5、改變脈沖寬度,從而改變PWM

 

 少了一些自認為是幽默風趣的語言、、為了是讓自己不再顯得那么吊兒郎當、、這篇博客在這又到了尾聲、、本人也在學習階段、、盡量把自己當成讀者,讓讀者看得懂、、有寫錯之處望指出來、不勝感激、、希望能對你有理解上的幫助、、

 

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM