【STM32】PWM

一、 PWM 概述
  1. 定义
    PWM(Pulse Width Modulation), 脉冲宽度调制。
    脉冲: 方波, 频率(freq)
    宽度: 高电平的宽度, 占空比(duty)

​ 详细波形如下图。

  1. 用途

    控制灯光的亮度(手机/平板/显示器背光灯)

    电机的转速

    ...

  2. 灯光的控制细节

    频率要大于 25Hz, 灯光的亮度的变化是跟着占空比而变化, 占空比越大, 灯光越暗; 占空比越小, 灯光越亮。

  3. STM32工作过程

​ CCR1:捕获比较(值)寄存器(x=1,2,3,4):设置比较值。

​ CCMR1: OC1M[2:0]位:

​ 对于PWM方式下,用于设置PWM模式1【110】或者PWM模式2【111】

​ CCER:CC1P位:输入/捕获1输出极性。0:高电平有效,1:低电平有效。

​ CCER:CC1E位:输入/捕获1输出使能。0:关闭,1:打开。

PWM模式1 & PWM模式2

寄存器TIMx_CCMR1的OC1M[2:0]位来分析:

c 复制代码
void TIM_OCxPreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

自动重载的预装载寄存器

c 复制代码
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

简单的说,ARPE=1,ARR立即生效。。。APRE=0,ARR下个比较周期生效。

STM32 定时器14输出通道引脚

PWM输出库函数

c 复制代码
void TIM_OCxInit(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
typedef struct
{
  uint16_t TIM_OCMode;  //PWM模式1或者模式2
  uint16_t TIM_OutputState; //输出使能 OR失能
  uint16_t TIM_OutputNState;
  uint16_t TIM_Pulse; //比较值,写CCRx
  uint16_t TIM_OCPolarity; //比较输出极性
  uint16_t TIM_OCNPolarity; 
  uint16_t TIM_OCIdleState;  
  uint16_t TIM_OCNIdleState; 
} TIM_OCInitTypeDef;

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //PWM模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure. TIM_Pulse=100;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2

设置比较函数:

void TIM_SetCompareX(TIM_TypeDef* TIMx, uint16_t Comparex);

使能输出比较预装载:

void TIM_OCxPreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

u使能自动重装载的预装载寄存器允许位:

c 复制代码
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

PWM输出配置步骤:

①使能定时器14和相关IO口时钟.

​ 使能定时器14时钟:RCC_APB1PeriphClockCmd();

​ 使能GPIOF时钟:RCC_AHB1PeriphClockCmd ();

初始化IO口为复用功能输出。函数:GPIO_Init();

​ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能

③ GPIOF9复用映射到定时器14

​ GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);

初始化定时器:ARR,PSC等:TIM_TimeBaseInit();

初始化输出比较参数:TIM_OC1Init();

使能预装载寄存器:TIM_OC1PreloadConfig(TIM14, **TIM_OCPreload_Enable);

⑦使能自动重装载的预装载寄存器允许位TIM_ARRPreloadConfig(TIM14,ENABLE);

⑧使能定时器.

⑨不断改变比较值CCRx,达到不同的占空比效果:TIM_SetCompare1();

二. 程序设计
  1. 原理图

​ 不同的定时器, 输出通道的数目都有所不一样。 在高级定时器输出多路的 PWM,

​ 比可以是不一样的, 能够由 TIM_SetComparex[1-3]来进行设置不同的通道占空比!

  1. 配置频率

    c 复制代码
    /* TIM14 clock enable , 定时器 14 时钟使能*/
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);
    /* Time base configuration , 定时器基本配置, TIM_Period 是计数值*/
    TIM_TimeBaseStructure.TIM_Period = (10000/100)-1; //输出频率为 100Hz,(10000/100) -1 得到的结果就是计数值。
    TIM_TimeBaseStructure.TIM_Prescaler = 8400-1; //预分频值
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频, 也称之为二次分频,当前是 1 分频, 说白了不分频,
    不降低频率
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数的方法
    TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure); //初始化
  2. 配置PWM输出功能

