【STM32】PWM程序
00. 目錄
文章目錄
- 00. 目錄
- 01. PWM簡(jiǎn)介
- 02. 硬件設(shè)計(jì)
- 03. 配置步驟
- 04. 程序示例
- 05. 結(jié)果驗(yàn)證
- 06. 附錄
- 07. 聲明
01. PWM簡(jiǎn)介
脈沖寬度調(diào)制(PWM),是英文“Pulse Width Modulation”的縮寫,簡(jiǎn)稱脈寬調(diào)制,是利用微處理器的數(shù)字輸出來對(duì)模擬電路進(jìn)行控制的一種非常有效的技術(shù)。簡(jiǎn)單一點(diǎn),就是對(duì)脈沖寬度的控制,PWM 原理如圖 14.1.1 所示:
圖 14.1.1 就是一個(gè)簡(jiǎn)單的 PWM 原理示意圖。圖中,我們假定定時(shí)器工作在向上計(jì)數(shù) PWM模式,且當(dāng) CNT<CCRx 時(shí),輸出 0,當(dāng) CNT>=CCRx 時(shí)輸出 1。那么就可以得到如上的 PWM示意圖:當(dāng) CNT 值小于 CCRx 的時(shí)候,IO 輸出低電平(0),當(dāng) CNT 值大于等于 CCRx 的時(shí)候,IO 輸出高電平(1),當(dāng) CNT 達(dá)到 ARR 值的時(shí)候,重新歸零,然后重新向上計(jì)數(shù),依次循環(huán)。改變 CCRx 的值,就可以改變 PWM 輸出的占空比,改變 ARR 的值,就可以改變 PWM 輸出的頻率,這就是 PWM 輸出的原理。
STM32F4 的定時(shí)器除了 TIM6 和 7。其他的定時(shí)器都可以用來產(chǎn)生 PWM 輸出。其中高級(jí)定時(shí)器 TIM1 和 TIM8 可以同時(shí)產(chǎn)生多達(dá) 7 路的 PWM 輸出。而通用定時(shí)器也能同時(shí)產(chǎn)生多達(dá) 4路的 PWM 輸出!這里我們僅使用 TIM14 的 CH1 產(chǎn)生一路 PWM 輸出。
02. 硬件設(shè)計(jì)
用到的硬件資源有:
1) 指示燈 DS0
2) 定時(shí)器 TIM14
這兩個(gè)我們前面都已經(jīng)介紹了,因?yàn)?TIM14_CH1 可以通過 PF9 輸出 PWM,而 DS0 就是直接在 PF9 上面的,所以電路上并沒有任何變化。
03. 配置步驟
3.1 開啟 TIM14 和 和 GPIO 時(shí)鐘,配置 PF9 選擇復(fù)用功能 AF9 (TIM14)輸出。
要使用 TIM14,我們必須先開啟 TIM14 的時(shí)鐘。這里我們還要配置 PF9 為復(fù)用(AF9)輸出,才可以實(shí)現(xiàn) TIM14_CH1 的 PWM 經(jīng)過 PF9輸出。 庫函數(shù)使能 TIM14 時(shí)鐘的方法是:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE); //TIM14 時(shí)鐘使能我們還要使能 GPIOF 的時(shí)鐘。然后我們要配置 PF9 引腳映射至 AF9,復(fù)用為定時(shí)器 14,調(diào)用的函數(shù)為:
GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); //GPIOF9 復(fù)用為定時(shí)器 14這里還需要說明一下,對(duì)于定時(shí)器通道的引腳關(guān)系,大家可以查看 STM32F4 對(duì)應(yīng)的數(shù)據(jù)手冊(cè),比如我們 PWM 實(shí)驗(yàn),我們使用的是定時(shí)器 14 的通道 1,對(duì)應(yīng)的引腳 PF9 可以從數(shù)據(jù)手冊(cè)表中查看:
3.2 初始化 TIM14, 設(shè)置 TIM14 的 ARR 和 和 PSC 等參數(shù)。
在開啟了 TIM14 的時(shí)鐘之后,我們要設(shè)置 ARR 和 PSC 兩個(gè)寄存器的值來控制輸出 PWM的周期。當(dāng) PWM 周期太慢(低于 50Hz)的時(shí)候,我們就會(huì)明顯感覺到閃爍了。因此,PWM周期在這里不宜設(shè)置的太小。這在庫函數(shù)是通過 TIM_TimeBaseInit 函數(shù)實(shí)現(xiàn)的,
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置自動(dòng)重裝載值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置預(yù)分頻值 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上計(jì)數(shù)模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據(jù)指定的參數(shù)初始化 TIMx 的3.3 設(shè)置 TIM14_CH1 的 PWM 模式 ,能 使能 TIM14 的 CH1 輸出。
我們要設(shè)置 TIM14_CH1 為 PWM 模式(默認(rèn)是凍結(jié)的),因?yàn)槲覀兊?DS0 是低電平亮,而我們希望當(dāng) CCR1 的值小的時(shí)候,DS0 就暗,CCR1 值大的時(shí)候,DS0 就亮,所以我們要通過配置 TIM14_CCMR1 的相關(guān)位來控制 TIM14_CH1 的模式。在庫函數(shù)中,PWM 通道設(shè)置是通過函數(shù) TIM_OC1Init()~TIM_OC4Init()來設(shè)置的,不同的通道的設(shè)置函數(shù)不一樣,這里我們使用的是通道 1,所以使用的函數(shù)是 TIM_OC1Init()。
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);TIM_OCInitTypeDef類型結(jié)構(gòu)體
typedef struct {uint16_t TIM_OCMode;uint16_t TIM_OutputState;uint16_t TIM_OutputNState; */uint16_t TIM_Pulse;uint16_t TIM_OCPolarity;uint16_t TIM_OCNPolarity;uint16_t TIM_OCIdleState;uint16_t TIM_OCNIdleState; } TIM_OCInitTypeDef;這里我們講解一下與我們要求相關(guān)的幾個(gè)成員變量:
參數(shù) TIM_OCMode 設(shè)置模式是 PWM 還是輸出比較,這里我們是 PWM 模式。
參數(shù) TIM_OutputState 用來設(shè)置比較輸出使能,也就是使能 PWM 輸出到端口。
參數(shù) TIM_OCPolarity 用來設(shè)置極性是高還是低。
其他的參數(shù) TIM_OutputNState,TIM_OCNPolarity,TIM_OCIdleState 和 TIM_OCNIdleState 是高級(jí)定時(shí)器才用到的。
3.4 使能 TIM14 。
在完成以上設(shè)置了之后,我們需要使能 TIM14。使能 TIM14 的方法前面已經(jīng)講解過:
TIM_Cmd(TIM14, ENABLE); //使能 TIM143.5 修改 TIM14_CCR1 來控制占空比。
在經(jīng)過以上設(shè)置之后,PWM 其實(shí)已經(jīng)開始輸出了,只是其占空比和頻率都是固定的,而我們通過修改 TIM14_CCR1 則可以控制 CH1 的輸出占空比。繼而控制 DS0 的亮度。在庫函數(shù)中,修改 TIM14_CCR1 占空比的函數(shù)是:
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare2);04. 程序示例
pwm.h
#ifndef __PWM_H__ #define __PWM_H__#include "sys.h"//定時(shí)器初始化 void TIM14_PWM_Init(u32 arr, u16 psc);#endif /*__PWM_H__*/pwm.c
#include "pwm.h"//定時(shí)器初始化 void TIM14_PWM_Init(u32 arr, u16 psc) {GPIO_InitTypeDef GPIO_Init_Struct;TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_OCInitTypeDef TIM_OCIInitStruct;//使能定時(shí)器TIM14時(shí)鐘RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);//使能GPIO時(shí)鐘 GPIOFRCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//GPIOF選擇位復(fù)用功能 GPIOF PF9GPIO_PinAFConfig(GPIOF, GPIO_PinSource9, GPIO_AF_TIM14);//初始化GPIOGPIO_Init_Struct.GPIO_Pin = GPIO_Pin_9;GPIO_Init_Struct.GPIO_Mode = GPIO_Mode_AF;GPIO_Init_Struct.GPIO_OType = GPIO_OType_PP;GPIO_Init_Struct.GPIO_PuPd = GPIO_PuPd_UP;GPIO_Init_Struct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOF, &GPIO_Init_Struct);//初始化定時(shí)器14TIM_TimeBaseInitStruct.TIM_Period = arr;TIM_TimeBaseInitStruct.TIM_Prescaler = psc;TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM14, &TIM_TimeBaseInitStruct);//設(shè)置TIM14_CH1為PWM模式TIM_OCIInitStruct.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCIInitStruct.TIM_OutputState = TIM_OutputState_Enable;TIM_OCIInitStruct.TIM_OCPolarity = TIM_OCPolarity_Low;TIM_OC1Init(TIM14, &TIM_OCIInitStruct);//使能TIM14在CCR1上的預(yù)裝載寄存器TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);//ARPE使能TIM_ARRPreloadConfig(TIM14, ENABLE);//使能TIM14TIM_Cmd(TIM14, ENABLE);}main.c
#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "beep.h" #include "key.h" #include "exti.h" #include "iwdg.h" #include "wwdg.h" #include "timer.h" #include "pwm.h"int main(void) { u16 led0Value = 0;u8 dir = 1;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);delay_init(168);TIM14_PWM_Init(500 - 1, 84 - 1);while(1){delay_ms(10);if (dir){led0Value++;}else{led0Value--;}if (led0Value > 300){dir = 0;}if (0 == led0Value){dir = 1;}TIM_SetCompare1(TIM14, led0Value);}}05. 結(jié)果驗(yàn)證
我們將看 DS0 不停的由暗變到亮,然后又從亮變到暗。
06. 附錄
6.1 【STM32】STM32系列教程匯總
網(wǎng)址:【STM32】STM32系列教程匯總
07. 聲明
該教程參考了正點(diǎn)原子的《STM32 F4 開發(fā)指南》
總結(jié)
以上是生活随笔為你收集整理的【STM32】PWM程序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【STM32】定时器程序
- 下一篇: 【STM32】复位