我们首先需要知道的是PWM的产生方式
通过STM32控制板,有两种方式能产生PWM,第一是利用普通IO口输出PWM,第二种是利用定时器的PWM的IO口或复用IO口。
第一种为普通IO口产生PWM
普通IO口如何产生一个pwm?其实就是通过一个高低电平周期性的变化。这种思想很重要,确定频率就可以确定周期(T=1/f)也就是在一个周期内产生pwm的时间可以确定下来了。
如何改变占空比?确定了时间,高电平的时间不就是想要的占空比么,比如要产生一个频率1khz,占空比为70%的pwm,根据频率我们知道了pwm的周期为1ms,产生一个占空比为70%的不就是0.7ms的时间给高电平么,(我们用定时器中断的方式,使0.1ms产生一次更新中断,计数中断次数,中断处理函数前七次中断都给高电平就ok了。
我们用的是第二种
设置输出时是按输出通道分的库函数。即需要初始化哪个通道,就调用哪个函数。不同的通道对应的GPIO口也是不一样的。
也就是说,使用这个PWM波形,是用来等效地实现一个模拟信号的输出。
比如我们以一个很快的频率给电机进行通电、断电,那么电机的速度就能维持在一个速度中。
LED在熄灭时,由于余晖和人眼视觉暂留现象,LED不会应马熄灭。而是有定的惯性,过一小段时间才会熄灭。电机也是。当电机断电时。电机的转动不会立马停止。这就是惯性的系统。
分析捕获/比较通道的输出部分
在这个图的左边输入的数据就是CNT和CRR1,他们进行比较,当满足CNT>CRR1或CNT=CRR1时,进入输出模式控制器。
输出模式控制器改变它输出OC1ref(reference参考信号)的高低电平。
接着这个ref信号往后转递。
首先他可以转递到上部分的主模式控制器中。可以把这个ref映射到主模式的TRGO输出上去。
主要是进行下面这一路。
这一个模块是一个极性选择电路。如果给CC1P写0,信号往上走,电平信号不反转。来啥样走啥样。如果给CC1P写1,信号进入下面一路,通过非门取反,电平信号反转。
这就是进行极性选择,就是选择要不要反转高低电平。
然后进入使能电路,决定要不要输出。
然后进入OC1引脚,就是TIMx_CH1通道的引脚,通过对引脚定义的查询可以知道具体是对应哪个GPIO口。
然后来细看一下输出比较模式控制器,这个是这个电路中非常重要的部分。
在这个模块里面可以选择多种模式来更加灵活地控制ref的输出,通过下面的寄存器进行配置。
第一个模式是冻结模式,即CNT=CCR时维持原状态。假如你正在输出PWM波形,想暂停,可以设置成这个模式。切换为冻结模式后,输出暂停。并且高低电平维持暂停时的状态保持不变。
接下来的2,3,4模式,配时置有效电平,配时置无效电平,匹配时电平翻转。这个有效电平和无效电平。一般是高级定时器里面的一个说法,可以暂且理解为,置有效电平就是置高电平。置无效电平就是置低电平。第四个模式匹配时电平翻转可以方便得输出一个频率可调且占空比始终为50%的波形。
第五、六个模式强制为无效电平和强制为有效电平。这两个模式和冻结模式相似。如果你想暂停波形输出,并且在暂停期间保持低电平或者高电平,就可以设置成这两个强制输出模式。
最后的两个模式也是最有用的模式,他们可以用于输出频率和占空比都可调的PWM波形。PWM模式1和PWM模式2只有ref置有效电平和无效电平换了一下。PWM模式2实际上就是PWM1模式输出的取反。
此部分转自基于STM32呼吸灯(PWM)_叫什么呀的博客-CSDN博客_stm32呼吸灯
PA1/USART2_RTS/
ADC_IN1/TIM2_CH2
所以我们要把pa1开复用,复用为TIM2_CH2,TIM2_CH2为捕获,比较的通道
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //Ñ¡ÔñPWMģʽ2
与TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;搭配使用,设置有效电平为高电平并在周期内进行分配
TIM_OCInitStructure.TIM_Pulse=500;//设置占空比时间
如果后续需要更改占空比则需要配置
TIM_PrescalerConfig与TIM_OC3PreloadConfig区别
TIM_OC3PreloadConfig:使能预加载寄存器PWM占空比不一样,IO口电压就不一样,灯的亮度就不一样,配置CCR寄存器预装功能。
这个预装功能。就是影子寄存器,
就是你写入的值不会立即生效。而是在更新事件才会生效
具体原理为,通过改变单位时间内脉冲的个数可以实现调频;通过改变占空比可以实现调压。占空比越大,所得到的平均电压也就越大,幅值也就越大;占空比越小,所得到的平均电压也就越小,幅值也就越小
(脉冲通常是指电子技术中经常运用的一种象脉搏似的短暂起伏的电冲击(电压或电流)。脉冲宽度是指电子领域中,脉冲所能达到最大值所持续的周期。)
人眼太慢了,所以灯如果以非常快的速度闪烁,你只能看到亮度变化,而闪烁你是看不到的,这个就是通过PWM送出不同的脉宽,也是LED的灰度实现原理
TIM_PrescalerConfig(TIM2,71, TIM_PSCReloadMode_Immediate);
/**
* @brief Configures the TIMx Prescaler.
* @param TIMx: where x can be 1 to 17 to select the TIM peripheral.
* @param Prescaler: specifies the Prescaler Register value
* @param TIM_PSCReloadMode: specifies the TIM Prescaler Reload mode
* This parameter can be one of the following values:
* @arg TIM_PSCReloadMode_Update: The Prescaler is loaded at the update event.
* @arg TIM_PSCReloadMode_Immediate: The Prescaler is loaded immediately.
* @retval None
*/
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode)
{
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
assert_param(IS_TIM_PRESCALER_RELOAD(TIM_PSCReloadMode));
/* Set the Prescaler value */
TIMx->PSC = Prescaler;
/* Set or reset the UG Bit */
TIMx->EGR = TIM_PSCReloadMode;
}
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); //你写入的CCRx值,立即生效 或者在更新事件之后生效,你就会用到这个预装载函数
*
* @brief Enables or disables the TIMx peripheral Preload register on CCR3.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_OCPreload: new state of the TIMx peripheral Preload register
* This parameter can be one of the following values:
* @arg TIM_OCPreload_Enable
* @arg TIM_OCPreload_Disable
* @retval None
*/
@brief启用或禁用CCR3上的TIMx外围预加载寄存器。
*@param TIMx:其中x可以是1、2、3、4、5或8以选择TIM外围设备。
*@param TIM_OCPreload:TIMx外围预加载寄存器的新状态
*此参数可以是以下值之一:
*@arg TIM_OCPreload_启用
*@arg TIM_OCPreload_禁用
*@retval无
void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload)
{
uint16_t tmpccmr2 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_OCPRELOAD_STATE(TIM_OCPreload));
tmpccmr2 = TIMx->CCMR2;
/* Reset the OC3PE Bit */
tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3PE);
/* Enable or Disable the Output Compare Preload feature */
tmpccmr2 |= TIM_OCPreload;
/* Write to TIMx CCMR2 register */
TIMx->CCMR2 = tmpccmr2;
}