STM32学习笔记:PWM互补输出(无刷直流电机驱动控制)

需要达成的目的为CH1通道输出PWM波,CH1N通道输出高电平等。

最新方法已在新博客贴出,更为简便。

==========================以下为较为复杂的初始方法===========================

最近科研训练在做无刷电机的控制。

需要达成的目的为CH1通道输出PWM波,CH1N通道输出高电平等。

算法采用六步换向算法,开环系统。

主控芯片选用STM32F103VCT6。

PWM输出引脚如下:

采用了高级定时器TIM1的完全重映射引脚。

PE9->UH   1        

PE10->UL  2N

PE11->VH  2

PE12->VL   3N

PE13->WH 3

PE14->WL  4

通道设置的有点问题,正确的较为方便的应该是UH1接CH1,UL1接CH1N(1通道的互补通道),后续利用飞线解决问题。(这里不处理也可以)

利用光耦将功率电与控制部分隔离开。光耦芯片使用6N137,注意:6N137是反逻辑的。即输入高电平经光耦后输出低电平。  

6N137的真值表:

隔离电路设计:

 

 驱动芯片选用IR2136,由于尚未实测IR2136是否能成功驱动MOSFET,暂不贴电路设计了。

无刷电机旋转时,需要导通一个上桥臂和一个下桥臂,如UH、WL导通,其他桥臂关断(UH指U相上桥臂,WL为W相下桥臂),此时需要PWM_UH与PWM_WL引脚输出PWM波,其他引脚为高电平输出(经光耦后反相为低电平)。

在这里贴出一个比较容易理解的方法:

需要说明的是:

需要达成的目的为CH1通道输出PWM波,CH1N通道输出高电平。(并不一定是这样的输出,只是通过修改CCR寄存器的值与比较值时,CH1与CH1N无法达到这样的目的,只能同时输出相同或互补的PWM波)。

这里达成目的的简单粗暴的方法为:首先所有通道正常输出PWM波,然后失能所有不需要输出PWM的引脚,通过配置GPIO,使这些不需要输出PWM的引脚输出高电平。

PWM输出相关配置:

PWM的占空比在主函数中配置。

//PE9(UH)、PE11(VH)、PE13(WH)、PE14(WL)、PE10(UL)、PE12(VL) PWM 输出
void TIM1_PWM_Init(u16 arr,u16 psc)
{  
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;	
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);  //使能GPIOE时钟时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //时钟使能
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);  //使能AFIO时钟
	GPIO_PinRemapConfig(GPIO_FullRemap_TIM1,ENABLE);//映射为TIMx
	
	//设置该引脚为复用输出功能,输出TIMx_CHx的PWM脉冲波形
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_11|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_10|GPIO_Pin_12; //TIMx_CHx
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOE, &GPIO_InitStructure);
 
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  不分频
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;//互补通道输出比较极性为低
	
	//根据TIM_OCInitStruct中指定的参数初始化外设TIMx
	TIM_OC1Init(TIM1, &TIM_OCInitStructure);  //PE9
	TIM_OC2Init(TIM1, &TIM_OCInitStructure);	//PE11
	TIM_OC3Init(TIM1, &TIM_OCInitStructure);  //PE13
	TIM_OC4Init(TIM1, &TIM_OCInitStructure);	//PE14
		
	TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);//使能或者失能 TIMx 在 CCR1 上的预装载寄存器
	TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
	TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);
	TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);
	
	TIM_CtrlPWMOutputs(TIM1,ENABLE);	//MOE 主输出使能	
	TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
	TIM_Cmd(TIM1, ENABLE);  //使能TIMx
}

GPIO配置:

void GPIOx_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); 	// 使能PE端口时钟
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11|GPIO_Pin_13|GPIO_Pin_10|GPIO_Pin_12;					
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;			// 推挽输出
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;			// IO口速度为50MHz
	GPIO_Init(GPIOE, &GPIO_InitStructure); 	   				// 根据设定参数初始化GPIOB.5
	//GPIO_SetBits(GPIOE, GPIO_Pin_9|GPIO_Pin_11|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_10|GPIO_Pin_12);	
}

