基于STM32F103C8T6的同步电机驱动-PWM驱动代码以及SVPWM的实现

本系列文章:

  1. 基于STM32F103C8T6的同步电机驱动-CubeMX配置与IQmath调用
  2. 基于STM32F103C8T6的同步电机驱动-PWM驱动代码以及SVPWM的实现

一、PWM驱动代码的编写

在系列文章的第一篇中已经对主定时器TIM1进行了PWM相关的配置,对从定时器TIM4进行了配置并开启了中断。电机驱动程序相关代码也将写在TIM4的中断里。

/****file:main.c*****/
//Include Header Files
#include "main.h"
#include "adc.h"
#include "can.h"
#include "i2c.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"
#include "IQmathlib.h"

//Global Variable
//PWM相关参数
uint16_t PWM1_PULSE=0;
uint16_t PWM2_PULSE=0;
uint16_t PWM3_PULSE=0;

/************向上为参数定义,向下为运行函数*******************************/
//main函数
int main(void)
{
  HAL_Init();
  SystemClock_Config();
  
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_CAN_Init();
  MX_I2C1_Init();
  MX_SPI1_Init();
  MX_TIM1_Init();
  MX_USART1_UART_Init();
  MX_I2C2_Init();
  MX_TIM4_Init();

  HAL_ADCEx_Calibration_Start(&hadc1);    //AD校准
  __HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_1, PWM1_PULSE); 
  __HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_2, PWM2_PULSE); 
  __HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_3, PWM3_PULSE); 
  __HAL_TIM_SET_AUTORELOAD(&htim4,2-1); //设置要输出的PWM脉冲数1000个  
  HAL_TIM_Base_Start_IT(&htim4);             //启动从定时器
  HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
  HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2);
  HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3); 
  HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_1);
  HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_2);
  HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_3);
  while (1)
  {

  }
}

//TIM4的中断回调函数
void  HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim == &htim4)
	{
		//中断进来先改变占空比,此时占空比为上一周期计算得到的值
		__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_1, PWM1_PULSE);
		__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_2, PWM2_PULSE);
		__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_3, PWM3_PULSE);		
		//在此后面加入电机驱动相关代码
		//电流电压ADC采样与计算
		//CLARK、PARK变换
		//编码器获取角度与速度
		//转速PI控制器
		//电流PI控制器
		//SVPWM
		//计算占空比值
		PWM1_PULSE = 400*_IQtoF(duty_ratio1);
		PWM2_PULSE = 400*_IQtoF(duty_ratio2);
		PWM3_PULSE = 400*_IQtoF(duty_ratio3);		
		//串口信息打印
	}

}

二、SVPWM的实现

已知SVPWM输入信号为两相静止坐标轴的电压值,即U_alpha、U_beta,输出为三路PWM占空比。

/****file:main.c*****/
//Global Variable
//PWM相关参数
uint16_t PWM1_PULSE=0;
uint16_t PWM2_PULSE=0;
uint16_t PWM3_PULSE=0;

//电压相关参数
_iq u_alpha ; _iq u_beta ; 	//两相静止坐标电压值

//SVPWM相关参数
int A;int B;int C;int N;
_iq U1 ; _iq U2 ; _iq U3 ; 
_iq T0;_iq T1;_iq T2;_iq T3;
_iq T4;_iq T5;_iq T6;_iq T7;
_iq duty_ratio1;_iq duty_ratio2;_iq duty_ratio3;


