目的:通过实现呼吸灯分析PWM波形
代码:
PWM.c
#include "stm32f10x.h" // Device header/*** @brief PWM初始化* @param 无* @retval 无
*/
void PWM_Init(void)
{// 使能IO和TIM2RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 初始化GPIOAGPIO_InitTypeDef GPIO_InitStructure;// 必须使用GPIO_Mode_AF_PP, 使用片上外设的输出替代输出数据寄存器的输出. 因此使用复用推挽输出代替普通推挽输出GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);// 初始化时基单元TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; // ARRTIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1; // PSCTIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);// 初始化输出比较寄存器TIM_OCInitTypeDef TIM_OCInitStructure;TIM_OCStructInit(&TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;TIM_OCInitStructure.TIM_Pulse = 0;TIM_OC1Init(TIM2, &TIM_OCInitStructure);// 运行控制TIM_Cmd(TIM2, ENABLE);
}/*** @brief 设置脉冲宽度. 占空比=Compare1/TIM_TimeBaseInitStructure.TIM_Period* @param * @retval
*/
void PWM_SetCompare1(uint16_t Compare1)
{TIM_SetCompare1(TIM2, Compare1);
}
main.c
#include "stm32f10x.h" // Device header
#include "OLED.h"
#include "Delay.h"
#include "PWM.h"uint16_t Compare1;int main(void)
{OLED_Init();PWM_Init();while(1){PWM_SetCompare1(Compare1);if(Compare1 >= 100){Compare1 = 0;}Compare1 += 20;Delay_ms(10);}
}
逻辑分析仪结果
可以看到呼吸灯的占空比从20%到100%,且周期T=1ms。
下面用C1代表Compare1,CCR代表捕获/比较寄存器值,下图是使用代码逻辑分析的各变量值及变化关系
C1 CCR C1 占空比 持续时间
0 0 20 0% 10ms
20 20 40 20% 10ms
40 40 60 40% 10ms
60 60 80 60% 10ms
80 80 100 80% 10ms
100 100 0 100% 10ms
0 0 20 0% 10ms
...
分析
这里设置了ARR自动重装寄存器值为100,预分频系数为720,即由TIMx定时器输出的频率f=72MHz/100/720=1000Hz,因此周期T=1/f=1ms。所以我们看到的每个周期都是t(高电平)+t(低电平)=1ms。
占空比=t(高电平)/T,这里TIMx定时器使用上升沿模式,计数器值从0到ARR后重装载再次变为0,那么这个ARR值相当于周期(的缩放),那么占空比=TIM_Pulse/TIM_Period 。TIM_Period =100。
在main.c
中,Compare1 从0递增到100再次变为0,也就是,CCR的值从0递增到100再次变为0,通过控制这个CCR实现对有效电平和无效电平控制。我认为这个电平应该是从最开始的无效电平开始的,但是我采集出来的是20%占空比开始的,因此尝试复位后,终于看到完整波形如下。
main.c
呼吸灯代码如下. 分析同上.
#include "stm32f10x.h" // Device header
#include "OLED.h"
#include "Delay.h"
#include "PWM.h"uint8_t i;int main(void)
{OLED_Init();PWM_Init();while(1){for(i = 0; i<=100; i++){PWM_SetCompare1(i);Delay_ms(10);}for(i = 0; i<=100; i++){PWM_SetCompare1(100 - i);Delay_ms(10);}}
}
参考:
PWM驱动LED呼吸灯、舵机、直流电机