打印
[活动]

【APM32M3514电机通用评估板评测】+ 源码分析

[复制链接]
27|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
经过几天的测试和使用,APM32M3514点击通用评估板已经使用的比较熟练了;
该源码除了foc和观测器代码不开源,其它的均是开源,整个控制流程与外设的配置开源给玩电驱的同学们一些参考;
先从main函数开始

int main(void)
{
    GPIO_BSRET_T bit = Bit_RESET;
    __disable_irq();                           
    /*  config peripherals  */
    MC_SystemClockInit();
    /*  M0CP    */
    M0CP_Firmware_Init();
    RCM_EnableAHBPeriphReset(RCM_AHB_PERIPH_M0CP);
    RCM_DisableAHBPeriphReset(RCM_AHB_PERIPH_M0CP);
    RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_M0CP);
    M0CP_HardInit();
    *(volatile unsigned int*)(0x40024000+0x10) = 0;
    /*  TIMER1      */
    Drv_Pwm_Init(PWM_PERIOD,DEAD_TIME);
    PWM_CompareConfig(PWM_PERIOD, PWM_PERIOD, PWM_PERIOD);
    /*  ADC      */
    Drv_Adc_Init();
    /*  OPA      */
    OPA_Init();
    /*  COMP      */
    COMP_Init();
    /*  GPIO      */
    IO_Init();
        Pilot_uart_init();
    /*  SYSTICK      */
    Systick_Init(SystemCoreClock / 1000);
    /* Initialize  motor control parameters */
    Init_Parameter(&Motor_type);
    /* Initialize interrupts */
    Interrupt_Init();
       /* Wait until ADC is ready */
    while (!ADC_ReadStatusFlag(ADC_FLAG_ADRDY));
    ADC_StartConversion();
    WWDTInit();
    __enable_irq();                             //Enable all interrupts
    TMR_EnablePWMOutputs(TMR1);
    while (1)
    {
        //Reads key from demoboard.
        NewDIRKey = GPIO_ReadInputBit(GPIOC,GPIO_PIN_13); //PC13 Direction方向按键
        if(NewDIRKey == BIT_RESET)
        {
            /*设定新方向为反转CCW*/
            Motor_type.User.s8NewDir = -1;
        }
        else{
            /*设定新方向为正转CW*/
            Motor_type.User.s8NewDir = 1;
        }
        if(Motor_type.User.s8NewDir != Motor_type.User.s8Direction)
        {
            /*启动转向切换功能*/
            Motor_type.User.bDirSwitchEnable = true;
        }
        
        if(Motor_type.User.bSlowLoopFlag)
        {
            WWDTFeedDog();
            /* Slow Loop Statemachine */
            s_STATE_SLOW[eM1_MainState]();
            Motor_type.User.bSlowLoopFlag =  0;
        }
                if( Get_Systick_Cnt() % 300 == 0)
                {
                        GPIO_WriteBitValue(GPIO_LedErr,GPIO_Pin_LedErr,bit);
                        bit = !bit;
                }
                if( Get_Systick_Cnt() % 100 == 0)
                {
                        //speed_rate = 20;
                        speed_rpm = hall_cnt*20;
                        hall_cnt = 0;
                        printf("<plots,%d,%d,%d,%d>\r\n",\
                                Motor_type.Foc.s16SpdFilt,\
                                Motor_type.stc_SmoPara.s16q15_Ealpha,\
                                speed_rpm,\
                                Motor_type.Foc.stc_Idq.s16q15_Q\
                        );
//                        Motor_type.Foc.stc_Idq.s16q15_D,\
//                        Motor_type.Foc.stc_Idq.s16q15_Q,\
//                        Motor_type.Foc.stc_IdqCmd.s16q15_D,\
//                        Motor_type.Foc.stc_IdqCmd.s16q15_Q);
                }
    }
}
main函数主要是对外设的配置初始化;
主循环是简单的按键识别反向选择、喂狗等;
主要需要看的是PWM和adc的初始化
先看pwm
void  Drv_Pwm_Init(uint16_t u16_Period,uint16_t u16_DeadTime)
{
    TMR_TimeBase_T    TIM_TimeBaseInitStructure;
    TMR_OCConfig_T    TIM_OCInitStructure;
    TMR_BDTInit_T     TIM_BDTRInitStructure;
  
    RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG  | RCM_APB2_PERIPH_TMR1 );
   
    /* Time Base configuration ,init time1 freq*/
    TIM_TimeBaseInitStructure.period            = u16_Period;  //(SYSTEM_FREQUENCY/2/8000) - 1;
    TIM_TimeBaseInitStructure.div               = 0;
    TIM_TimeBaseInitStructure.counterMode       = TMR_COUNTER_MODE_CENTERALIGNED2;
    TIM_TimeBaseInitStructure.clockDivision     = TMR_CKD_DIV1;
    TIM_TimeBaseInitStructure.repetitionCounter = 1;
    TMR_ConfigTimeBase(TMR1, &TIM_TimeBaseInitStructure);

    /* Automatic Output enable, Break, dead time and lock configuration*/
    TIM_BDTRInitStructure.RMOS_State       = TMR_RMOS_STATE_ENABLE;//--------
    TIM_BDTRInitStructure.IMOS_State       = TMR_IMOS_STATE_ENABLE;//--------
    TIM_BDTRInitStructure.lockLevel        = TMR_LOCK_LEVEL_OFF;//00:锁定关闭,寄存器无写保护;01:锁定级别1,不能写入TIMx_BDTR寄存器的DTG、BKE、BKP、AOE位和TIMx_CR2寄存器的OISx/OISxN位;
    TIM_BDTRInitStructure.deadTime         = u16_DeadTime;//死区时间
    /**
     * Brake configuration: enable brake
     * Brake input polarity: active in low level   
     * Auto output enable configuration: Disable MOE bit hardware control
     */
    TIM_BDTRInitStructure.breakState       = TMR_BREAK_STATE_ENABLE;//TMR_BREAK_STATE_ENABLE TMR_BREAK_STATE_DISABLE;
    TIM_BDTRInitStructure.breakPolarity    = TMR_BREAK_POLARITY_HIGH;
    TIM_BDTRInitStructure.automaticOutput  = TMR_AUTOMATIC_OUTPUT_DISABLE;
    TMR_ConfigBDT(TMR1, &TIM_BDTRInitStructure);

    /*pwm driver set,channel 1,2,3,4set pwm mode*/
    TIM_OCInitStructure.OC_Mode         = TMR_OC_MODE_PWM2;
    TIM_OCInitStructure.OC_OutputState  = TMR_OUTPUT_STATE_ENABLE;  //TMR_OUTPUT_STATE_DISABLE;
    TIM_OCInitStructure.OC_OutputNState = TMR_OUTPUT_NSTATE_ENABLE; //TMR_OUTPUT_NSTATE_DISABLE;//------------
    TIM_OCInitStructure.Pulse           = u16_Period;
    TIM_OCInitStructure.OC_Polarity     = TMR_OC_POLARITY_HIGH;
    TIM_OCInitStructure.OC_NPolarity    = TMR_OC_NPOLARITY_HIGH; //互补输出极性-------
    TIM_OCInitStructure.OC_Idlestate    = TMR_OCIDLESTATE_RESET;  // TMR_OCIDLESTATE_SET; //
    TIM_OCInitStructure.OC_NIdlestate   = TMR_OCNIDLESTATE_RESET; // TMR_OCNIDLESTATE_SET;//
    //set OC1/OC1N
    TMR_OC1Config(TMR1, &TIM_OCInitStructure);
    //set oc2/oc2N
    TIM_OCInitStructure.Pulse = u16_Period;
    TMR_OC2Config(TMR1, &TIM_OCInitStructure);
    //set OC3/OC3N
    TIM_OCInitStructure.Pulse = u16_Period;
    TMR_OC3Config(TMR1, &TIM_OCInitStructure);
   
    TIM_OCInitStructure.OC_Mode         = TMR_OC_MODE_PWM2;              //选择定时器模式:TIM脉冲宽度调制模式2
    TIM_OCInitStructure.OC_OutputState  = TMR_OUTPUT_STATE_ENABLE;       //CH1比较输出使能               
    TIM_OCInitStructure.OC_OutputNState = TMR_OUTPUT_NSTATE_ENABLE;      //CH1N比较输出使能       
    TIM_OCInitStructure.OC_Polarity     = TMR_OC_POLARITY_HIGH;           //CH1输出极性:TIM输出比较极性高       
    TIM_OCInitStructure.OC_NPolarity    = TMR_OC_NPOLARITY_HIGH;          //CH1N输出极性:TIM输出比较极性高       
    TIM_OCInitStructure.OC_Idlestate    = TMR_OCIDLESTATE_RESET;         //CH1输出空闲状态:0       
    TIM_OCInitStructure.OC_NIdlestate   = TMR_OCNIDLESTATE_SET;          //CH1N输出空闲状态:0       
     //set OC4
    TIM_OCInitStructure.Pulse = 10;
    TMR_OC4Config(TMR1, &TIM_OCInitStructure);//OC4
    //enable interrupt
    TMR_EnableInterrupt(TMR1, TMR_INT_BRK);

    TMR_EnableAUTOReload(TMR1);//TIMx_ARR寄存器被装入缓冲器
    TMR_OC1PreloadConfig(TMR1,TMR_OC_PRELOAD_ENABLE);
    TMR_OC2PreloadConfig(TMR1,TMR_OC_PRELOAD_ENABLE);//比较值预装载使能
    TMR_OC3PreloadConfig(TMR1,TMR_OC_PRELOAD_ENABLE);
    TMR_OC4PreloadConfig(TMR1,TMR_OC_PRELOAD_ENABLE);
   
    TMR_EnableAUTOReload(TMR1);
   
    TMR_Enable(TMR1);
    TMR1->REPCNT = 1;
    /* Main Output Enable */
    TMR_EnablePWMOutputs(TMR1);
   
    /*  GPIO config     */
    GPIO_Config_T   GPIO_InitStructure;

    GPIO_InitStructure.pin      =   GPIO_PIN_PWM_UH_Mobile;
    GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
    GPIO_InitStructure.mode     =   GPIO_MODE_AF;
    GPIO_InitStructure.pupd     =   GPIO_PUPD_PD;
    GPIO_Config(GPIO_PWM_UH_Mobile, &GPIO_InitStructure);

    GPIO_InitStructure.pin      =   GPIO_PIN_PWM_VH_Mobile;
    GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
    GPIO_InitStructure.mode     =   GPIO_MODE_AF;
    GPIO_InitStructure.pupd     =   GPIO_PUPD_PD;
    GPIO_Config(GPIO_PWM_VH_Mobile, &GPIO_InitStructure);

    GPIO_InitStructure.pin      =   GPIO_PIN_PWM_WH_Mobile;
    GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
    GPIO_InitStructure.mode     =   GPIO_MODE_AF;
    GPIO_InitStructure.pupd     =   GPIO_PUPD_PD;
    GPIO_Config(GPIO_PWM_WH_Mobile, &GPIO_InitStructure);

    GPIO_InitStructure.pin      =   GPIO_PIN_PWM_UL_Mobile;
    GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
    GPIO_InitStructure.mode     =   GPIO_MODE_AF;
    GPIO_InitStructure.pupd     =   GPIO_PUPD_PD;
    GPIO_Config(GPIO_PWM_UL_Mobile, &GPIO_InitStructure);

    GPIO_InitStructure.pin      =   GPIO_PIN_PWM_VL_Mobile;
    GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
    GPIO_InitStructure.mode     =   GPIO_MODE_AF;
    GPIO_InitStructure.pupd     =   GPIO_PUPD_PD;
    GPIO_Config(GPIO_PWM_VL_Mobile, &GPIO_InitStructure);

    GPIO_InitStructure.pin      =   GPIO_PIN_PWM_WL_Mobile;
    GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
    GPIO_InitStructure.mode     =   GPIO_MODE_AF;
    GPIO_InitStructure.pupd     =   GPIO_PUPD_PD;
    GPIO_Config(GPIO_PWM_WL_Mobile, &GPIO_InitStructure);

    GPIO_InitStructure.pin      =   GPIO_PIN_PWM_Break_Mobile;
    GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
    GPIO_InitStructure.mode     =   GPIO_MODE_AF;
    GPIO_InitStructure.pupd     =   GPIO_PUPD_PD;
    GPIO_Config(GPIO_PWM_Break_Mobile, &GPIO_InitStructure);
    //复用映射,需参考文档
    GPIO_ConfigPinAF(GPIO_PWM_UH_Mobile,GPIO_PIN_SOURCE_PWM_UH_Mobile,GPIO_AF_PIN2);
    GPIO_ConfigPinAF(GPIO_PWM_VH_Mobile,GPIO_PIN_SOURCE_PWM_VH_Mobile,GPIO_AF_PIN2);
    GPIO_ConfigPinAF(GPIO_PWM_WH_Mobile,GPIO_PIN_SOURCE_PWM_WH_Mobile,GPIO_AF_PIN2);
    GPIO_ConfigPinAF(GPIO_PWM_UL_Mobile,GPIO_PIN_SOURCE_PWM_UL_Mobile,GPIO_AF_PIN2);
    GPIO_ConfigPinAF(GPIO_PWM_VL_Mobile,GPIO_PIN_SOURCE_PWM_VL_Mobile,GPIO_AF_PIN2);
    GPIO_ConfigPinAF(GPIO_PWM_WL_Mobile,GPIO_PIN_SOURCE_PWM_WL_Mobile,GPIO_AF_PIN2);
    GPIO_ConfigPinAF(GPIO_PWM_Break_Mobile,GPIO_PIN_SOURCE_PWM_Break_Mobile,GPIO_AF_PIN3);
}
pwm使用的是timr1,频率为16K,死区时间为1us。
使用高级定时器,产生互补pwm。
其次是ADC的配置:
void Drv_Adc_Init(void)
{
    ADC_Config_T   ADC_InitStructure;
    DMA_Config_T   DMA_InitStructure;
    DMA_InitStructure.peripheralAddress  = (uint32_t)&(ADC->DATA);//ADC地址
    DMA_InitStructure.memoryAddress      = (uint32_t)&ADC_ConvertedValue[0]; //内存地址
    DMA_InitStructure.direction          = DMA_DIR_PERIPHERAL; //方向(从外设到内存)
    DMA_InitStructure.bufferSize         = TOTAL_CHANNEL;//TOTAL_CHANNEL; //传输内容的大小---传输次数
    DMA_InitStructure.peripheralInc      = DMA_PERIPHERAL_INC_DISABLE; //外设地址固定
    DMA_InitStructure.memoryInc          = DMA_MEMORY_INC_ENABLE;//DMA_MEMORY_INC_ENABLE; //内存地址固定  
    DMA_InitStructure.peripheralDataSize = DMA_PERIPHERAL_DATASIZE_HALFWORD ; //外设数据单位
    DMA_InitStructure.memoryDataSize     = DMA_MEMORY_DATASIZE_HALFWORD ;    //内存数据单位
    DMA_InitStructure.circular           = DMA_CIRCULAR_ENABLE  ; //DMA模式:循环传输
    DMA_InitStructure.priority           = DMA_PRIORITY_LEVEL_VERYHIGH ; //优先级:高
    DMA_InitStructure.memoryTomemory     = DMA_M2M_DISABLE;   //禁止内存到内存的传输
    ADC_Reset();
    DMA_Config(DMA_CHANNEL_1, &DMA_InitStructure);  //配置DMA的1通道
    DMA_Enable(DMA_CHANNEL_1);
    ADC_ClockMode(ADC_CLOCK_MODE_ASYNCLK);//48M/4=12mADC_CLOCK_MODE_SYNCLKDIV4   
    ADC_ConfigStructInit(&ADC_InitStructure);
    ADC_InitStructure.convMode    = ADC_CONVERSION_SINGLE;
    ADC_InitStructure.scanDir     = ADC_SCAN_DIR_UPWARD;
    ADC_InitStructure.extTrigConv1 = ADC_EXT_TRIG_CONV_TRG1;  //  timer1 CC4
    ADC_InitStructure.extTrigEdge1 = ADC_EXT_TRIG_EDGE_RISING;
    ADC_InitStructure.dataAlign   = ADC_DATA_ALIGN_RIGHT;
    ADC_InitStructure.resolution  = ADC_RESOLUTION_12B;   
    ADC_Config(&ADC_InitStructure);
    /*ADC_CHANNEL_2 :PA4 IV;ADC_CHANNEL_8:PB0 IU;ADC_CHANNEL_6:PA6 Vbus;ADC_CHANNEL_7:PA7 Handle;ADC_CHANNEL_12:PB10 Ibus*/
    ADC_ConfigChannel(ADC_CHANNEL_2 | ADC_CHANNEL_8 | ADC_CHANNEL_6 | ADC_CHANNEL_7| ADC_CHANNEL_12 ,ADC_SAMPLE_TIME_1_5);
    ADC->CFG1_B.OVRMAG = 1;   
    ADC_EnableInterrupt(ADC_INT_CS);
//=========================ADC中断使用=================================================
    NVIC_EnableIRQ(ADC_COMP_IRQn);
    NVIC_SetPriority(ADC_COMP_IRQn,0);  
    ADC_DMARequestMode(ADC_DMA_MODE_CIRCULAR);
    ADC_EnableDMA();
    ADC_Enable();  
    ADC_StartConversion();//必需要启动一下
   
    /*  Config IO   */
    GPIO_Config_T   GPIO_InitStructure;

    GPIO_InitStructure.pin      =   GPIO_Pin_ADC_VDC;
    GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
    GPIO_InitStructure.mode     =   GPIO_MODE_AN;
    GPIO_InitStructure.pupd     =   GPIO_PUPD_NO;
    GPIO_Config(GPIO_ADC_VDC, &GPIO_InitStructure);
   
    GPIO_InitStructure.pin      =   GPIO_Pin_ADC_Handle;
    GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
    GPIO_InitStructure.mode     =   GPIO_MODE_AN;
    GPIO_InitStructure.pupd     =   GPIO_PUPD_NO;
    GPIO_Config(GPIO_ADC_Handle, &GPIO_InitStructure);
   
    GPIO_InitStructure.pin      =   GPIO_Pin_ADC_IU;
    GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
    GPIO_InitStructure.mode     =   GPIO_MODE_AN;
    GPIO_InitStructure.pupd     =   GPIO_PUPD_NO;
    GPIO_Config(GPIO_ADC_IU, &GPIO_InitStructure);
   
    GPIO_InitStructure.pin      =   GPIO_Pin_ADC_IV;
    GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
    GPIO_InitStructure.mode     =   GPIO_MODE_AN;
    GPIO_InitStructure.pupd     =   GPIO_PUPD_NO;
    GPIO_Config(GPIO_ADC_IV, &GPIO_InitStructure);
   
    GPIO_InitStructure.pin      =   GPIO_Pin_ADC_IBUS;
    GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
    GPIO_InitStructure.mode     =   GPIO_MODE_AN;
    GPIO_InitStructure.pupd     =   GPIO_PUPD_NO;
    GPIO_Config(GPIO_ADC_IBUS, &GPIO_InitStructure);
//    GPIO_InitStructure.pin      =   GPIO_Pin_ADC_VOT;
//    GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
//    GPIO_InitStructure.mode     =   GPIO_MODE_AN;
//    GPIO_InitStructure.pupd     =   GPIO_PUPD_NO;
//    GPIO_Config(GPIO_ADC_VOT, &GPIO_InitStructure);
}
ADC配置为DMA模式,使用TIMER1的CC4的上升沿进行触发,也就是说,TIMER1的通道4,每产生一个PWM的上升沿,就会检测一次ADC的数据;
为什么使用通道4?
因为TIMER1的通道1~3要控制三相桥,通道4空余的作为一个触发源,并不会真正的产生一个PWM信号;
会在ADC的中断内进行数据的读取;

void ADC_COMP_IRQHandler(void)
{   
    ADC->STS =  ADC->STS;//Clear interrupt flag bit
    static uint8_t u8ADCTimeCnt = 0;
    static uint32_t u32IaSum = 0;
    static uint32_t u32IbSum = 0;
    static uint16_t u16Cnt = 0;
   
    if(u16Cnt <= 127)
    {
        u16Cnt++;
        u32IbSum += (int16_t)ADC_GetValue(CURR_CHANNEL_V);
        u32IaSum += (int16_t)ADC_GetValue(CURR_CHANNEL_U);
    }
    else if(u16Cnt == 128)
    {
        u16Cnt++;
        u32IbSum = u32IbSum>>7;
        u32IaSum = u32IaSum>>7;
        Motor_type.Foc.stc_IuvwOffset.s16q15_V = u32IbSum << 3;
        Motor_type.Foc.stc_IuvwOffset.s16q15_U = u32IaSum << 3;
        u32IbSum = 0;
        u32IaSum = 0;
        Motor_type.Foc.s16q15IbusOffset = (int16_t)ADC_GetValue(IBUS_CHANNEL) << 3;
    }
    else
    {
        /*采样*/
        Get_ADC_Result(&Motor_type);
        /* Fast Loop Statemachine */
        s_STATE_FAST[eM1_MainState]();
        if(++u8ADCTimeCnt >= Motor_type.User.u16SlowLoopDiv)   //For slow loop state machine
        {
          u8ADCTimeCnt = 0;
          Motor_type.User.bSlowLoopFlag = 1;
        }
    }
}
在ADC的中断内进行foc算法的控制;
使用Get_ADC_Result(&Motor_type);先获取adc值;
通过s_STATE_FAST[eM1_MainState]();进行foc运算;

foc控制:
static void M1_RunSpinFast(void)
{
    Motor_type.Foc.s16CmdTheta += Motor_type.stc_SmoPara.s16q15SpdObs*Motor_type.Foc.s16SpdToTheta >> 15;
    Motor_type.Foc.stc_SinCos = sin_cos_cal(Motor_type.Foc.s16CmdTheta);
    /*Current loop*/
    current_ctrl(&Motor_type);
    Motor_type.Foc.u16q15Vdq_sqrt = isqrt32((uint32_t)(Motor_type.Foc.stc_Vdq.s16q15_D * Motor_type.Foc.stc_Vdq.s16q15_D + Motor_type.Foc.stc_Vdq.s16q15_Q * Motor_type.Foc.stc_Vdq.s16q15_Q));

    /*  observation     */
    Motor_type.stc_SmoPara.s16q15_Ialpha = Motor_type.Foc.stc_Iab.s16q15_A;
    Motor_type.stc_SmoPara.s16q15_Ibeta = Motor_type.Foc.stc_Iab.s16q15_B;
    Motor_type.stc_SmoPara.s16q15_Ualpha = Motor_type.Foc.stc_Vab.s16q15_A;
    Motor_type.stc_SmoPara.s16q15_Ubeta = Motor_type.Foc.stc_Vab.s16q15_B;
    smo_cal(&Motor_type.stc_SmoPara);
       
    /*  PLL     */
    Motor_type.stc_PiPll.s16_Error = ((-Motor_type.stc_SmoPara.s16q15_Ealpha*Motor_type.Foc.stc_SinCos.s16q15_Cos)
                        - (Motor_type.stc_SmoPara.s16q15_Ebeta*Motor_type.Foc.stc_SinCos.s16q15_Sin)) >> 15;
    anti_pi(&Motor_type.stc_PiPll);
    Motor_type.stc_SmoPara.s16q15SpdObs = Motor_type.stc_PiPll.s32_Out;
    /*  svpwm   */
    Motor_type.Foc.stc_SvpwmPara.s16q15_Vbus = Motor_type.Foc.s16Vbus;
    Motor_type.Foc.stc_SvpwmPara.s16q15_Valpha = Motor_type.Foc.stc_Vab.s16q15_A;
    Motor_type.Foc.stc_SvpwmPara.s16q15_Vbeta = Motor_type.Foc.stc_Vab.s16q15_B;
    svpwm7_cal(&Motor_type.Foc.stc_SvpwmPara);
    PWM_Update(&Motor_type);
}
先获取电角度,转换为正弦值,在current_ctrl函数进行clarke变化,再进行park变化,对d轴电流进行pi计算,再对q轴电流进行pi计算,计算除vq和vd值,进行反park变化;
void current_ctrl(Motor_TypeDef *Motor)
{
    clarke(&Motor->Foc.stc_Iuvw, &Motor->Foc.stc_Iab);
    park(&Motor->Foc.stc_Iab,&Motor->Foc.stc_SinCos, &Motor->Foc.stc_Idq);
    /*      PI for Id       */
    Motor->stc_IdPi.s16_Error = Motor->Foc.stc_IdqCmd.s16q15_D-Motor->Foc.stc_Idq.s16q15_D;
    anti_pi(&Motor->stc_IdPi);

    Motor->Foc.stc_Vdq.s16q15_D = Motor->stc_IdPi.s32_Out;
    /*      limit the Vq    */
    uint32_t u32_Temp;
    int16_t s16q15Vmax = Motor->Foc.s16Vbus * 18918 >> 15;     // Vamx=Vbus/sqrt(3)
    u32_Temp = s16q15Vmax*s16q15Vmax
               - Motor->Foc.stc_Vdq.s16q15_D*Motor->Foc.stc_Vdq.s16q15_D;
    Motor->stc_IqPi.s32_Umax = isqrt32(u32_Temp);
    Motor->stc_IqPi.s32_Umin = -Motor->stc_IqPi.s32_Umax;
    /*      PI for Iq       */
    Motor->stc_IqPi.s16_Error = Motor->Foc.stc_IdqCmd.s16q15_Q-Motor->Foc.stc_Idq.s16q15_Q;
    anti_pi(&Motor->stc_IqPi);
    Motor->Foc.stc_Vdq.s16q15_Q = Motor->stc_IqPi.s32_Out;
   
    /*  InvPark     */
    inv_park(&Motor->Foc.stc_Vdq, &Motor->Foc.stc_SinCos, &Motor->Foc.stc_Vab);
}
再将换算除的vd,vq,iq,id赋值到smo滑模观测器参数内进行电角度观测;
使用pi对pll进行整定,能换算出速度值;
最后使用svpwm7_cal(&Motor_type.Foc.stc_SvpwmPara);对不同的角度区域进行换算,得到SVPWM信号,使用PWM_Update(&Motor_type);更新PWM值进行输出;
void PWM_Update(Motor_TypeDef *Motor)
{
    if(Motor->User.s8Direction != -1)
    {
        Motor->PWMx.Timer->CC1 = (32768-Motor->Foc.stc_SvpwmPara.u16q15_DutyU)*PWM_PERIOD >> 15;
        Motor->PWMx.Timer->CC2 = (32768-Motor->Foc.stc_SvpwmPara.u16q15_DutyV)*PWM_PERIOD >> 15;
    }
    else
    {
        Motor->PWMx.Timer->CC1 = (32768-Motor->Foc.stc_SvpwmPara.u16q15_DutyV)*PWM_PERIOD >> 15;
        Motor->PWMx.Timer->CC2 = (32768-Motor->Foc.stc_SvpwmPara.u16q15_DutyU)*PWM_PERIOD >> 15;
    }
    Motor->PWMx.Timer->CC3 = (32768-Motor->Foc.stc_SvpwmPara.u16q15_DutyW)*PWM_PERIOD >> 15;
}



这个控制是运行快速旋转的控制方法,还有慢速旋转的控制方法,可自行了解学习;

以上是源码的控制流程

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

28

主题

132

帖子

3

粉丝