//TIM4的中断回调函数
void  HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim == &htim4)
	{
		//中断进来先改变占空比,此时占空比为上一周期计算得到的值
		__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_1, PWM1_PULSE);
		__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_2, PWM2_PULSE);
		__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_3, PWM3_PULSE);		
		//在此后面加入电机驱动相关代码
		//电流电压ADC采样与计算
		//CLARK、PARK变换
		//编码器获取角度与速度
		//转速PI控制器
		//电流PI控制器
		//SVPWM
		U1 = u_beta;
		U2 = _IQmpy( _IQ(sqrt3_2) , u_alpha ) - _IQmpy(_IQ(0.5) , u_beta);
		U3 = _IQmpy( _IQ(-sqrt3_2) , u_alpha ) - _IQmpy(_IQ(0.5) , u_beta);		
		if(U1>0){A=1;} else{A=0;}
		if(U2>0){B=1;} else{B=0;}
		if(U3>0){C=1;} else{C=0;}
		N=A+2*B+4*C;
		//对应扇区   //算T时不乘以Ts 算占空比时不除Ts,相互抵消 
		switch (N)
		{
		case 3://第一扇区 0-4-6-7-6-4-0
			T4 = _IQmpy( _IQ(K) ,U2  );
			T6 = _IQmpy( _IQ(K) ,U1  );
			T0 = _IQmpy( _IQ(0.5) , _IQ(1.0)-T4-T6 ); 
			T7 = T0;
			T1 = _IQ(0);T2 =_IQ(0);T3 =_IQ(0);T5 =_IQ(0);
			duty_ratio1 = T4 + T6 + T7;
			duty_ratio2 = T6 + T7;
			duty_ratio3 = T7;
			break;
		case 1://第二扇区 0-2-6-7-6-2-0
			T2 = _IQmpy( _IQ(-K) ,U2  );
			T6 = _IQmpy( _IQ(-K) ,U3  );
			T0 = _IQmpy( _IQ(0.5) , _IQ(1.0)-T2-T6 ); 
			T7 = T0;
			T1 = _IQ(0);T3 =_IQ(0);T4 =_IQ(0);T5 =_IQ(0);
			duty_ratio1 = T6 + T7;
			duty_ratio2 = T2 + T6 + T7;
			duty_ratio3 = T7;
			break;
		case 5://第三扇区 0-2-3-7-3-2-0
			T2 = _IQmpy( _IQ(K) ,U1  );
			T3 = _IQmpy( _IQ(K) ,U3  );
			T0 = _IQmpy( _IQ(0.5) , _IQ(1.0)-T2-T3 ); 
			T7 = T0;
			T1 = _IQ(0);T6 =_IQ(0);T4 =_IQ(0);T5 =_IQ(0);
			duty_ratio1 = T7;
			duty_ratio2 = T2 + T3 + T7;
			duty_ratio3 = T3 + T7;
			break;
		case 4://第四扇区 0-1-3-7-3-2-0
			T1 = _IQmpy( _IQ(-K) ,U1  );
			T3 = _IQmpy( _IQ(-K) ,U2  );
			T0 = _IQmpy( _IQ(0.5) , _IQ(1.0)-T1-T3 ); 
			T7 = T0;
			T2 = _IQ(0);T6 =_IQ(0);T4 =_IQ(0);T5 =_IQ(0);
			duty_ratio1 = T7;
			duty_ratio2 = T3 + T7;
			duty_ratio3 = T1 + T3 + T7;
			break;          
		case 6://第五扇区 0-1-5-7-5-1-0
			T1 = _IQmpy( _IQ(K) ,U3  );
			T5 = _IQmpy( _IQ(K) ,U2  );
			T0 = _IQmpy( _IQ(0.5) , _IQ(1.0)-T1-T5 ); 
			T7 = T0;
			T2 = _IQ(0);T6 =_IQ(0);T4 =_IQ(0);T3 =_IQ(0);
			duty_ratio1 = T5 + T7;
			duty_ratio2 = T7;
			duty_ratio3 = T1 + T5 + T7;
			break;          
		case 2://第六扇区 0-4-5-7-5-4-0
			T4 = _IQmpy( _IQ(-K) ,U3  );
			T5 = _IQmpy( _IQ(-K) ,U1  );
			T0 = _IQmpy( _IQ(0.5) , _IQ(1.0)-T4-T5 ); 
			T7 = T0;
			T2 = _IQ(0);T6 =_IQ(0);T1 =_IQ(0);T3 =_IQ(0);
			duty_ratio1 = T4 + T5 + T7;
			duty_ratio2 = T7;
			duty_ratio3 = T5 + T7;
			break;
			   
		default:
			break;
		}		
		//计算占空比值
		PWM1_PULSE = 400*_IQtoF(duty_ratio1);
		PWM2_PULSE = 400*_IQtoF(duty_ratio2);
		PWM3_PULSE = 400*_IQtoF(duty_ratio3);		
		//串口信息打印
	}

}
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