STM32输出PWM波形错误解析

2023-05-16

一、背景

项目中需要用STM32F407输出4路PWM波形控制两个A4950模块,从而驱动2个直流电机。使用TIM1的在PE9、PE11、PE13、PE14上分别产生4路PWM波形,前两路(记作pwm1、pwm2,分别接A4950的IN1和IN2)控制电机1,后两路(记作pwm1、pwm2,分别接另一个A4950的IN1和IN2)控制电机2。

根据A4950的芯片手册,电机正转时,IN1给占空比不为0的pwm波形,IN2给占空比为100%的信号;电机反转时,IN1给占空比为100%的信号,IN2给占空比不为0的pwm波形。于是,配置TIM1的4路输出采用PWM1模式,有效电平为高电平。代码如下:

void PWM_TIM_Config(uint32_t Cycle)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStrcture;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(PWM_TIM_CLK,ENABLE); //使能TIM1时钟
	RCC_AHB1PeriphClockCmd(PWM_OUT_PORT_CLK,ENABLE); //使能GPIOE时钟
	
        //配置PE9
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_OType =GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Pin =PWM1_OUT_PIN ;
	GPIO_InitStructure.GPIO_Speed=GPIO_High_Speed;
	GPIO_Init(PWM1_OUT_PORT,&GPIO_InitStructure); 
	
        //配置PE11
	GPIO_InitStructure.GPIO_Pin =PWM2_OUT_PIN ;
	GPIO_Init(PWM2_OUT_PORT,&GPIO_InitStructure); 
	
        //配置PE13
	GPIO_InitStructure.GPIO_Pin =PWM3_OUT_PIN ;
	GPIO_Init(PWM3_OUT_PORT,&GPIO_InitStructure);

        //配置PE14
	GPIO_InitStructure.GPIO_Pin =PWM4_OUT_PIN ;
	GPIO_Init(PWM4_OUT_PORT,&GPIO_InitStructure); 
	
        //把PE9、PE11、PE13、PE14连接到TIM1
	GPIO_PinAFConfig(PWM1_OUT_PORT,PWM1_PINSOURCE,PWM1_AF);	
	GPIO_PinAFConfig(PWM2_OUT_PORT,PWM2_PINSOURCE,PWM2_AF);
	GPIO_PinAFConfig(PWM3_OUT_PORT,PWM3_PINSOURCE,PWM3_AF);	
	GPIO_PinAFConfig(PWM4_OUT_PORT,PWM4_PINSOURCE,PWM4_AF);	
        
        //TIM1时基配置,上数计数
	TIM_TimeBaseStructInit (&TIM_TimeBaseInitStrcture);
	TIM_TimeBaseInitStrcture.TIM_Period=  Cycle-1;
	TIM_TimeBaseInitStrcture.TIM_Prescaler =1;//2分频,84MHz
	TIM_TimeBaseInitStrcture.TIM_CounterMode =TIM_CounterMode_Up ;
	TIM_TimeBaseInitStrcture.TIM_ClockDivision=0;
	TIM_TimeBaseInitStrcture.TIM_RepetitionCounter =0;
	TIM_TimeBaseInit(PWM_TIM,&TIM_TimeBaseInitStrcture);
        
        //输出比较(OC1-OC4)配置:PWM1模式,有效电平为高
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1 ;
	TIM_OCInitStructure.TIM_OutputState =TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse =0;
	TIM_OCInitStructure.TIM_OCPolarity =TIM_OCPolarity_High;
	TIM_OC1Init(PWM_TIM,&TIM_OCInitStructure ); 
	TIM_OC2Init(PWM_TIM,&TIM_OCInitStructure );
	TIM_OC3Init(PWM_TIM,&TIM_OCInitStructure );
	TIM_OC4Init(PWM_TIM,&TIM_OCInitStructure );


	TIM_CtrlPWMOutputs(PWM_TIM ,ENABLE);//PWM输出使能
	
	TIM_OC1PreloadConfig (PWM_TIM,TIM_OCPreload_Enable);
	TIM_OC2PreloadConfig (PWM_TIM,TIM_OCPreload_Enable);
	TIM_OC3PreloadConfig (PWM_TIM,TIM_OCPreload_Enable);
	TIM_OC4PreloadConfig (PWM_TIM,TIM_OCPreload_Enable);
	
	TIM_ARRPreloadConfig (PWM_TIM,ENABLE);
	TIM_Cmd(PWM_TIM,ENABLE);
}

调试时发现,两个电机有一个无法控制方向,占空比和速度的关系也和预期的不一致,反复检查代码,百思不得其解。

二、问题分析

设置pwm1占空比为11.9%,pwm2占空比为0%,pwm3占空比为23.8%,pwm4占空比为0%,用示波器观察pwm1和pwm3的波形,发现波形如图1。这与设置的“PWM1模式,高电平为有效电平”应当产生的波形极性刚好相反。而且pwm2的波形为3.3v,pwm4的波形为0v,显然pwm2的输出极性也错了。

错误pwm波形
图1 错误pwm波形

与输出比较器输出的极性相关的寄存器时CCER,从Keil MDK中查看TIM1的CCER寄存器的状态,发现如图2所示。可以发现CC4P的值为0,CC1P到CC3P的值均为1,这表明输出比较器4是高电平为有效电平,输出比较器1到3是低电平是有效电平,这就和观察到的PWM波形输出一致了。但是程序中确实是把OC1到OC4的有效电平都设置成了高电平啊,为什么会这样呢?

错误的CCER
图2 错误的CCER寄存器值

在程序中设置断点(图3)观察结构体TIM_OCInitStructure的值,发现结构体各项的值如图4所示。

断点位置
图3 断点位置
错误的OCInitStructure值
图4 错误的OCInitStructure值

可以发现结构体中的TIM_OCNpolarity的值为2(即有效值为低电平),再看stm32f4xx_tim.c中TIM_OC1Init函数的代码:

图5 设置CC1P的代码
图6 设置CC1NP的代码

由于TIM_OCNPolarity为2,所以718行的语句运行后,CCER最后在第1bit位置被置1,即CC1P=1(事实上,把TIM_OCPolarity和TIM_OCNPolarity中的任何一个设置为了TIM_OCPolarity_Low,即值2,都会导致CC1P=1)。

显然,PWM波形错误是由于结构体TIM_OCInitStructure没有被正确的初始化引起的。那么为什么它没被正确的初始化呢?因为这里是在函数内部申明的结构体变量,因此是一个局部变量,局部变量分配内存时是不会被初始化为0的,因此其成员TIM_OCNPolarity这里就刚好不为0。

为了解决这个问题,在给TIM_OCInitStructure赋值之前,先调用初始化函数TIM_OCStructInit (&TIM_OCInitStructure),使其各成员变量初始化为默认值,然后再根据需要修改结构体成员的值。修改代码后,结构体TIM_OCInitStructure的值如图7所示,寄存器CCER的值在配置好后如图8所示,产生的波形如图9所示。

正确的TIM_OCInitStructure值
图7 正确的TIM_OCInitStructure值
正确的CCER值
图8 正确的CCER值
正确的PWM波形
图9 正确的PWM波形

三、结论

对于STM32编程中常见的用于初始化的结构体,例如TIM_TimeBaseInitTypeDef、TIM_OCInitTypeDef,一定要先调用相应的初始化函数(尤其是这些结构体作为局部变量时),例如TIM_TimeBaseStructInit、TIM_OCStructInit。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32输出PWM波形错误解析 的相关文章

  • gitee团队合作,上传文件到别人的Gitee仓库

    首先要确保在别人的Gitee项目中 项目创建人可以通过邀请拉其他人进入Gitee项目中 下面开始上传 第一步 xff0c 在任意位置 xff0c 基本上选择桌面 新建一个文件夹 xff0c 在里面点击右键 xff0c 选择 Git Bash

随机推荐