【STM32】PWM 输出 (标准库)

本文详细介绍了STM32的PWM工作原理、输出模式,并通过实例展示了如何使用TIM初始化结构体设置PWM参数。通过编程实现了PWM输出,通过改变比较值调整占空比,观察到LED亮度的渐变,呈现呼吸灯效果。
摘要由CSDN通过智能技术生成

Author:AXYZdong 自动化专业 工科男
有一点思考,有一点想法,有一点理性!
定个小小目标,努力成为习惯!在最美的年华遇见更好的自己!
CSDN@AXYZdong,CSDN首发,AXYZdong原创
唯一博客更新的地址为: 👉 AXYZdong的博客 👈


一、PWM简介

PWM:脉冲宽度调制(Pulse width modulation,PWM)

脉冲宽度调制是一种模拟控制方式,根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通时间的改变,从而实现开关稳压电源输出的改变。这种方式能使电源的输出电压在工作条件变化时保持恒定,是利用微处理器的数字信号对模拟电路进行控制的一种非常有效的技术。脉冲宽度调制是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。——百度百科


二、PWM输出模式

PWM 输出就是对外输出脉宽(即占空比)可调的方波信号,信号频率由自动重装 寄存器 ARR 的值决定,占空比由 比较寄存器 CCR 的值决定。

PWM 模式分为两种,PWM1和 PWM2。区别如下:

模式 计数器 CNT 计算方式说明
PWM1递增 CNT < CCR,通道CH为有效,否则为无效
递减CNT > CCR,通道 CH为无效,否则为有效
PWM2递增 CNT < CCR,通道CH为有效,否则为无效
递减CNT < CCR,通道CH为有效,否则为无效

三、初始化结构体

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的值,决定脉冲宽度。可设置范围为 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】点亮LED
【STM32】GPIO输入—按键检测
【STM32】0.96寸OLED显示屏(7针SPI协议)软件模拟SPI
【STM32】1.44寸TFT液晶屏显示字符、汉字和图片
【STM32】stm32f407 + DS18B20 碰出不一样的火花
【STM32】5分钟了解STM32的串口通信
【STM32】串口通信—用代码与芯片对话
【STM32】串口通信出现乱码(使用官方标准库)
【STM32】EXTI—外部中断/事件控制器
【STM32】TIM—基本定时器

【STM32】CubeMX+HAL 点亮LED
【STM32】CubeMX+HAL 输出PWM

【STM32】ST-LINK下载器下载后需复位,程序才运行的问题

其他相关文章:
【信号与系统】笔记合集,你确定不收藏吗?我已经收藏了
我用50行代码居然「让天猫精灵把客厅灯开了」
流程图在线绘制,快速、便捷、高效!


  本次的分享就到这里


11

好书不厌百回读,熟读自知其中意。将学习成为习惯,用知识改变命运,用博客见证成长,用行动证明努力。
如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!
听说 👉 点赞 👈 的人运气不会太差,每一天都会元气满满呦!^ _ ^ ❤️ ❤️ ❤️
码字不易,大家的支持就是我坚持下去的动力。点赞后不要忘了👉关注👈我哦!
更多精彩内容请前往 AXYZdong的博客


如果以上内容有任何错误或者不准确的地方,欢迎在下面 👇 留个言。或者你有更好的想法,欢迎一起交流学习~~~

评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AXYZdong

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值