STM32——定时器PWM

参考博客
STM32F4定时器与PWM
STM32F4除了基本定时器TIM6和TIM7,其他定时器都可以产生PWM输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出(TIM9-TIM14最多能产生2路)。
PWM的输出其实就是对外输出脉宽可调(即占空比调节)的方波信号,信号频率是由自动重装寄存器 ARR 的值决定,占空比由比较寄存器 CCR 的值决定。

PWM模式:
PWM输出比较模式总共有8种,最常用的两种PWM输出模式:PWM1和PWM2。
在这里插入图片描述
PWM模式根据计数器CNT计数方式,可分为边沿对齐模式和中心对齐模式。

PWM边沿对齐模式
当 TIMx_CR1 寄存器中的 DIR 位为低时执行递增计数,计数器CNT从 0 计数到自动重载值(TIMx_ARR 寄存器的内容),然后重新从 0 开始计数并生成计数器上溢事件。以 PWM 模式 1 为例。只要TIMx_CNT < TIMx_CCRx, PWM 参考信号 OCxREF 便为 高电平,否则为低电平。如果 TIMx_CCRx 中的比较值大于自动重载值(TIMx_ARR 中),则 OCxREF 保持为“ 1”。如果比较值为 0, 则 OCxREF 保持为“ 0”。
当 TIMx_CR1 寄存器中的 DIR 位为高时执行递减计数,计数器CNT从自动重载值(TIMx_ARR 寄存器的内容)递减计数到0,然后重新从TIMx_ARR值开始计数并生成计数器下溢事件。以 PWM 模式 1 为例。只要TIMx_CNT >TIMx_CCRx, PWM 参考信号 OCxREF 便为 低电平,否则为高电平。如果 TIMx_CCRx 中的比较值大于自动重载值(TIMx_ARR 中),则 OCxREF 保持为“ 1”。此模式下不能产生0%的PWM波形。
在这里插入图片描述
PWM中心对齐模式
在中心对齐模式下,计数器 CNT 是工作做递增/递减模式下。开始的时候, 计数器CNT 从 0 开始计数到自动重载值减 1(ARR-1),生成计数器上溢事件;然后从自动重载值开始向下计数到 1 并生成计数器下溢事件。之后从 0 开始重新计数。
在这里插入图片描述
以ARR=8,CCRx=4为例进行介绍。第一阶段计数器CNT工作在递增计数方式,从0开始计数,当TIMx_CNT < TIMx_CCRx时,PWM 参考信号 OCxREF为高电平,当TIMx_CNT >= TIMx_CCRx时,PWM 参考信号 OCxREF为低电平。第二阶段计数器CNT工作在递减计数方式,从ARR开始递减计数,当TIMx_CNT > TIMx_CCRx时,PWM 参考信号 OCxREF为低电平,当TIMx_CNT <= TIMx_CCRx时,PWM 参考信号 OCxREF为高电平。
PWM输出配置步骤
(1)使能定时器及端口时钟,并设置引脚复用器映射
可选的参数在 stm32f4xx_gpio.h
在这里插入图片描述

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE);
void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t  GPIO_PinSource, uint8_t GPIO_AF);
GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);

(2)初始化定时器参数,包含自动重装值,分频系数,计数方式等

voidTIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

(3)初始化PWM输出参数,包含PWM模式、输出极性,使能等

void TIM_OCxInit(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);  
/typedef struct
{
  uint16_t TIM_OCMode;        //比较输出模式
  uint16_t TIM_OutputState;   //比较输出使能
  uint16_t TIM_OutputNState;  //比较互补输出使能
  uint32_t TIM_Pulse;         //脉冲宽度
  uint16_t TIM_OCPolarity;    //输出极性
  uint16_t TIM_OCNPolarity;   //互补比较输出极性
  uint16_t TIM_OCIdleState;   //空闲状态下比较输出状态
  uint16_t TIM_OCNIdleState;  //空闲状态下比较输出状态
} TIM_OCInitTypeDef;         **/

(4)开启定时器

void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);TIM_Cmd(TIM4,ENABLE); //开启定时器

为了使代码完整可以使能定时器在CCR1上的预装载寄存器以及使能定时器ARR上的装载寄存器,也可以不用使能

void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

(5)修改TIMx_CCRx的值控制占空比
通常在主函数中对其进行调用

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint32_t Compare1);

pwm源文件:

#include "pwm.h"

