一、PWM簡介
PWM:脈沖寬度調制(Pulse width modulation,PWM)
脈沖寬度調制是一種模擬控制方式,根據相應載荷的變化來調制晶體管基極或MOS管柵極的偏置,來實現晶體管或MOS管導通時間的改變,從而實現開關穩壓電源輸出的改變。這種方式能使電源的輸出電壓在工作條件變化時保持恒定,是利用微處理器的數字信號對模擬電路進行控制的一種非常有效的技術。脈沖寬度調制是利用微處理器的數字輸出來對模擬電路進行控制的一種非常有效的技術,廣泛應用在從測量、通信到功率控制與變換的許多領域中?!俣劝倏?p>
二、PWM輸出模式
PWM 輸出就是對外輸出脈寬(即占空比)可調的方波信號,信號頻率由自動重裝 寄存器 ARR 的值決定,占空比由 比較寄存器 CCR 的值決定。
PWM 模式分為兩種,PWM1和 PWM2。區別如下:
三、初始化結構體
1. TIM_TimeBaseInitTypeDef
typedef struct {
uint16_t TIM_Prescaler; // 預分頻器
uint16_t TIM_CounterMode; // 計數模式
uint32_t TIM_Period; // 定時器周期
uint16_t TIM_ClockDivision; // 時鐘分頻
uint8_t TIM_RepetitionCounter; // 重復計算器
} TIM_TimeBaseInitTypeDef;
結構體具體介紹參見:【STM32】TIM—基本定時器
2. TIM_OCInitTypeDef
/**
* @brief TIM Output Compare Init structure definition
*/
typedef struct
{
uint16_t TIM_OCMode; /*!< Specifies the TIM mode.
This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */
uint16_t TIM_OutputState; /*!< Specifies the TIM Output Compare state.
This parameter can be a value of @ref TIM_Output_Compare_State */
uint16_t TIM_OutputNState; /*!< Specifies the TIM complementary Output Compare state.
This parameter can be a value of @ref TIM_Output_Compare_N_State
@note This parameter is valid only for TIM1 and TIM8. */
uint32_t TIM_Pulse; /*!< Specifies the pulse value to be loaded into the Capture Compare Register.
This parameter can be a number between 0x0000 and 0xFFFF */
uint16_t TIM_OCPolarity; /*!< Specifies the output polarity.
This parameter can be a value of @ref TIM_Output_Compare_Polarity */
uint16_t TIM_OCNPolarity; /*!< Specifies the complementary output polarity.
This parameter can be a value of @ref TIM_Output_Compare_N_Polarity
@note This parameter is valid only for TIM1 and TIM8. */
uint16_t TIM_OCIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state.
This parameter can be a value of @ref TIM_Output_Compare_Idle_State
@note This parameter is valid only for TIM1 and TIM8. */
uint16_t TIM_OCNIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state.
This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State
@note This parameter is valid only for TIM1 and TIM8. */
} TIM_OCInitTypeDef;
(1) TIM_OCMode:比較輸出模式選擇,總共有八種,常用的為 PWM1/PWM2。它設定 CCMRx寄存器 OCxM[2:0]位的值。
(2) TIM_OutputState:比較輸出使能,決定最終的輸出比較信號 OCx是否通過外部引腳輸出。它設定 TIMx_CCER寄存器 CCxE/CCxNE 位的值。
(3) TIM_OutputNState:比較互補輸出使能,決定 OCx的互補信號 OCxN是否通過外部引腳輸出。它設定 CCER寄存器 CCxNE 位的值。
(4) TIM_Pulse:比較輸出脈沖寬度,實際設定比較寄存器 CCR的值,決定脈沖寬度??稍O置范圍為 0至 65535。
(5) TIM_OCPolarity:比較輸出極性,可選 OCx為高電平有效或低電平有效。它決定著定時器通道有效電平。它設定 CCER寄存器的 CCxP位的值。
(6) TIM_OCNPolarity:比較互補輸出極性,可選 OCxN 為高電平有效或低電平有效。它設定 TIMx_CCER寄存器的 CCxNP位的值。
(7) TIM_OCIdleState:空閑狀態時通道輸出電平設置,可選輸出 1或輸出 0,即在空閑狀態(BDTR_MOE 位為 0)時,經過死區時間后定時器通道輸出高電平或低電平。它設定 CR2寄存器的 OISx位的值。
(8) TIM_OCNIdleState:空閑狀態時互補通道輸出電平設置,可選輸出 1 或輸出 0,即在空閑狀態(BDTR_MOE 位為 0)時,經過死區時間后定時器互補通道輸出高電平或低電 平,設定值必須與 TIM_OCIdleState 相反。它設定是 CR2 寄存器的 OISxN 位的值。
四、PWM輸出實驗
編程思路
初始化 LED
初始化延時函數
開啟定時器時鐘
設置定時器周期和預分頻器
初始化定時器
主函數中修改比較值和占空比
pwm.h
// =============================================
# @Time : 2020-10-24
# @Author : AXYZdong
# @CSDN : https://blog.csdn.net/qq_43328313
# @FileName: pwm.h
# @Software: keil5 MDK
// =============================================
#ifndef _TIME_H
#define _TIME_H
#include "stm32f4xx.h"
void TIM3_PWM_Init(u32 ARR , u32 PSC);
#endif
pwm.c
// =============================================
# @Time : 2020-10-24
# @Author : AXYZdong
# @CSDN : https://blog.csdn.net/qq_43328313
# @FileName: pwm.c
# @Software: keil5 MDK
// =============================================
#include "pwm.h"
#include "bsp_led.h"
extern void TIM3_PWM_Init(u32 ARR , u32 PSC);
void TIM3_PWM_Init(u32 ARR , u32 PSC)
{
//此部分需手動修改IO口設置
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //TIM3時鐘使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能PORTA時鐘
GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_TIM3); //GPIOA6復用為定時器3
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //GPIOFA
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //復用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽復用輸出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA6
TIM_TimeBaseStructure.TIM_Prescaler=PSC; //定時器分頻
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上計數模式
TIM_TimeBaseStructure.TIM_Period=ARR; //自動重裝載值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);//初始化定時器3
//初始化TIM14 Channel1 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //選擇定時器模式:TIM脈沖寬度調制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //輸出極性:TIM輸出比較極性低
TIM_OC1Init(TIM3, &TIM_OCInitStructure); //根據T指定的參數初始化外設TIM1 4OC1
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR1上的預裝載寄存器
TIM_ARRPreloadConfig(TIM3,ENABLE);//ARPE使能
TIM_Cmd(TIM3, ENABLE); //使能TIM3
}
main.c
// =============================================
# @Time : 2020-10-24
# @Author : AXYZdong
# @CSDN : https://blog.csdn.net/qq_43328313
# @FileName: main.c
# @Software: keil5 MDK
// =============================================
#include "stm32f4xx.h"
#include "delay.h"
#include "pwm.h"
#include "bsp_led.h"
int main(void)
{
u16 ledpwmval=0;
u8 flag=1;
delay_init(168); //初始化延時函數
LED_GPIO_Config(); //初始化LED
TIM3_PWM_Init(100-1,84-1); //初始化定時器
while(1)
{
delay_ms(10);
if(flag)ledpwmval++;
else ledpwmval--;
if(ledpwmval==0)flag=1;
if(ledpwmval==40)flag=0;
TIM_SetCompare1(TIM3,ledpwmval); //修改比較值,修改占空比
}
}
五、總結
PWM輸出,觀察到 LED 緩慢變亮又緩慢變暗的狀態(呼吸燈)
通過對定時器初始化數據和比較值的修改,可以改變亮暗時間
【參考文獻】
[1] 《零死角玩轉 STM32—基于野火 F407[霸天虎]開發板 》
上一篇:【STM32】STM32F407 + DHT11
下一篇:【STM32】TIM---基本定時器
推薦閱讀
史海拾趣