一位萌新为参加robomaster所做的前期准备–stm32基础(五)(PWM)
一. 实验完成目的:利用定时器输出pwm(脉冲宽度调制)即改变占空比,来实现对led灯亮度的调节,使其达到类似呼吸的效果(后期运用到摩擦轮电机中)
二. 方案:
① 对led的GPIO口参数进行配置,初始化io口为复用功能输出
② 需要运用到通用定时器,需对其进行打开相关时钟,设置分频系数,计数溢出值,计数模式0
③ 对应GPIO口输出pwm,通道与GPIO口要一一对应(有的要重映射配置,打开AFIO时钟,设置重映射)
④ 初始化输出比较参数(初始化pwm),使能定时器
三. 流程图
四. 主要实验代码
int main(){
u8 dir=1;
u16 pwmval=0; //调节ccr的值,进而控制空占比
//leds_init();
TIM4_PWM_Init(); //初始化定时器,pwm等
while(1){
sw_delay_ms(100); //延时100毫秒(很重要,否则看不出现象)
if(dir){
pwmval++;
}
else{
pwmval--;
}
if(pwmval==0){
dir=1;
}
if(pwmval>100){
dir=0;
}
TIM_SetCompare3(TIM4,pwmval); //改变ccr,调整空占比
}
}
void TIM4_PWM_Init(void){
TIM_TimeBaseInitTypeDef TIm_TimeBaseInitStruct;
TIM_OCInitTypeDef TIM_OC_struct;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//如果定时器通道与io口要复用映射(重映射),则要打开AFIO时钟
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_Init(GPIOB,&GPIO_InitStructure);
//配置GPIO,模式为复用推挽输出
GPIO_PinRemapConfig(GPIO_Remap_TIM4,ENABLE);
//设置重映射 (如果没有重映像则不需要开启)
TIm_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;
TIm_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
TIm_TimeBaseInitStruct.TIM_Period=200; TIm_TimeBaseInitStruct.TIM_Prescaler=0;
TIM_TimeBaseInit(TIM4,&TIm_TimeBaseInitStruct);
//初始化定时器(向上计数,周期,预分频值)
TIM_OC_struct.TIM_OCMode=TIM_OCMode_PWM1;
//选择定时器模式:TIM脉冲宽度调制模式1
TIM_OC_struct.TIM_OCNPolarity=TIM_OCPolarity_High;
//输出极性:TIM输出比较极性高
TIM_OC_struct.TIM_OutputNState=TIM_OutputState_Enable;
//比较输出使能
TIM_OC_struct.TIM_Pulse=0;
//设置待装入捕获比较寄存器的脉冲值
TIM_OC3Init(TIM4,&TIM_OC_struct);
TIM_OC3PreloadConfig(TIM4,TIM_OCPreload_Enable);
//使能预装载寄存器(精确控制输出波形完整性)
TIM_ARRPreloadConfig(TIM4, ENABLE);
//使能自动装载寄存器
TIM_Cmd(TIM4,ENABLE); //使能定时器
}
五. 相关知识
① 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。
② PWM模式1-在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)。
PWM模式2-在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为有效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平
③
④ Pwm常用函数库
GPIO_PinRemapConfig()
//如果引脚与通道有重映射要调用此函数,且打开AFIO时钟
TIM_OC3Init()
//初始化pwm参数
TIM_OC3PreloadConfig()
//使能预装载寄存器
TIM_ARRPreloadConfig()
//使能自动装载寄存器
TIM_SetCompare3()
//不断改变ccr来调节占空比
六. 总结
本次实验关键在于掌握pwm的相关配置,以及对于定时器与io口引脚的复映射,理解了pwm的工作原理,先掌握呼吸灯,对于摩擦轮电机只需输入相应的参数即可。本次实验一开始led常亮,找了好几天,对比一些代码发现配置没有什么错误,最终发现没有在每次循环时加延时函数,没有延时100毫秒,导致没有出现呼吸的现象。
Pwm配置步骤:
① 使能定时器4和相关IO口时钟。
使能定时器4时钟:RCC_APB1PeriphClockCmd();
使能GPIO时钟:RCC_APB2PeriphClockCmd();
② 初始化IO口为复用功能输出。函数:GPIO_Init();
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
③ 如果需要重映射,需要开启AFIO时钟。同时设置重映射。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM4, ENABLE);
④ 初始化定时器:ARR,PSC等:TIM_TimeBaseInit();
⑤ 初始化输出比较参数:TIM_OC3Init();
⑥ 使能预装载寄存器: TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);
⑦ 使能定时器。TIM_Cmd();
⑧ 不断改变比较值CCRx,达到不同的占空比效果:TIM_SetCompare3();