单片机 :STM32F407
开发板:DMF407电机开发板
平台:keil V5.31
HSE 为8MHZ
HSI为16MHZ
ADC初始化:
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*/
watchtempvars1=TSK_HighFrequencyTask();//watchtempvars1=0
UI_DACUpdate(watchtempvars1);//用不到
int watchtempvars1=0;
int watchtempvars2=0;
__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] );
}
不返回IDLE,不能启动。
这是因为主板上电后,滴答时钟工作
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( &STMM1 );为IDLE,然后变为Fault_NOW
__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 );
}