(8条消息) 9、STM32的PWM的原理与使用(内附代码)
1、PWM是什么?
是脉冲宽度调制,简称脉宽调制。利用微处理器数字输出对模拟电路进行控制的一种有效的技术,就是对脉冲宽度的控制。
这里说的脉冲,就是我们产生的方波。方波就是N个这样的周期连续的产生。
一个周期内高电平持续的时间就是脉冲宽度(脉宽),而PWM(脉冲宽度调制)就是控制一个周期内的高电平的持续时间。
2、简单的PWM的原理示意图
CNT:是当前值寄存器,计数寄存器。
ARR:是自动重载寄存器(初始化设定)。
CCRx:比较值寄存器(TIM_SetCompare1()设定修改占空比)。
假定定时器工作在向上计数PWM模式下:
当CNT<CCRx时,引脚输出0,当CNT>=CCRx时,引脚输出1。
当CNT的值小于CCRx的时候,IO输出低电平(0),
当CNT值大于或等于CCRx的时候,IO输出高电平(1),
当CNT的值达到ARR的时候,就会重新归零,然后重新向上计数,依次循环。
改变CCRx的值就可以改变PWM的输出的占空比。改变ARR的值,就可以改变PWM的输出的频率,这就是PWM的输出原理。
3、寄存器工作流程:
PWM 模式
脉冲宽度调制模式可以生成一个信号,该信号频率由 TIMx_ARR 寄存器值决定,其占空比由 TIMx_CCRx 寄存器值决定。
通过向 TIMx_CCMRx 寄存器中的 OCxM 位写入 110(PWM 模式 1)或 111(PWM 模式 2) ,可以独立选择各通道 (每个 OCx 输出对应一个 PWM)的 PWM 模式。必须通过将TIMx_CCMRx 寄存器中的 OCxPE 位置 1 使能相应预装载寄存器,最后通过将 TIMx_CR1寄存器中的 ARPE 位置 1 使能自动重载预装载寄存器(在递增计数或中心对齐模式下)。
由于只有在发生更新事件时预装载寄存器才会传送到影子寄存器,因此启动计数器之前,必须通过将 TIMx_EGR 寄存器中的 UG 位置 1 来初始化所有寄存器。OCx 极性可使用 TIMx_CCER 寄存器的 CCxP 位来编程。既可以设为高电平有效,也可以设为低电平有效。 OCx 输出通过将 TIMx_CCER 寄存器中的 CCxE 位置 1 来使能。有关详细信息,请参见 TIMx_CCERx 寄存器说明在 PWM 模式(1 或 2)下, TIMx_CNT 总是与 TIMx_CCRx 进行比较,以确定是TIMx_CNT =< TIMx_CCRx。
因为计数器采用递增方式计数,所以定时器能够在边沿对齐模式下生成 PWM。
4、PWM 边沿对齐模式
以下以 PWM 模式 1 为例。只要 TIMx_CNT < TIMx_CCRx, PWM 参考信号 OCxREF 便为高电平,否则为低电平。如果 TIMx_CCRx 中的比较值大于自动重载值(TIMx_ARR 中),则 OCxREF 保持为“1”。如果比较值为 0, 则 OCxRef 保持为“0”。 图 183 举例介绍边沿对齐模式的一些 PWM 波形 (TIMx_ARR=8)。
5、PWM步骤-灯光亮度控制:
查看LED的原理图:
//①根据原理图找到4个引脚: PF9可以使用TIM14_CH1,表示可以使用定时器14的通道1产生PWM输出。 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; // 定义的TIM属性结构体变量 GPIO_InitTypeDef GPIO_InitStruct; // 定义GPIO类型变量 TIM_OCInitTypeDef TIM_OCInitStruct; // 定义复用功能的变量 ②// 1.初始化时钟:TIM14 和 PF9 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); /* TIM3 clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE); // 2.配GPIO引脚为复用功能 /* GPIOC Configuration: TIM14 CH1 (PF9) */ GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; // 选择引脚为PF9 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; // 设置为复用功能 GPIO_InitStruct.GPIO_Speed = GPIO_High_Speed; // 设置输出速度为100MHz GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; // 设置为推挽输出 GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; // 设置为上拉输出 GPIO_Init(GPIOC, &GPIO_InitStruct); // 安装参数 // 3.将TIM和引脚的复用功能连接:TIM14和PF9连接起来 GPIO_PinAFConfig(GPIOF, GPIO_PinSource9, GPIO_AF_TIM14); // 4.配置TIM定时器的参数 TIM_TimeBaseInitStruct.TIM_Period = 100-1; // 设置重装载值 ARR(控制频率) TIM_TimeBaseInitStruct.TIM_Prescaler = 8400-1; // 设置预分频系数:周期(次) 100Hz == 100us TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; // 设置再分频值:TIM_CKD_DIV1就是不分频 TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; // 设置计数模式 TIM_TimeBaseInit(TIM14, &TIM_TimeBaseInitStruct); // 5.配置复用功能:PWM TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; // 配置为PWM模式1 TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; // 开启输出使能 //TIM_OCInitStruct.TIM_Pulse = CCR1_Val; // 初始化配置比较值寄存器 TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; // 配置为高电平有效 // 6.TIM14通道1初始化 TIM_OC1Init(TIM14, &TIM_OCInitStruct); // TIM14通道1初始化 // 7.设置自动重载比较值CCR1初值,不断产生PWM脉冲 TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable); // 8.设置自动重装载值(ARR),不断产生PWM脉冲 TIM_ARRPreloadConfig(TIM14, ENABLE); /* 9.使能定时器14 */ TIM_Cmd(TIM14, ENABLE); // 10.使能TIM1PWM输出(高级定时器) //TIM_CtrlPWMOutputs(TIM1, ENABLE)
设置比较值函数
void TIM_SetCompareX(TIM_TypeDef* TIMx, uint16_t Comparex);