1、系列目录
2、原理
(1)呼吸灯原理
呼吸灯在手机上非常常见,现象就是灯光暗->亮->暗的过程,由现象可以倒推出原理:灯的电压小->大->小。但是这里为什么选PWM控制电压的大小呢?
因为STM32中的TIM可以输出可控占空比的PWM波形,由PWM的占空比(高电平时间与整个周期的比值)来控制输出电压的大小。
(2)PWM占空比改变原理
在STM32的TIM寄存器中,有CCR寄存器,可以控制某一通道的CCR值,从而改变占空比
由图片可以看出我们只需要控制CCR和ARR之间的数值关系,即可控制IO口输出的PWM波形。
3、程序设计逻辑
- 选择合适的定时器通道。我使用的正点原子精英板,TIM3_CH2通道的部分重映射端口与LED0的端口一样(PB5)。
- 设置端口重映射,这里我们在配置的时候一定要注意你选择的是部分重映射还是完全重映射,因为选择的模式不一样,重映射的端口也不一样。
- 开启复用端口时钟(AFIO)
- 配置GPIO端口为复用推挽输出
- 配置TIM定时器,基础配置,OC配置
- 通过库函数使CCR渐变,通过IM_SetCompare2()函数使输入CCR2的值渐增,达到最大值后渐减。
如果不理解什么是部分重映射和完全重映射,点击这里
4、OC结构体分析
既然用到TIM定时器的输出模式,那么在初始化的时候肯定要使用到定时器的TIM_OCInitTypeDef结构体函数。
typedef struct
{
uint16_t TIM_OCMode; /*选择定时器通道输出模式 */
uint16_t TIM_OutputState; /*输出使能*/
uint16_t TIM_OutputNState; /*互补通道输出使能
@note This parameter is valid only for TIM1 and TIM8. */
uint16_t TIM_Pulse; /*配置CCR的值,between 0x0000 and 0xFFFF */
uint16_t TIM_OCPolarity; /*输出极性*/
uint16_t TIM_OCNPolarity; /*互补通道输出极性
@note This parameter is valid only for TIM1 and TIM8. */
uint16_t TIM_OCIdleState; /*空闲状态输出比较极性
@note This parameter is valid only for TIM1 and TIM8. */
uint16_t TIM_OCNIdleState; /*!< 空闲状态互补通道输出比较极性
@note This parameter is valid only for TIM1 and TIM8. */
} TIM_OCInitTypeDef;
可以看到结构体中有TIM_OutputNState;TIM_OCNPolarity;TIM_OCNIdleState;TIM_OCIdleState的配置只与高级定时器TIM1和TIM8相关,这些配置是与已有的通道做一个互补的信号,可以输出三相控制无刷电机、刹车、死区之类的功能。不做赘述,后面使用的时候会继续分析。
TIM_OCMode:定时器通道输出模式,一般选择PWM1或PWM2
TIM_OutputState:输出标志位,输出使能TIM_OutputState_Enable
TIM_Pulse:CCR值
TIM_OCPolarity:输出极性,在未计数到CCR时,输出高电平or低电平
5、代码示例
//TIM3 通道2 PB5
void TIM_Config(u16 arr,u16 psc)
{
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_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE);
//PB5 配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
printf("GPIO is ready\r\n");
//TIM5基础配置
//计时器时钟 = APB总线时钟/分频因子
// psc
TIM_TimeBaseStructure.TIM_Period = arr;//重装载值/最大计数值
TIM_TimeBaseStructure.TIM_Prescaler = psc;//预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
//TIM3 PWM配置
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;//PWM2模式
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//允许IO端口输出
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性,高
TIM_OC2Init(TIM3,&TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);
TIM_Cmd(TIM3,ENABLE); //使能TIM3
printf("TIMer is ready\r\n");
//main.c
u16 led0pwmval=0;
u8 dir=1;
TIM_Config(699,0);
printf("The experiment bigan !\r\n");
while(1)
{
delay_ms(10);
if(dir)led0pwmval++;
else led0pwmval--;
if(led0pwmval>300)dir=0;
if(led0pwmval==0)dir=1;
TIM_SetCompare2(TIM3,led0pwmval);
}
6、总结
本节用的TIM3普通定时器输出可变占空比的PWM波形,体现在LED灯的亮度表现上。PWM的应用非常广泛,并且本节也是为了下一节使用PWM控制电调,实现对无刷电机的控制做基础,没有难点,只需要理解PWM占空比的改变原理和方法。