STM32笔记之 PWM(脉宽调制)
写在前面:
本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。
目录
一、PWM简介
脉冲宽度调制(英语:Pulse Width Modulation,缩写:PWM),简称脉宽调制,是将模拟信号变换为脉冲的一种技术,一般变换后脉冲的周期固定,但脉冲的工作周期会依模拟信号的大小而改变。
一般我们常用的 PWM技术是用来调光或者调速的,这也是最最常见的。
二、STM32F1中对 PWM的支持
在 STM32F1里面,PWM的生成是由 Timer输出的,但并不是所有的 Timer都支持;注意,这里说的是利用硬件技术产生 PWM,其制造出来的 PWM频率是非常可观,至于用软件定时控制 IO输出脚,即所谓的软件 PWM技术,这里就不阐述了。
从上面得知,STM32F1的 Timer是可以产生 PWM的,但并不是所有的 Timer都支持;所以,翻看一下手册,可以得知,支持 PWM硬件输出技术的 Timer有 “通用定时器” 和 “高级控制定时” 这两款类型,而对于 “基本定时器” 是并没有 PWM硬件输出技术的,所以在实际应用中要稍微注意一下,以免造成资源分配不合理。
1、通用定时器(TIM2 ~ TIM5)
每个定时都有 4个独立通道作为输出:
2、高级控制定时器(TIM1 & TIM8)
该款定时器可产生7路 PWM输出:
3、基本定时器(TIM6 & TIM7)
有关定时器的讲解,可以看之前的篇章:STM32笔记之 Timer(定时器)
三、PWM计数模式
- 边沿对齐模式
1、向上计数
2、向下计数
- *对齐模式
四、工作原理
以向上计数为例:
计数值以每周期固定从 Bottom开始计数,一直累加到 Top,然后再重新计数;只要不停止运行,便如此往复循环;从 Bottom累加到 Top为一个周期,为了制造出 PWM脉冲,而我们要做的就是设置 Compare的值,这样一来,就多了个 Compare参考值,也可以说是分割值;在计数的时候,每每累加一次计数,都跟 Compare值作比较,当计数值与 Compare值相同时,就控制输出状态与之相反,从而得到上图中 Output的图线。
五、PWM输出的模式
上面提到,Compare值作比较,当计数值与 Compare值相同时,就控制输出状态与之相反;因此,就会出现两种占空比的状态,一种是上图的当 Compare到 Top之间输出为高电平,另一种则是与之相反的 Bottom至 Compare之间为高电平.
那么对应在 STM32中,其状态确定在 TIMx_CCMRx寄存器位 6:4 的 OCxM[2:0]中:
注意:STM32中的PWM模式只是区别什么时候是有效电平,但并没有确定是高电平有效还是低电平有效。这需要结合 CCER寄存器的 CCxP位的值来确定。
六、例程演示
下面以 TIM3的 ch3、4作为例子:
#define TIME3_ARR 624 // 自动重装载寄存器周期值
#define TIME3_PSC 71 // TIMx时钟频率预分频值
#define TIME3_PULSE (uint16_t)((TIME3_ARR+1) *0.6 - 1) // 比较寄存器值
uint16_t Time3_CCR3_Val = TIME3_PULSE;
uint16_t Time3_CCR4_Val = TIME3_PULSE;
void TIM3_PWM_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStructure.GPIO_Pin = LR_SETP_MOTOR_PUL_PIN | PP_SETP_MOTOR_PUL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure); // IO口配置
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = TIME3_ARR;
TIM_TimeBaseStructure.TIM_Prescaler = TIME3_PSC; // 1600Hz
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); // 定时器基本配置
/* PWM1 Mode configuration: Channel3 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = Time3_CCR3_Val;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC3Init(TIM3, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
/* PWM1 Mode configuration: Channel4 */
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = Time3_CCR4_Val;
TIM_OC4Init(TIM3, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM3, ENABLE);
/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE);
}
本文地址:https://blog.csdn.net/qq_42992084/article/details/108547321
下一篇: 用c++图形库编写的双人打气球