以UH、WL输出PWM,其他引脚输出高电平为例:

void GPIOE_High(void)
{
	 GPIOx_Init();
 	 GPIO_SetBits(GPIOE,GPIO_Pin_11|GPIO_Pin_13|GPIO_Pin_12|GPIO_Pin_10);//引脚输出高电平	
}

利用宏定义:

#define     PWMUVW_Dis        TIM1->CCER &= ~(TIM_CCER_CC1E|TIM_CCER_CC2NE|TIM_CCER_CC2E|TIM_CCER_CC3NE|TIM_CCER_CC3E|TIM_CCER_CC4E);//取消使能UVW所有的输出,所有管子均关闭
#define     UH_ON             TIM1->CCER |= TIM_CCER_CC1E;
#define     UL_ON             TIM1->CCER |= TIM_CCER_CC2NE;
#define     VH_ON             TIM1->CCER |= TIM_CCER_CC2E;
#define     VL_ON             TIM1->CCER |= TIM_CCER_CC3NE;
#define     WH_ON             TIM1->CCER |= TIM_CCER_CC3E;
#define     WL_ON             TIM1->CCER |= TIM_CCER_CC4E;
                                
#define     PWMUH_ON_WL_ON	  PWMUVW_Dis; UH_ON; WL_ON;  GPIOx_Init(); GPIO_SetBits(GPIOE,GPIO_Pin_11|GPIO_Pin_13|GPIO_Pin_12|GPIO_Pin_10);

最后进行主函数的编写:

int main(void)
 {    
	 //delay_init();	  
	 //PWM输出测试
  
	 TIM1_PWM_Init(1799,1);//不分频。PWM频率=72000/(1799+1)=40 KH
	 TIM_SetCompare1(TIM1,300);	//PE9,通过修改300这个数字来修改占空比
	 TIM_SetCompare2(TIM1,300);	//PE11、PE10
	 TIM_SetCompare3(TIM1,300);  //PE13
	 TIM_SetCompare4(TIM1,300); //PE14	
   	 PWMUH_ON_WL_ON;
}

利用KEIL自带的虚拟示波器验证结果:

发现,只有PE9与PE14输出PWM, 其他引脚输出高电平,达成目的。

  • 3
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
STM32是一款功能强大的微控制器,广泛应用于各种嵌入式系统中,包括无刷直流电机控制无刷直流电机是一种常见的电动机类型,具有高效率、低噪音和长寿命的优点。为了控制无刷直流电机,我们需要使用适当的程序来实现。 首先,我们需要了解无刷直流电机的工作原理。无刷直流电机由一组永磁轴上的多个电磁线圈组成,这些线圈通过电子换向器逐个进行驱动。电子换向器的工作是根据电机转子的位置,切换相应的线圈,以保持电机转子的旋转。 在STM32控制程序中,我们需要编写相应的代码来读取电机旋转位置,并实时调整电子换向器的状态来控制电机转子的旋转。我们可以使用STM32的定时器和外部中断功能来实现这一点。 首先,我们需要使用定时器来测量电机转子的位置。通过读取定时器的计数值,我们可以确定电机转子的位置。然后,我们可以使用外部中断功能来检测电机转子位置变化的事件。当检测到位置变化时,我们可以更新电子换向器的状态,以控制电机转子的旋转方向和速度。 在编写控制程序时,我们需要考虑到电机性能和特性的差异。例如,电机的最大速度、最大扭矩和最小起动电压等参数需要根据具体电机的规格进行调整。此外,还需要注意电机控制环路的稳定性和响应速度。 总而言之,STM32无刷直流电机控制程序需要根据具体电机和应用需求编写。通过合理利用STM32的定时器和外部中断功能,我们可以实现精确、高效的无刷直流电机控制,为各种嵌入式应用提供动力驱动

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北辰辰辰辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值