【STM32】PWM 输出 (标准库)

举报
AXYZdong 发表于 2022/01/18 11:21:32 2022/01/18
【摘要】 PWM:脉冲宽度调制(Pulse width modulation)。PWM输出实验,制作呼吸灯。

Author: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
# @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
# @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
# @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[霸天虎]开发板 》
  本次的分享就到这里


11

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


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

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。