void TIM14_CH1_PWM_Init(u16 per,u16 psc)
{
	    GPIO_InitTypeDef GPIO_InitStructure; //定义复用管教9结构体变量
	
	    TIM_TimeBaseInitTypeDef  TIMBaseInitStructure;  //定时器参数结构体
	    TIM_OCInitTypeDef  TIM_OCINitStructure;  //pwm输出参数结构体
	    
	    
			RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE);  //使能定时器14时钟
      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);  //使能端口时钟,因为定时器14的pwm在通道1,是挂接在AHB的GPIOF9上的

	    GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);  //将PF9映射到TIM4通道1的pwm功能上
	
	    //初始化PF9端口
			GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //复用输出模式
			GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//管脚设置F9
			GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//速度为100M
			GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
			GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
			GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化结构体
			
	    //初始化定时器参数
	    TIMBaseInitStructure.TIM_Period =per;  //自动重装载值  周期
  	  TIMBaseInitStructure.TIM_Prescaler = psc;   //预分频系数(时钟源)
	    TIMBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;   //时钟分割,时钟分频 通常不需要修改
			TIMBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数模式选择向上计数
      TIM_TimeBaseInit(TIM14,&TIMBaseInitStructure);   //初始化定时器中断
	    
			
			//初始化PWM输出参数
			TIM_OCINitStructure.TIM_OCMode = TIM_OCMode_PWM1;      //比较输出模式:pwm模式
			TIM_OCINitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性
      TIM_OCINitStructure.TIM_OutputState = TIM_OutputState_Enable;  //比较输出使能
			TIM_OC1Init(TIM14,&TIM_OCINitStructure);
			
			TIM_OC1PreloadConfig(TIM14,ENABLE);//使能定时器14在CCR1上的预装载寄存器
			TIM_ARRPreloadConfig(TIM14,ENABLE); // 使能定时器14ARR上的装载寄存器
			
			TIM_Cmd(TIM14,ENABLE);  //开启定时器TIM14
			
}


主函数:

#include "led.h"
#include "system.h"
#include "SysTick.h"
#include "key.h"
#include "pwm.h"

int main()
{
	u8 fx = 0;
	u16 i = 0;
	SysTick_Init(168);
	LED_Init();
	TIM14_CH1_PWM_Init(500-1,84-1);//84MHz分频为84即1MHz为1us,计数500次为500us,频率为2KHz
  	
	while(1)
	{
		if(fx == 0){    //fx用于对亮暗改变方向
		     i++;       //用于比较函数
			if(i == 300){   //在计数到300的时候改变计数方向(增减)
			    fx = 1;
			}
		}else{
		   i--;
			 if(i == 0){
			     fx = 0;
			 }
		
		}
		TIM_SetCompare1(TIM14,i);   //pwm用于比较的函数,以此来控制占空比的值
		myDelay_ms(10);
	}
	
}

		 


### STM32 单片机定时器 PWM 配置教程 #### 1. 定时器选择与初始化 STM32系列芯片提供了多种类型的定时器,对于PWM信号生成而言,通常会选择通用定时器(TIM2-TIM5)或高级定时器(TIM1, TIM8)[^1]。这些定时器具有丰富的功能集,能够满足不同应用场景下的需求。 为了实现PWM输出,在项目启动阶段需完成如下操作: - **使能相应外设时钟**:通过RCC(Reset and Clock Control)模块开启目标定时器及其关联GPIO端口的电源供应。 - **配置GPIO引脚模式**:设定指定管脚为复用推挽输出方式,以便后续作为PWM通道使用。 ```c // 假定采用TIM2_CH1(PA0), 开启对应APB1总线与时钟树上的资源访问权限. __HAL_RCC_TIM2_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 复用推挽输出 GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF1_TIM2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); ``` #### 2. 设置定时器参数并启用自动重装载预分频特性 接下来定义计数值上限(AutoReload Value),以及基于系统主频计算得出合适的预分频系数(Prescaler value),从而决定最终PWM周期长度[Tpwm=ARR*(PSC+1)/Fclk_tim]。这里假设期望得到频率为5kHz的方波,则可按以下方式进行初步估算: \[ ARR=\frac{f_{sys}}{(psc+1)\times f_{out}}-\textit{1} \] 其中\( f_{sys}=72MHz\)(具体取决于实际使用的MCU型号) ```c uint32_t PrescalerValue = (uint32_t)((SystemCoreClock / 2) / 1000000) - 1; TIM_HandleTypeDef htim2; htim2.Instance = TIM2; htim2.Init.Prescaler = PrescalerValue; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 999; /* 设定期望的PWM周期 */ htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; if (HAL_TIM_PWM_Init(&htim2) != HAL_OK){ Error_Handler(); /* 初始化失败处理函数 */ } ``` #### 3. 创建PWM通道实例化结构体对象,并调整占空比属性 最后一步便是创建具体的PWM通道实体,同时指明其对应的匹配寄存器(CCRx Register)地址;另外还需注意的是,改变CCRx中的值即可动态调节PWM波形高低电平持续时间比例关系——即所谓的“占空比”。 ```c TIM_OC_InitTypeDef sConfigOC; sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 499; /* 初始占空比约为50% */ sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK){ Error_Handler(); } /* 启动PWM信号发生过程 */ if(HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1)!= HAL_OK){ Error_Handler(); } ``` 以上代码片段展示了如何在STM32平台上构建一个简单的PWM输出接口[^2]。值得注意的是,上述例子仅适用于特定条件下(如固定的工作频率),当面对更复杂的应用场景时可能还需要进一步优化相关参数设置逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值