📄 main.c
字号:
//! The angle of the motor drive will be updated, and new waveform values
//! computed and supplied to the PWM module.
//!
//! \note Since this interrupt is software triggered, there is no interrupt
//! source to clear in this handler.
//!
//! \return None.
//
//*****************************************************************************
void
MainWaveformTick(void)
{
unsigned long ulTemp, pulDutyCycles[3];
unsigned long ulHall;
//
// There is nothing to be done if the motor drive is not running.
//
if((g_ulState == STATE_STOPPED) || (g_ulState == STATE_PRECHARGE) ||
(g_ulState == STATE_BACK_PRECHARGE))
{
//
// Reduce the PWM period count based on the number of updates that
// would have occurred if the motor drive was running.
//
PWMReducePeriodCount((PWMGetPeriodCount() /
(g_sParameters.ucUpdateRate + 1)) *
(g_sParameters.ucUpdateRate + 1));
//
// Return without doing anything further.
//
return;
}
//
// Current Control Loop: When the target current is non-zero, and the
// motor current exceeds the target current value, the duty cycle will
// be reduced to limit the current to the target settings.
//
if((g_sParameters.sTargetCurrent != 0) &&
(g_sMotorCurrent > g_sParameters.sTargetCurrent))
{
static short sPreviousMotorCurrent = 0;
if(sPreviousMotorCurrent != g_sMotorCurrent)
{
//
// Save the motor current value.
//
sPreviousMotorCurrent = g_sMotorCurrent;
//
// Get the difference between the target and motor current.
//
ulTemp = (g_sMotorCurrent - g_sParameters.sTargetCurrent);
//
// Compute the percentage over, in 16.16 fixed point format.
//
ulTemp = ((ulTemp * 65536) / g_sParameters.sTargetCurrent);
//
// Compute the equivalent percentage of the current duty cycle.
//
ulTemp = ((ulTemp * g_ulDutyCycle) / 65536);
//
// Reduce the duty cycle.
//
g_ulDutyCycle = g_ulDutyCycle - ulTemp;
}
}
//
// Loop until the PWM period count is less than the update rate. The angle
// is updated based on the number of update periods that have passed, which
// may be more than one. After the angle is updated, the waveform
// moulations are computed. Since the period count may go above the update
// rate while computing the waveform modulation, this outer loop is
// required to ensure that the all update periods are accounted for before
// this routine returns.
//
while(PWMGetPeriodCount() > g_sParameters.ucUpdateRate)
{
//
// Get the number of updates that are pending. Normally, this will be
// one, but may be larger if the processor is heavily loaded.
//
ulTemp = PWMGetPeriodCount() / (g_sParameters.ucUpdateRate + 1);
//
// See if the motor drive direction is forward or backward.
//
if(g_ulState & STATE_FLAG_FORWARD)
{
//
// The motor drive direction is forward, so increment the motor
// drive angle by the angle delta.
//
g_ulAngle += (g_ulAngleDelta * (g_sParameters.ucUpdateRate + 1) *
ulTemp);
}
else
{
//
// The motor drive direction is backward, so decrement the motor
// drive angle by the angle delta.
//
g_ulAngle -= (g_ulAngleDelta * (g_sParameters.ucUpdateRate + 1) *
ulTemp);
}
//
// Reduce the PWM period count by the number of updates just performed.
//
PWMReducePeriodCount(ulTemp * (g_sParameters.ucUpdateRate + 1));
//
// Perform trapezoid modulation.
//
if(HWREGBITH(&(g_sParameters.usFlags), FLAG_DRIVE_BIT) ==
FLAG_DRIVE_TRAPEZOID)
{
//
// Set the duty cycle for each phase to the amplitude.
//
pulDutyCycles[0] = pulDutyCycles[1] = pulDutyCycles[2] =
g_ulDutyCycle;
//
// For sensored operation, check the sensor type.
//
if(HWREGBITH(&(g_sParameters.usFlags), FLAG_SENSOR_BIT) ==
FLAG_SENSOR_PRESENT)
{
//
// For digital/gpio hall sensor, set the previous and current
// values to the same, to skip the modulation code (it is
// run directly from the hall interrupt).
//
if(HWREGBITH(&(g_sParameters.usFlags), FLAG_SENSOR_TYPE_BIT) ==
FLAG_SENSOR_TYPE_GPIO)
{
ulHall = g_ulHallValue;
g_ulHallPrevious = ulHall;
}
//
// For linear hall sensor, use the linear hall value calculated
// in the ADC module.
//
else
{
ulHall = g_ulLinearHallValue;
}
}
//
// For Sensorless operation, check if the mode is startup or
// run mode.
//
else
{
//
// Use the startup sequence hall values for startup mode.
//
if(g_ulState & STATE_FLAG_STARTUP)
{
ulHall = g_ulStartupHallValue;
}
//
// Use the Back EMF hall values for run mode.
//
else
{
ulHall = g_ulBEMFHallValue;
}
}
//
// Run the trapezoid modulation based on the Hall sensor value.
//
if(ulHall != g_ulHallPrevious)
{
TrapModulate(ulHall);
g_ulHallPrevious = ulHall;
}
}
//
// Perform sine wave modulation.
//
else if(HWREGBITH(&(g_sParameters.usFlags), FLAG_DRIVE_BIT) ==
FLAG_DRIVE_SINE)
{
static const unsigned long ulHallToAngle[] =
{ 0, 270, 30, 330, 150, 210, 90, 0 };
//
// Check for change in Hall State.
//
if((g_ulHallPrevious != g_ulHallValue) &&
((g_ulSineTarget != g_ulSpeed) || (g_ulHallValue == 5)))
{
g_ulAngle = ulHallToAngle[g_ulHallValue];
if((g_ulState & STATE_FLAG_FORWARD) == STATE_FLAG_BACKWARD)
{
g_ulAngle += 60;
g_ulAngle %= 360;
}
g_ulAngle = (((g_ulAngle << 16) / 360) << 16);
}
g_ulHallPrevious = g_ulHallValue;
//
// Run the sine modulation code.
//
SineModulate(g_ulAngle, g_ulDutyCycle, pulDutyCycles);
//
// If running in reverse, the duty cycles must be inverted
//
if((g_ulState & STATE_FLAG_FORWARD) == STATE_FLAG_BACKWARD)
{
pulDutyCycles[0] = 65536 - pulDutyCycles[0];
pulDutyCycles[1] = 65536 - pulDutyCycles[1];
pulDutyCycles[2] = 65536 - pulDutyCycles[2];
}
}
//
// For now, there are no other modulations enabled, so ensure that
// the Duty Cycle is set to minimal.
//
else
{
pulDutyCycles[0] = pulDutyCycles[1] = pulDutyCycles[2] = 0;
}
//
// Set the new duty cycle.
//
//g_ulDebugInfo = (g_ulDutyCycle * 100) / 65536;
PWMSetDutyCycle(pulDutyCycles[0], pulDutyCycles[1], pulDutyCycles[2]);
}
}
//*****************************************************************************
//
//! Handles the gate driver precharge mode of the motor drive.
//!
//! This function performs the processing and state transitions associated with
//! the gate driver precharge mode of the motor drive.
//!
//! \return None.
//
//*****************************************************************************
static void
MainPrechargeHandler(void)
{
//
// Punch the watchdog to prevent timeout from killing our startup
// sequence.
//
WatchdogReloadSet(WATCHDOG_BASE, WATCHDOG_RELOAD_VALUE);
//
// Decrement the count of milliseconds while in this state.
//
g_ulStateCount--;
//
// See if the motor drive has been in the precharge state long enough.
//
if(g_ulStateCount != 0)
{
//
// There is nothing further to be done for this state.
//
return;
}
if(HWREGBITH(&(g_sParameters.usFlags), FLAG_SENSOR_BIT) ==
FLAG_SENSOR_ABSENT)
{
//
// For the manual commutation sequence in startup, set the commutation
// period to an integer number of milliseconds.
//
g_ulStartupHallStateCount = g_ulStartupHallStateCountReload = 50;
//
// Set the intial duty cycle.
//
g_ulDutyCycle = ((65536 * g_sParameters.ucStartupDutyCycle) / 100);
PWMSetDutyCycle(g_ulDutyCycle, g_ulDutyCycle, g_ulDutyCycle);
//
// Set the duration of the startup mode.
//
g_ulStateCount = g_sParameters.ulStartupCount;
//
// Set the forward/reverse state accordingly.
//
if(g_ulState == STATE_PRECHARGE)
{
g_ulState = STATE_STARTUP;
}
else
{
g_ulState = STATE_BACK_STARTUP;
}
//
// And return.
//
return;
}
//
// Set the miniumum duty cycle.
//
g_ulDutyCycle = 0;
PWMSetDutyCycle(g_ulDutyCycle, g_ulDutyCycle, g_ulDutyCycle);
//
// If trapezoid drive, kick start the motor by running a Hall interrupt.
// Otherwise, enable all the PWM outputs for other drive modes.
//
if(HWREGBITH(&(g_sParameters.usFlags), FLAG_DRIVE_BIT) ==
FLAG_DRIVE_TRAPEZOID)
{
GPIOBIntHandler();
}
else
{
PWMOutputOn();
}
//
// Advance the state machine to the appropriate acceleration state based on
// the motor direction.
//
if(g_ulState == STATE_PRECHARGE)
{
g_ulState = STATE_RUN;
}
else
{
g_ulState = STATE_BACK_RUN;
}
//
// Start the motor drive at zero.
//
g_ulSpeed = 0;
//
// Reset the integrator.
//
g_lSpeedIntegrator = 0;
//
// Start the motor drive at an angle of zero degrees.
//
g_ulAngle = 0;
}
//*****************************************************************************
//
//! Handles the startup mode of the motor drive.
//!
//! This function performs the processing and state transitions associated with
//! the startup mode of the motor drive for sensorless operation.
//!
//! \return None.
//
//*****************************************************************************
static void
MainStartupHandler(void)
{
static unsigned char ucHallSequence[] = {5, 1, 3, 2, 6, 4};
static unsigned char ucHallState = 0;
//
// Punch the watchdog to prevent timeout from killing our startup
// sequence.
//
WatchdogReloadSet(WATCHDOG_BASE, WATCHDOG_RELOAD_VALUE);
//
// See if the motor drive has been in the startup state long enough.
//
if(g_ulStateCount == 0)
{
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -