基于STM32F103C8T6的同步电机驱动-PWM驱动代码以及SVPWM的实现
·
基于STM32F103C8T6的同步电机驱动-PWM驱动代码以及SVPWM的实现
本系列文章:
- 基于STM32F103C8T6的同步电机驱动-CubeMX配置与IQmath调用
- 基于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);
//串口信息打印
}
}
更多推荐
所有评论(0)