本帖对Systick中断和ADC中断中的三个任务进行简单介绍。在上贴(【基于NUCLEO-F746ZG电机开发应用】7.程序框架-两个重要中断)中介绍了Systick中断执行安全任务和中频任务,ADC中断主要执行高频任务。下面对任务的流程进行介绍,对各任务内的函数具体是如何进行采集和计算的,后续我们单独进行分析:
1.安全任务
安全任务对于过温,过流,欠压,过压保护进行判断, 如果触发了上述保护,则会关闭PWM输出。本任务中对温度ADC采样,母线电压采样,采样完成后进行判断,与设置的上限和下限进行比较,如果超过了设置的阈值,则返回故障码。
安全任务流程图如下:
安全任务的代码:其中对代码进行了注释和分析。
__weak void TSK_SafetyTask_PWMOFF(uint8_t bMotor)
{
/* USER CODE BEGIN TSK_SafetyTask_PWMOFF 0 */
/* USER CODE END TSK_SafetyTask_PWMOFF 0 */
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)//电机1
{
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]);//关闭PWM输出
FOC_Clear(bMotor); //它重新初始化电流和电压变量。
//此外,它清除 qd 电流 PI 控制器、电压传感器和SpeednTorquecontroller
MPM_Clear((MotorPowMeas_Handle_t*)pMPM[bMotor]);//清除测量缓冲区并初始化索引
/* USER CODE BEGIN TSK_SafetyTask_PWMOFF 1 */
/* USER CODE END TSK_SafetyTask_PWMOFF 1 */
break;
case FAULT_OVER://当故障条件消失时,应用程序打算保持的持久状态。
//后续状态通常是 STOP_IDLE,一旦用户确认故障条件,状态机就会移动。
PWMC_SwitchOffPWM(pwmcHandle[bMotor]);//关闭PWM输出
/* USER CODE BEGIN TSK_SafetyTask_PWMOFF 2 */
/* USER CODE END TSK_SafetyTask_PWMOFF 2 */
break;
default:
break;
}
/* USER CODE BEGIN TSK_SafetyTask_PWMOFF 3 */
/* USER CODE END TSK_SafetyTask_PWMOFF 3 */
}
2.中频任务
中频任务执行于systick中断中 ,实际为速度环以及状态机执行地方。中频任务的流程图如下:
中频任务的代码如下:其中对代码进行了注释和分析。
/**
* [url=home.php?mod=space&uid=159083]@brief[/url] 为每个驱动器实例执行中频任务功能。
*
* 以 Systick 频率计时。
*/
__weak void MC_Scheduler(void)
{
/* USER CODE BEGIN MC_Scheduler 0 */
/* USER CODE END MC_Scheduler 0 */
if (bMCBootCompleted == 1)//初始化完成
{
if(hMFTaskCounterM1 > 0u)//任务计数大于0
{
hMFTaskCounterM1--;//递减
}
else
{
TSK_MediumFrequencyTaskM1();//执行中频任务
//速度环以及状态机执行
/* USER CODE BEGIN MC_Scheduler 1 */
/* USER CODE END MC_Scheduler 1 */
hMFTaskCounterM1 = MF_TASK_OCCURENCE_TICKS;//任务计数,
//MF_TASK_OCCURENCE_TICKS=(SYS_TICK_FREQUENCY/SPEED_LOOP_FREQUENCY_HZ)-1u
//SYS_TICK_FREQUENCY=2000,SPEED_LOOP_FREQUENCY_HZ = 1000
}
if(hBootCapDelayCounterM1 > 0u) //驱动器启动电容器对电机 1 充电所需的延迟计数
{
hBootCapDelayCounterM1--;
}
if(hStopPermanencyCounterM1 > 0u)//电机 1 在 STOP 状态下的持续时间
{
hStopPermanencyCounterM1--;
}
}
else
{
}
/* USER CODE BEGIN MC_Scheduler 2 */
/* USER CODE END MC_Scheduler 2 */
}
3.高频任务
高频任务函数位于mc_task.c的TSK_HighFrequencyTask()函数,执行的是核心FOC算法。高频任务的流程图如下:
高频任务的代码如下:
__weak uint8_t TSK_HighFrequencyTask(void)
{
/* USER CODE BEGIN HighFrequencyTask 0 */
/* USER CODE END HighFrequencyTask 0 */
uint8_t bMotorNbr = 0;
uint16_t hFOCreturn;
uint16_t hState; /* only if sensorless main*/
Observer_Inputs_t STO_Inputs; /* only if sensorless main*/
STO_Inputs.Valfa_beta = FOCVars[M1].Valphabeta; /* only if sensorless*/
if ( STM[M1].bState == SWITCH_OVER )
{
if (!REMNG_RampCompleted(pREMNG[M1]))
{
FOCVars[M1].Iqdref.q = REMNG_Calc(pREMNG[M1]);//执行斜坡计算并返回状态变量的当前值
}
}
/* USER CODE BEGIN HighFrequencyTask SINGLEDRIVE_1 */
/* USER CODE END HighFrequencyTask SINGLEDRIVE_1 */
hFOCreturn = FOC_CurrControllerM1();//执行FOC核心算法,并返回执行完成的状态
/* USER CODE BEGIN HighFrequencyTask SINGLEDRIVE_2 */
/* USER CODE END HighFrequencyTask SINGLEDRIVE_2 */
if(hFOCreturn == MC_FOC_DURATION)//FOC执行有错误
{
STM_FaultProcessing(&STM[M1], MC_FOC_DURATION, 0);//报错
}
else//没有错误
{
//检查对齐和第一加速阶段是否已完成
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);//复位参数
}
//获取电机状态
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);//更新转子电角度
}
/* USER CODE BEGIN HighFrequencyTask SINGLEDRIVE_3 */
/* USER CODE END HighFrequencyTask SINGLEDRIVE_3 */
}
/* USER CODE BEGIN HighFrequencyTask 1 */
/* USER CODE END HighFrequencyTask 1 */
return bMotorNbr;
}
三大核心任务是电机运行的基础,电机的运行以及各种状态和保护措施都在这三个任务中。后续对三个任务进行详细的分析。
不过我在学习的过程中发现,还是要把基本原理弄清楚,各种参数设置弄明白才能看的更清晰三大任务的计算是如何进行的。后续我们先了解一下基本的参数配置和数学模型。