理清思路
- 确定使用的定时器(本文里为定时器1)
- 确定输出通道(本文里为CH1)
- 根据所选用的输出端口确定重映射关系(本文里使用PA8,采用部分重映射)
*注意
:本文里所使用的是定时器1
,其时钟信号来源于APB2
时钟,而stm32f103里大部分定时器的时钟信号源来自APB1
时钟,并且由于定时器1
属于高级定时器与普通定时器配置上略有不同,请读者根据自己的需要调整代码。
初始化工作
- 使能并初始化时钟
- 使能并初始化GPIO
- 使能AFIO,配置重映射
代码
void PWM_timer1_PA8_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef OCInit;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1|
RCC_APB2Periph_GPIOA|
RCC_APB2Periph_AFIO,ENABLE);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM1, ENABLE);
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Prescaler=0;
TIM_TimeBaseStructure.TIM_Period=1000;
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);
TIM_CtrlPWMOutputs(TIM1,ENABLE);//使用高级定时器输出PWM时需要这条代码,如果是普通定时器则不需要这条代码
OCInit.TIM_OCMode=TIM_OCMode_PWM1;
OCInit.TIM_OCPolarity=TIM_OCPolarity_High;
OCInit.TIM_Pulse = 500;
OCInit.TIM_OutputState=TIM_OutputState_Enable;
TIM_OC1Init(TIM1,&OCInit);
TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);
TIM_Cmd(TIM1,ENABLE);
}
代码详解
GPIO和定时器部分的配置在我之前的文章里都已经讲过了,下面的内容将会对定时器的PWM相关的内容着重分析。
需要注意的是:
GPIO的引脚视情况需要配置为复用推挽输出模式
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
重映射函数GPIO_PinRemapConfig(GPIO_PartialRemap_TIMx, ENABLE);
根据手册可知,如果我们想让PA8作为PWM的输出端口,那么可以对定时器1做部分重映射或者不做重映射。
高级定时器的刹车和死区寄存器(TIMx_BDTR)
对于普通定时器来说是不需要下面这条代码的,但是对于高级定时器来说,如果你想输出PWM,那么就需要下面这条代码来配置刹车和死区寄存器。
TIM_CtrlPWMOutputs(TIM1,ENABLE);
关于刹车和死区寄存器的说明本章不做重点讨论,如果你感兴趣可自行阅读下面寄存器说明:
捕获/比较输出配置
OCInit.TIM_OCMode=TIM_OCMode_PWM1;
OCInit.TIM_OCPolarity=TIM_OCPolarity_High;
OCInit.TIM_Pulse = 500;
OCInit.TIM_OutputState=TIM_OutputState_Enable;
TIM_OC1Init(TIM1,&OCInit);
TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);
这一部分代码配置了比较输出通道的输出模式、极性、使能(默认情况下,如果没有指定’‘OCInit.TIM_Pulse = 500’',初始化之后占空比为0,否则为500/1000),然后初始化比较输出通道1并使能预加载功能。
修改占空比
TIM_SetCompare1(TIMx,X);//修改定时器x通道1的占空比
TIM_SetCompare2(TIMx,X);//修改定时器x通道2的占空比
TIM_SetCompare3(TIMx,X);//修改定时器x通道3的占空比
TIM_SetCompare4(TIMx,X);//修改定时器x通道4的占空比
呼吸灯的实现
下为简略版,循环修改占空比实现呼吸灯效果代码
int main(void)
{
delay_init();
PWM_timer1_PA8_Init();
while (1)
{
TIM_SetCompare1(TIM1,1000);
delay_ms(100);
TIM_SetCompare1(TIM1,500);
delay_ms(100);
TIM_SetCompare1(TIM1,200);
delay_ms(100);
TIM_SetCompare1(TIM1,0);
delay_ms(100);
TIM_SetCompare1(TIM1,200);
delay_ms(100);
TIM_SetCompare1(TIM1,500);
delay_ms(100);
}
}
感谢阅读
下附上效果展示:
stm32f103呼吸灯