20200808-PWM输出-Tim定时器-stm32

本文详细介绍了STM32微控制器中PWM的工作原理及其应用。覆盖了PWM简介、STM32定时器输出通道引脚配置、PWM初始化代码解析、与定时器中断的区别等内容。并提供了实际代码示例,帮助读者深入理解STM32 PWM输出的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


用于德飞莱开发板。参考代码为正点原子代码

pwm 工作原理

PWM 简介

脉冲宽度调制模式(PWM模式),就是可以产生一个由TIMx_ARR寄存器确定频率,由TIMx_CCRx寄存器确定占空比的信号。
STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。 其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用时器也能同时产生多达 4路的 PWM 输出,这样,STM32 最多可以同时产生 30 路 PWM 输出!
在这里插入图片描述

STM32定时器输出通道引脚

在这里插入图片描述

代码

主函数调用

TIM_SetCompare2 函数为核心代码,修改占空比

//PWM调用
 	u16 led0pwmval=0;
	u8 dir=1;	
 	TIM3_PWM_Init(900,0);	 //0代表不分频。PWM频率=72000000/900=80Khz
while(1)
{																//PWM改变占空比
	 	delay_ms(10);	 
		if(dir)led0pwmval++;
		else led0pwmval--;

 		if(led0pwmval>300)dir=0;
		if(led0pwmval==0)dir=1;										 
		TIM_SetCompare2(TIM3,led0pwmval);		   
}

pwm初始化代码

//TIM3 PWM部分初始化 
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM3_PWM_Init(u16 arr,u16 psc)
{  
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);	//使能定时器3时钟
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
	
	GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射  TIM3_CH2->PB5    
 
   //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形	GPIOB.5
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
 
   //初始化TIM3
	TIM_TimeBaseStructure.TIM_Period = arr-1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
	
	//初始化TIM3 Channel2 PWM模式	 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2

	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器
 
	TIM_Cmd(TIM3, ENABLE);  //使能TIM3
	

}

与tim定时器中断的区别

定时器中断

PWM

1图为定时器中断,2图为PWM输出
PWM输出下不需要用定时器中断,也不用设置NVIC中断优先级
PWM输出下需要开启AFIO端口复用。若用到映射还要开启端口映射
PWM输出下需要对PWM模式参数进行设置

注意

不同输入通道有不同的端口(固定的),有的需要重映像
注意写代码时通道不同调用函数也有不同

设置占空比的函数也不一样
在这里插入图片描述

代码讲解

开启 TIM3 时钟 以及复用功能时钟置 ,配置 PB5 为复用输出。要使用 TIM3,我们必须先开启 TIM3 的时钟,这点相信大家看了这么多代码,应该明白了。这里我们还要配置 PB5 为复用输出,这是因为 TIM3_CH2 通道将重映射到 PB5 上,PB5属于复用功能输出

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //复用时钟使能

STM32定时器输出通道引脚在这里插入图片描述

如果端口涉及重映射问题还需要:

GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);

初始化 TIM3, 设置 TIM3 的 的 ARR 和 和 PSC 。在开启了 TIM3 的时钟之后,我们要设置 ARR 和 PSC 两个寄存器的值来控制输出 PWM 的周期。当 PWM 周期太慢(低于 50Hz)的时候,我们就会明显感觉到闪烁了。因此,PWM 周期在这里不宜设置的太小。这在库函数是通过 TIM_TimeBaseInit 函数实现的,调用的格式为:

TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化 TIMx 的

设置 TIM3_CH2 的 的 PWM 模式,使能 TIM3 的 的 CH2 输出。 。接下来,我们要设置 TIM3_CH2 为 PWM 模式(默认是冻结的),因为我们的 DS0 是低电平亮,而我们希望当 CCR2 的值小的时候,DS0 就暗,CCR2 值大的时候,DS0 就亮,所以我们要通过配置 TIM3_CCMR1 的相关位来控制 TIM3_CH2 的模式。在库函数中,PWM 通道设置是通过函数 TIM_OC1Init()~TIM_OC4Init()来设置的,不同的通道的设置函数不一样,这里我们使用的是通道 2,所以使用的函数是

TIM_OCInitTypeDef TIM_OCInitStructure; 
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择 PWM 模式 2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性高
TIM_OC2Init(TIM3, &TIM_OCInitStructure); //初始化 TIM3 OC2
5) )能 使能 TIM3 。
在完成以上设置了之后,我们需要使能 TIM3。使能 TIM3 的方法前面已经讲解过:
TIM_Cmd(TIM3, ENABLE); //使能 TIM3

参数 TIM_OCMode 设置模式是 PWM 还是输出比较,这里我们是 PWM 模式。参数 TIM_OutputState 用来设置比较输出使能,也就是使能 PWM 输出到端口。参数 TIM_OCPolarity 用来设置极性是高还是低。其他的参数 TIM_OutputNState,TIM_OCNPolarity,TIM_OCIdleState 和 TIM_OCNIdleState 是高级定时器 TIM1 和 TIM8 才用到的。

修改占空比。
最后,在经过以上设置之后,PWM 其实已经开始输出了,只是其占空比和频率都是固定的,而我们通过修改 TIM3_CCR2 则可以控制 CH2 的输出占空比。继而控制 DS0 的亮度。在库函数中,修改 TIM3_CCR2 占空比的函数是

TIM_SetCompare2(TIM3,pwmval);

参考连接

【STM32】通用定时器的PWM输出(实例:PWM输出)_Yngz_Miao的博客-优快云博客_stm32 pwm输出
https://blog.youkuaiyun.com/qq_38410730/article/details/79996222
STM32定时器PWM输出_Azuresmh的博客-优快云博客_stm32定时器pwm
https://blog.youkuaiyun.com/Azuresmh/article/details/87028668

add

  /* Time base configuration */
        TIM_TimeBaseStructure.TIM_Period = 999;  //1KHz
        TIM_TimeBaseStructure.TIM_Prescaler = 0;
        TIM_TimeBaseStructure.TIM_ClockDivision = 0;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
        //TIM2预分频设置:1MHZ,APB1分频系数2,输入到TIM3时钟为36MHzx2 = 72MHz  
        TIM_PrescalerConfig(TIM2,71, TIM_PSCReloadMode_Immediate);               

好好理解公式f=1/T(频率=1/周期)
TIM_TimeBaseStructure.TIM_Period里面装的就是周期
TIM_TimeBaseStructure.TIM_Prescaler装的是预分频系数,用来驱动计数器自加的
如果TIM_Period装的数值是999并且TIM_Prescaler装的是71
那么计数器就会以1us记一次,记满1000次(0-999是1000次),那么记满的时间就是1000us,相对应的周期就是1000us
所以频率=1000000/1000=1000Hz,为什么是1000000,因为公式的单位是秒,你要化成us才能正确计算
(71在最后一行)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

开心超人dev

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

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

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

打赏作者

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

抵扣说明:

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

余额充值