c 复制代码
/* PWM1 Mode configuration: Channel1 , 让 PWM 的通道 1 工作在模式 1*/
//PWM 模式 1, 在递增模式下, 只要 TIMx_CNT < TIMx_CCR1, 通道 1 便为有效状态(高电平), 否则为无效状态(低电平)。
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //允许输出
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //有效的时候, 输出高电平
TIM_OC1Init(TIM14, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable); //自动重载初值, 不断输出 PWM 脉冲
TIM_ARRPreloadConfig(TIM14, ENABLE); //自动重载初值使能
/* TIM14 enable counter, 使能定时器 14 工作 */
TIM_Cmd(TIM14, ENABLE);

demo:

c 复制代码
#include "beep.h"
#include "sys.h"
#include "delay.h"


// LED pwm定时器设置
void init_TIM14()
{
	// 定义GPIO外设
	GPIO_InitTypeDef  GPIO_InitStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;

	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

	// 使能定时器14系统时钟源
	// APB1 :42M
    // TIM3 : 42*2 = 84M == 1s	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);
	
	// 配置定时时间 10ms
	TIM_TimeBaseStructure.TIM_Period = 100-1; // 重装载寄存器
	TIM_TimeBaseStructure.TIM_Prescaler = 8400-1; // 分频系数
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; // 时钟二次分频
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure);
	
	/* PWM1 Mode configuration: Channel1 */
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // pwm1模式,CNT < CCR,输出有效电平
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 输出使能
	TIM_OCInitStructure.TIM_Pulse = 0; // CCR初始值,通过改变CCR设置占空比
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 有效电平为高电平
	
	TIM_OC1Init(TIM14, &TIM_OCInitStructure);
	// 自动重装载器使能
	TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);
	
	/* TIM14 enable counter */
	TIM_Cmd(TIM14, ENABLE);
	
	// 初始化LED PF9
	// 使能F组管脚工作
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);

	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // 复用模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 推挽模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // 无拉电阻
	GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed;
	// 初始化GPIO
	GPIO_Init(GPIOF, &GPIO_InitStructure);
	
	// 将PF9和定时器进行绑定
	GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);
	
}


int main()
{	
	uint32_t pwm_cmp;
	init_TIM14();

	while(1)
	{
		// 设置占空比,pwm_cmp小于ARR(重装载寄存器)值
		for(pwm_cmp = 0; pwm_cmp < 100; pwm_cmp++)
		{
			TIM_SetCompare1(TIM14, pwm_cmp);
			delay_ms(20);
		}
		for(pwm_cmp = 100; pwm_cmp > 0; pwm_cmp--)
		{
			TIM_SetCompare1(TIM14, pwm_cmp);
			delay_ms(20);
		}
	}
}
相关推荐
yutian06061 小时前
Keil MDK下载程序后MCU自动重启设置
单片机·嵌入式硬件·keil
析木不会编程4 小时前
【小白51单片机专用教程】protues仿真独立按键控制LED
单片机·嵌入式硬件·51单片机
枯无穷肉8 小时前
stm32制作CAN适配器4--WinUsb的使用
stm32·单片机·嵌入式硬件
不过四级不改名6778 小时前
基于HAL库的stm32的can收发实验
stm32·单片机·嵌入式硬件
嵌入式科普9 小时前
十一、从0开始卷出一个新项目之瑞萨RA6M5串口DTC接收不定长
c语言·stm32·cubeide·e2studio·ra6m5·dma接收不定长
嵌入式大圣9 小时前
单片机UDP数据透传
单片机·嵌入式硬件·udp
云山工作室9 小时前
基于单片机的视力保护及身姿矫正器设计(论文+源码)
stm32·单片机·嵌入式硬件·毕业设计·毕设
嵌入式-老费9 小时前
基于海思soc的智能产品开发(mcu读保护的设置)
单片机·嵌入式硬件
qq_3975623111 小时前
MPU6050 , 设置内部低通滤波器,对于输出数据的影响。(简单实验)
单片机
liyinuo201711 小时前
嵌入式(单片机方向)面试题总结
嵌入式硬件·设计模式·面试·设计规范