📄 main.c
字号:
static long g_lSpeedIntegrator;
//*****************************************************************************
//
//! The maximum value that of the PI controller accumulator
//! (#g_lSpeedIntegrator). This limit is based on the I coefficient and
//! the maximum duty cycle of the motor drive, and is used to avoid
//! "integrator windup", a potential pitfall of PI controllers.
//
//*****************************************************************************
static long g_lSpeedIntegratorMax;
//*****************************************************************************
//
//! The current state of the motor drive state machine. This state machine
//! controls acceleration, deceleration, starting, stopping, braking, and
//! reversing direction of the motor drive.
//
//*****************************************************************************
static unsigned long g_ulState = STATE_STOPPED;
//*****************************************************************************
//
//! The current speed of the motor. This value is updated based on whether
//! the encoder or Hall sensors are being used.
//
//*****************************************************************************
unsigned long g_ulMeasuredSpeed = 0;
//*****************************************************************************
//
//! The previous value of the "Hall" state for trapezoid modulation.
//
//*****************************************************************************
static unsigned long g_ulHallPrevious = 8;
//*****************************************************************************
//
//! The Stall Detection Count.
//
//*****************************************************************************
static unsigned long g_ulStallDetectCount = 0;
//*****************************************************************************
//
//! The Sine modulation target speed.
//
//*****************************************************************************
static unsigned long g_ulSineTarget = 0;
//*****************************************************************************
//
//! Handles errors from the driver library.
//!
//! This function is called when an error is encountered by the driver library.
//! Typically, the errors will be invalid parameters passed to the library's
//! APIs.
//!
//! In this application, nothing is done in this function. It does provide a
//! convenient location for a breakpoint that will catch all driver library
//! errors.
//!
//! \return None.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, unsigned long ulLine)
{
}
#endif
//*****************************************************************************
//
//! Multiplies two 16.16 fixed-point numbers.
//!
//! \param lX is the first multiplicand.
//! \param lY is the second multiplicand.
//!
//! This function takes two fixed-point numbers, in 16.16 format, and
//! multiplies them together, returning the 16.16 fixed-point result. It is
//! the responsibility of the caller to ensure that the dynamic range of the
//! integer portion of the value is not exceeded; if it is exceeded the result
//! will not be correct.
//!
//! \return Returns the result of the multiplication, in 16.16 fixed-point
//! format.
//
//*****************************************************************************
#if defined(ewarm) || defined(DOXYGEN)
static long
MainLongMul(long lX, long lY)
{
//
// The assembly code to efficiently perform the multiply (using the
// instruction to multiply two 32-bit values and return the full 64-bit
// result).
//
__asm(" smull r0, r1, r0, r1\n"
" lsrs r0, r0, #16\n"
" orr r0, r0, r1, lsl #16\n"
" bx lr");
//
// This return is never reached but is required to avoid a compiler
// warning.
//
return(0);
}
#endif
#if defined(gcc) || defined(sourcerygxx)
static long __attribute__((naked))
MainLongMul(long lX, long lY)
{
//
// The assembly code to efficiently perform the multiply (using the
// instruction to multiply two 32-bit values and return the full 64-bit
// result).
//
__asm(" smull r0, r1, r0, r1\n"
" lsrs r0, r0, #16\n"
" orr r0, r0, r1, lsl #16\n"
" bx lr");
//
// This return is never reached but is required to avoid a compiler
// warning.
//
return(0);
}
#endif
#if defined(rvmdk) || defined(__ARMCC_VERSION)
__asm long
MainLongMul(long lX, long lY)
{
//
// The assembly code to efficiently perform the multiply (using the
// instruction to multiply two 32-bit values and return the full 64-bit
// result).
//
smull r0, r1, r0, r1;
lsrs r0, r0, #16;
orr r0, r0, r1, lsl #16;
bx lr;
}
#endif
//*****************************************************************************
//
//! Changes the PWM frequency of the motor drive.
//!
//! This function changes the period of the PWM signals produced by the motor
//! drive. It is simply a wrapper function around the PWMSetFrequency()
//! function; the PWM frequency-based timing parameters of the motor drive are
//! adjusted as part of the PWM frequency update.
//!
//! \return None.
//
//*****************************************************************************
void
MainSetPWMFrequency(void)
{
//
// Disable the update interrupts temporarily.
//
IntDisable(INT_PWM1);
IntDisable(INT_PWM2);
//
// Set the new PWM frequency.
//
PWMSetFrequency();
//
// Compute the new angle delta based on the new PWM frequency and the
// number of poles in the motor.
//
g_ulAngleDelta = (((g_ulSpeed / 60) << 9) / g_ulPWMFrequency) << 9;
g_ulAngleDelta *= (g_sParameters.ucNumPoles + 1);
//
// Re-enable the update interrupts.
//
IntEnable(INT_PWM1);
IntEnable(INT_PWM2);
}
//*****************************************************************************
//
//! Changes the target speed of the motor drive.
//!
//! This function changes the target speed of the motor drive. If
//! required, the state machine will be transitioned to a new state in order to
//! move the motor drive to the target speed.
//!
//! \return None.
//
//*****************************************************************************
void
MainSetSpeed(void)
{
//
// Clip the target speed to the minimum speed if it is too small.
//
if(g_ulTargetSpeed < g_sParameters.ulMinSpeed)
{
g_ulTargetSpeed = g_sParameters.ulMinSpeed;
}
//
// Clip the target speed to the maximum speed if it is too large.
//
if(g_ulTargetSpeed > g_sParameters.ulMaxSpeed)
{
g_ulTargetSpeed = g_sParameters.ulMaxSpeed;
}
}
//*****************************************************************************
//
//! Sets the direction of the motor drive.
//!
//! \param bForward is a boolean that is true if the motor drive should be
//! run in the forward direction.
//!
//! This function changes the direction of the motor drive. If required, the
//! state machine will be transitioned to a new state in order to change the
//! direction of the motor drive.
//!
//! \return None.
//
//*****************************************************************************
void
MainSetDirection(tBoolean bForward)
{
//
// Temporarily disable the millisecond interrupt.
//
IntDisable(INT_PWM2);
//
// See if the motor should be running in the forward direction.
//
if(bForward)
{
//
// See if the motor is presently running backward.
//
if(g_ulState == STATE_BACK_RUN)
{
//
// If not already decelerating, then set the initial deceleration
// rate based on the configured parameter value.
//
if(g_ucMotorStatus != MOTOR_STATUS_DECEL)
{
g_ulDecelRate = g_sParameters.usDecel << 16;
}
//
// Advance the state machine to the decelerate to reverse direction
// state.
//
g_ulState = STATE_BACK_REV;
}
//
// See if the motor is presently running forward but in the process of
// reversing to the backward direction.
//
if(g_ulState == STATE_REV)
{
//
// Leave the motor drive running in the forward direction.
//
g_ulState = STATE_RUN;
}
}
//
// Otherwise the motor should be running in the backward direction.
//
else
{
//
// See if the motor is presently running forward.
//
if(g_ulState == STATE_RUN)
{
//
// If not already decelerating, then set the initial deceleration
// rate based on the configured parameter value.
//
if(g_ucMotorStatus != MOTOR_STATUS_DECEL)
{
g_ulDecelRate = g_sParameters.usDecel << 16;
}
//
// Advance the state machine to the decelerate to reverse direction
// state.
//
g_ulState = STATE_REV;
}
//
// See if the motor is presently running backward but in the process of
// reversing to the forward direction.
//
if(g_ulState == STATE_BACK_REV)
{
//
// Leave the motor drive running in the backward direction.
//
g_ulState = STATE_BACK_RUN;
}
}
//
// Re-enable the millisecond interrupt.
//
IntEnable(INT_PWM2);
}
//*****************************************************************************
//
//! Updates the I coefficient of the speed PI controller.
//!
//! \param lNewFAdjI is the new value of the I coefficient.
//!
//! This function updates the value of the I coefficient of the duty cycle PI
//! controller. In addition to updating the I coefficient, it recomputes the
//! maximum value of the integrator and the current value of the integrator in
//! terms of the new I coefficient (eliminating any instantaneous jump in the
//! output of the PI controller).
//!
//! \return None.
//
//*****************************************************************************
void
MainUpdateFAdjI(long lNewFAdjI)
{
//
// Temporarily disable the millisecond interrupt.
//
IntDisable(INT_PWM2);
//
// See if the new I coefficient is zero.
//
if(lNewFAdjI == 0)
{
//
// Since the I coefficient is zero, the integrator and integrator
// maximum are also zero.
//
g_lSpeedIntegratorMax = 0;
g_lSpeedIntegrator = 0;
}
else
{
//
// Compute the maximum value of the integrator. This is the value that
// results in the maximum output duty cycle (i.e. integrator max * I =
// max speed).
//
g_lSpeedIntegratorMax = 65536 * 100;
//
// Adjust the current value of the integrator to account for the new
// value of the I coefficient. This satisfies the equation "old
// integrator * old I = new integrator * new I", so that the output
// doesn't immediately change (in a drastic way) as a result of the
// change in the I coefficient.
//
g_lSpeedIntegrator = ((g_lSpeedIntegrator / lNewFAdjI) *
g_sParameters.lFAdjI);
}
//
// Save the new I coefficient.
//
g_sParameters.lFAdjI = lNewFAdjI;
//
// Re-enable the millisecond interrupt.
//
IntEnable(INT_PWM2);
}
//*****************************************************************************
//
//! Handles the waveform update software interrupt.
//!
//! This function is periodically called as a result of the waveform update
//! software interrupt being asserted. This interrupt is asserted at the
//! requested rate (based on the update rate parameter) by the PWM interrupt
//! handler.
//!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -