单片机无感FOC驱动之ADC

单片机无感FOC驱动之ADC 单片机 STM32F407开发板DMF407电机开发板平台keil V5.31HSE 为8MHZHSI为16MHZADC初始化static void MX_ADC1_Init(void) { ADC_InjectionConfTypeDef sConfigInjected {0}; ADC_ChannelConfTypeDef sConfig {0}; hadc1.Instance ADC1; hadc1.Init.ClockPrescaler ADC_CLOCK_SYNC_PCLK_DIV4; hadc1.Init.Resolution ADC_RESOLUTION_12B; hadc1.Init.ScanConvMode ENABLE; hadc1.Init.ContinuousConvMode DISABLE; hadc1.Init.DiscontinuousConvMode DISABLE; hadc1.Init.ExternalTrigConvEdge ADC_EXTERNALTRIGCONVEDGE_NONE; hadc1.Init.ExternalTrigConv ADC_SOFTWARE_START; hadc1.Init.DataAlign ADC_DATAALIGN_LEFT; hadc1.Init.NbrOfConversion 2; hadc1.Init.DMAContinuousRequests DISABLE; hadc1.Init.EOCSelection ADC_EOC_SINGLE_CONV; if (HAL_ADC_Init(hadc1) ! HAL_OK) { Error_Handler(); } sConfigInjected.InjectedChannel ADC_CHANNEL_8; sConfigInjected.InjectedRank 1; sConfigInjected.InjectedNbrOfConversion 3; sConfigInjected.InjectedSamplingTime ADC_SAMPLETIME_28CYCLES; sConfigInjected.ExternalTrigInjecConvEdge ADC_EXTERNALTRIGINJECCONVEDGE_RISING; sConfigInjected.ExternalTrigInjecConv ADC_EXTERNALTRIGINJECCONV_T1_CC4; sConfigInjected.AutoInjectedConv DISABLE; sConfigInjected.InjectedDiscontinuousConvMode ENABLE; sConfigInjected.InjectedOffset 0; if (HAL_ADCEx_InjectedConfigChannel(hadc1, sConfigInjected) ! HAL_OK) { Error_Handler(); } /** Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time */ sConfigInjected.InjectedChannel ADC_CHANNEL_6; sConfigInjected.InjectedRank 2; if (HAL_ADCEx_InjectedConfigChannel(hadc1, sConfigInjected) ! HAL_OK) { Error_Handler(); } /** Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time */ sConfigInjected.InjectedChannel ADC_CHANNEL_3; sConfigInjected.InjectedRank 3; if (HAL_ADCEx_InjectedConfigChannel(hadc1, sConfigInjected) ! HAL_OK) { Error_Handler(); } /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. */ sConfig.Channel ADC_CHANNEL_9; sConfig.Rank 1; sConfig.SamplingTime ADC_SAMPLETIME_28CYCLES; sConfig.Offset 0; if (HAL_ADC_ConfigChannel(hadc1, sConfig) ! HAL_OK) { Error_Handler(); } /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. */ sConfig.Channel ADC_CHANNEL_0; sConfig.Rank 2; sConfig.Offset 0; if (HAL_ADC_ConfigChannel(hadc1, sConfig) ! HAL_OK) { Error_Handler(); } }ADC中断void ADC_IRQHandler(void) { if(LL_ADC_IsActiveFlag_JEOS(ADC1)) { // Clear Flags ADC1-SR ~(uint32_t)(LL_ADC_FLAG_JEOS | LL_ADC_FLAG_JSTRT); UI_DACUpdate(TSK_HighFrequencyTask()); /*GUI, this section is present only if DAC is enabled*/ } } __STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_JEOS(ADC_TypeDef *ADCx) { /* Note: on this STM32 serie, there is no flag ADC group injected */ /* end of unitary conversion. */ /* Flag noted as JEOC is corresponding to flag JEOS */ /* in other STM32 families). */ return (READ_BIT(ADCx-SR, LL_ADC_FLAG_JEOS) (LL_ADC_FLAG_JEOS)); }改成这样// UI_DACUpdate(TSK_HighFrequencyTask()); /*GUI, this section is present only if DAC is enabled*/watchtempvars1TSK_HighFrequencyTask();watchtempvars1UI_DACUpdate(watchtempvars1);用不到int watchtempvars10; int watchtempvars20; __weak void UI_DACUpdate(uint8_t bMotorNbr) { watchtempvars1; if (UI_GetSelectedMC(pDAC-_Super) bMotorNbr) { UI_DACExec(pDAC-_Super); /* Exec DAC update */ watchtempvars2; } }__weak uint8_t TSK_HighFrequencyTask(void) { uint8_t bMotorNbr 0; uint16_t hFOCreturn; uint16_t hState; /* only if sensorless main*/ Observer_Inputs_t STO_Inputs; /* only if sensorless main*/ watchtempvars1; STO_Inputs.Valfa_beta FOCVars[M1].Valphabeta; /* only if sensorless*/ if ( STM[M1].bState SWITCH_OVER ) { watchtempvars2; if (!REMNG_RampCompleted(pREMNG[M1])) { FOCVars[M1].Iqdref.q REMNG_Calc(pREMNG[M1]); } } hFOCreturn FOC_CurrControllerM1(); if(hFOCreturn MC_FOC_DURATION) { STM_FaultProcessing(STM[M1], MC_FOC_DURATION, 0); } else { watchtempvars3; bool IsAccelerationStageReached RUC_FirstAccelerationStageReached(RevUpControlM1); STO_Inputs.Ialfa_beta FOCVars[M1].Ialphabeta; /* only if sensorless*/ STO_Inputs.Vbus VBS_GetAvBusVoltage_d((pBusSensorM1-_Super)); /* only for sensorless*/ STO_PLL_CalcElAngle (STO_PLL_M1, STO_Inputs); STO_PLL_CalcAvrgElSpeedDpp (STO_PLL_M1); /* Only in case of Sensor-less */ if (IsAccelerationStageReached false) { STO_ResetPLL(STO_PLL_M1); watchtempvars4; } hState STM_GetState(STM[M1]); if((hState START) || (hState SWITCH_OVER) || (hState START_RUN)) /* only for sensor-less*/ { int16_t hObsAngle SPD_GetElAngle(STO_PLL_M1._Super); VSS_CalcElAngle(VirtualSpeedSensorM1,hObsAngle); watchtempvars5; } } return bMotorNbr; }启动失败时电机启动按键触发启动void EXTI4_IRQHandler (void) { /* USER CODE BEGIN START_STOP_BTN */ if ( LL_EXTI_ReadFlag_0_31(LL_EXTI_LINE_4) ) { LL_EXTI_ClearFlag_0_31 (LL_EXTI_LINE_4); UI_HandleStartStopButton_cb (); } }__weak void UI_HandleStartStopButton_cb (void) { /* USER CODE BEGIN START_STOP_BTN */ if (MC_GetSTMStateMotor1() IDLE) { /* Ramp parameters should be tuned for the actual motor */ MC_StartMotor1(); } else { MC_StopMotor1(); } /* USER CODE END START_STOP_BTN */ }如果不给电机控制板提供电源__weak State_t MC_GetSTMStateMotor1(void) { return MCI_GetSTMState( pMCI[M1] ); }不返回不能启动。这是因为主板上电后滴答时钟工作void SysTick_Handler(void) { #ifdef MC_HAL_IS_USED static uint8_t SystickDividerCounter SYSTICK_DIVIDER; /* USER CODE BEGIN SysTick_IRQn 0 */ /* USER CODE END SysTick_IRQn 0 */ if (SystickDividerCounter SYSTICK_DIVIDER) { HAL_IncTick(); HAL_SYSTICK_IRQHandler(); SystickDividerCounter 0; } SystickDividerCounter ; #endif /* MC_HAL_IS_USED */ MC_RunMotorControlTasks(); }__weak void MC_RunMotorControlTasks(void) { if ( bMCBootCompleted ) { MC_Scheduler(); TSK_SafetyTask(); UI_Scheduler(); } }__weak void MC_Scheduler(void) { if (bMCBootCompleted 1) { if(hMFTaskCounterM1 0u) { hMFTaskCounterM1--; } else { TSK_MediumFrequencyTaskM1(); hMFTaskCounterM1 MF_TASK_OCCURENCE_TICKS; } if(hBootCapDelayCounterM1 0u) { hBootCapDelayCounterM1--; } if(hStopPermanencyCounterM1 0u) { hStopPermanencyCounterM1--; } } else { } }__weak void TSK_MediumFrequencyTaskM1(void) { State_t StateM1; int16_t wAux 0; (void) STO_PLL_CalcAvrgMecSpeedUnit( STO_PLL_M1, wAux ); PQD_CalcElMotorPower( pMPM[M1] ); StateM1 STM_GetState( STM[M1] ); switch ( StateM1 ) { case IDLE_START: RUC_Clear( RevUpControlM1, MCI_GetImposedMotorDirection( oMCInterface[M1] ) ); R3_2_TurnOnLowSides( pwmcHandle[M1] ); TSK_SetChargeBootCapDelayM1( CHARGE_BOOT_CAP_TICKS ); STM_NextState( STM[M1], CHARGE_BOOT_CAP ); break; case CHARGE_BOOT_CAP: if ( TSK_ChargeBootCapDelayHasElapsedM1() ) { PWMC_CurrentReadingCalibr( pwmcHandle[M1], CRC_START ); STM_NextState(STM[M1],OFFSET_CALIB); } break; case OFFSET_CALIB: if ( PWMC_CurrentReadingCalibr( pwmcHandle[M1], CRC_EXEC ) ) { STM_NextState( STM[M1], CLEAR ); } break; case CLEAR: /* In a sensorless configuration. Initiate the Revup procedure */ FOCVars[M1].bDriveInput EXTERNAL; STC_SetSpeedSensor( pSTC[M1], VirtualSpeedSensorM1._Super ); STO_PLL_Clear( STO_PLL_M1 ); if ( STM_NextState( STM[M1], START ) true ) { FOC_Clear( M1 ); R3_2_SwitchOnPWM( pwmcHandle[M1] ); } break; case START: { /* Mechanical speed as imposed by the Virtual Speed Sensor during the Rev Up phase. */ int16_t hForcedMecSpeedUnit; qd_t IqdRef; bool ObserverConverged false; /* Execute the Rev Up procedure */ if( ! RUC_Exec( RevUpControlM1 ) ) { /* The time allowed for the startup sequence has expired */ STM_FaultProcessing( STM[M1], MC_START_UP, 0 ); } else { /* Execute the torque open loop current start-up ramp: * Compute the Iq reference current as configured in the Rev Up sequence */ IqdRef.q STC_CalcTorqueReference( pSTC[M1] ); IqdRef.d FOCVars[M1].UserIdref; /* Iqd reference current used by the High Frequency Loop to generate the PWM output */ FOCVars[M1].Iqdref IqdRef; } (void) VSS_CalcAvrgMecSpeedUnit( VirtualSpeedSensorM1, hForcedMecSpeedUnit ); /* check that startup stage where the observer has to be used has been reached */ if (RUC_FirstAccelerationStageReached(RevUpControlM1) true) { ObserverConverged STO_PLL_IsObserverConverged( STO_PLL_M1,hForcedMecSpeedUnit ); (void) VSS_SetStartTransition( VirtualSpeedSensorM1, ObserverConverged ); } if ( ObserverConverged ) { qd_t StatorCurrent MCM_Park( FOCVars[M1].Ialphabeta, SPD_GetElAngle( STO_PLL_M1._Super ) ); /* Start switch over ramp. This ramp will transition from the revup to the closed loop FOC. */ REMNG_Init( pREMNG[M1] ); REMNG_ExecRamp( pREMNG[M1], FOCVars[M1].Iqdref.q, 0 ); REMNG_ExecRamp( pREMNG[M1], StatorCurrent.q, TRANSITION_DURATION ); STM_NextState( STM[M1], SWITCH_OVER ); } } break; case SWITCH_OVER: { bool LoopClosed; int16_t hForcedMecSpeedUnit; if( ! RUC_Exec( RevUpControlM1 ) ) { /* The time allowed for the startup sequence has expired */ STM_FaultProcessing( STM[M1], MC_START_UP, 0 ); } else { /* Compute the virtual speed and positions of the rotor. The function returns true if the virtual speed is in the reliability range */ LoopClosed VSS_CalcAvrgMecSpeedUnit(VirtualSpeedSensorM1,hForcedMecSpeedUnit); /* Check if the transition ramp has completed. */ LoopClosed | VSS_TransitionEnded( VirtualSpeedSensorM1 ); /* If any of the above conditions is true, the loop is considered closed. The state machine transitions to the START_RUN state. */ if ( LoopClosed true ) { #if ( PID_SPEED_INTEGRAL_INIT_DIV 0 ) PID_SetIntegralTerm( pPIDSpeed[M1], 0 ); #else PID_SetIntegralTerm( pPIDSpeed[M1], (int32_t) ( FOCVars[M1].Iqdref.q * PID_GetKIDivisor(pPIDSpeed[M1]) / PID_SPEED_INTEGRAL_INIT_DIV ) ); #endif STM_NextState( STM[M1], START_RUN ); } } } break; case START_RUN: /* only for sensor-less control */ STC_SetSpeedSensor(pSTC[M1], STO_PLL_M1._Super); /*Observer has converged*/ { FOC_InitAdditionalMethods(M1); FOC_CalcCurrRef( M1 ); STM_NextState( STM[M1], RUN ); } STC_ForceSpeedReferenceToCurrentSpeed( pSTC[M1] ); /* Init the reference speed to current speed */ MCI_ExecBufferedCommands( oMCInterface[M1] ); /* Exec the speed ramp after changing of the speed sensor */ break; case RUN: MCI_ExecBufferedCommands( oMCInterface[M1] ); FOC_CalcCurrRef( M1 ); break; case ANY_STOP: R3_2_SwitchOffPWM( pwmcHandle[M1] ); FOC_Clear( M1 ); MPM_Clear( (MotorPowMeas_Handle_t*) pMPM[M1] ); TSK_SetStopPermanencyTimeM1( STOPPERMANENCY_TICKS ); STM_NextState( STM[M1], STOP ); break; case STOP: if ( TSK_StopPermanencyTimeHasElapsedM1() ) { STM_NextState( STM[M1], STOP_IDLE ); } break; case STOP_IDLE: STC_SetSpeedSensor( pSTC[M1],VirtualSpeedSensorM1._Super ); /* sensor-less */ VSS_Clear( VirtualSpeedSensorM1 ); /* Reset measured speed in IDLE */ STM_NextState( STM[M1], IDLE ); break; default: break; } }执行中频任务前几次StateM1 STM_GetState( STM[M1] );为然后变为Fault__weak void TSK_SafetyTask(void) { if (bMCBootCompleted 1) { TSK_SafetyTask_PWMOFF(M1); /* User conversion execution */ RCM_ExecUserConv (); } }__weak void TSK_SafetyTask_PWMOFF(uint8_t bMotor) { uint16_t CodeReturn MC_NO_ERROR; uint16_t errMask[NBR_OF_MOTORS] {VBUS_TEMP_ERR_MASK}; CodeReturn | errMask[bMotor] NTC_CalcAvTemp(pTemperatureSensor[bMotor]); /* check for fault if FW protection is activated. It returns MC_OVER_TEMP or MC_NO_ERROR */ CodeReturn | PWMC_CheckOverCurrent(pwmcHandle[bMotor]); /* check for fault. It return MC_BREAK_IN or MC_NO_FAULTS (for STM32F30x can return MC_OVER_VOLT in case of HW Overvoltage) */ if(bMotor M1) { CodeReturn | errMask[bMotor] RVBS_CalcAvVbus(pBusSensorM1); } STM_FaultProcessing(STM[bMotor], CodeReturn, ~CodeReturn); /* Update the STM according error code */ switch (STM_GetState(STM[bMotor])) /* Acts on PWM outputs in case of faults */ { case FAULT_NOW: PWMC_SwitchOffPWM(pwmcHandle[bMotor]); FOC_Clear(bMotor); MPM_Clear((MotorPowMeas_Handle_t*)pMPM[bMotor]); break; case FAULT_OVER: PWMC_SwitchOffPWM(pwmcHandle[bMotor]); break; default: break; } }__weak State_t STM_FaultProcessing( STM_Handle_t * pHandle, uint16_t hSetErrors, uint16_t hResetErrors ) { State_t LocalState pHandle-bState; /* Set current errors */ pHandle-hFaultNow ( pHandle-hFaultNow | hSetErrors ) ( ~hResetErrors ); pHandle-hFaultOccurred | hSetErrors; if ( LocalState FAULT_NOW ) { if ( pHandle-hFaultNow MC_NO_FAULTS ) { pHandle-bState FAULT_OVER; LocalState FAULT_OVER; } } else { if ( pHandle-hFaultNow ! MC_NO_FAULTS ) { pHandle-bState FAULT_NOW; LocalState FAULT_NOW; } } return ( LocalState ); }