📄 pwm_ctrl.c
字号:
//
// Set the flag indicating that the duty cycles need to be updated.
//
HWREGBITW(&g_ulPWMFlags, PWM_FLAG_NEW_DUTY_CYCLE) = 1;
//
// Re-enable the PWM interrupt.
//
IntEnable(INT_PWM0);
}
//*****************************************************************************
//
//! Sets the PWM outputs to precharge the high side gate drives.
//!
//! This function configures the PWM outputs such that they will start charging
//! the bootstrap capacitor on the high side gate drives. Without this step,
//! the high side gates will not turn on properly for the first several PWM
//! cycles when starting the motor drive.
//!
//! \return None.
//
//*****************************************************************************
void
PWMOutputPrecharge(void)
{
//
// Punch the watchdog to make sure we don't get reset.
//
WatchdogReloadSet(WATCHDOG_BASE, WATCHDOG_RELOAD_VALUE);
//
// Ensure that all outputs are not-inverted.
//
PWMOutputInvert(PWM_BASE, (PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT |
PWM_OUT_3_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT),
false);
//
// Disable the high and low side switches.
//
PWMOutputState(PWM_BASE, PWM_OUT_0_BIT | PWM_OUT_2_BIT | PWM_OUT_4_BIT,
false);
PWMOutputState(PWM_BASE, PWM_OUT_1_BIT | PWM_OUT_3_BIT | PWM_OUT_5_BIT,
false);
//
// Set the PWM duty cycles to 3% (negative side).
//
g_ulPWMDutyCycleA = ((97 * 65535) / 100);
g_ulPWMDutyCycleB = ((97 * 65535) / 100);
g_ulPWMDutyCycleC = ((97 * 65535) / 100);
//
// Set the PWM period based on the configured PWM frequency.
//
PWMGenPeriodSet(PWM_BASE, PWM_GEN_0, g_ulPWMClock);
PWMGenPeriodSet(PWM_BASE, PWM_GEN_1, g_ulPWMClock);
PWMGenPeriodSet(PWM_BASE, PWM_GEN_2, g_ulPWMClock);
//
// Update the PWM duty cycles.
//
PWMUpdateDutyCycle();
//
// Indicate that a precharge has been started.
//
HWREGBITW(&g_ulPWMFlags, PWM_FLAG_NEW_PRECHARGE) = 1;
}
//*****************************************************************************
//
//! Turns on all the PWM outputs.
//!
//! This function turns on all of the PWM outputs, allowing them to be
//! propagated to the gate drivers.
//!
//! \return None.
//
//*****************************************************************************
void
PWMOutputOn(void)
{
//
// Punch the watchdog to make sure we don't get reset.
//
WatchdogReloadSet(WATCHDOG_BASE, WATCHDOG_RELOAD_VALUE);
//
// Ensure that all outputs are not-inverted.
//
PWMOutputInvert(PWM_BASE, (PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT |
PWM_OUT_3_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT),
false);
//
// Enable all six PWM outputs.
//
PWMOutputState(PWM_BASE, (PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT |
PWM_OUT_3_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT),
true);
}
//*****************************************************************************
//
//! Enable/Disable PWM outputs as needed for Trapezoid modulation.
//!
//! \param ulEnable is the bit-mapped value representing which phase(s)
//! of the motor drive should be active.
//!
//! This function turns off non-selected outputs and turns on selected
//! outputs. If slow decay mode is enabled, the high side is driven in
//! complementary mode.
//!
//! \return None.
//
//*****************************************************************************
void
PWMOutputTrapezoid(unsigned long ulEnable)
{
unsigned long ulHigh, ulLow;
//
// Disable ADC interrupts that reference the PWM output/invert states.
//
IntDisable(INT_ADC0);
IntDisable(INT_ADC3);
//
// Punch the watchdog to make sure we don't get reset.
//
WatchdogReloadSet(WATCHDOG_BASE, WATCHDOG_RELOAD_VALUE);
//
// Determine the high and low phase outputs.
//
ulHigh = ulEnable & (PWM_OUT_0_BIT | PWM_OUT_2_BIT | PWM_OUT_4_BIT);
ulLow = ulEnable & (PWM_OUT_1_BIT | PWM_OUT_3_BIT | PWM_OUT_5_BIT);
//
// If driving in slow decay mode, enable the low side of the high phase.
//
if(HWREGBITH(&(g_sParameters.usFlags), FLAG_DECAY_BIT) == FLAG_DECAY_SLOW)
{
ulHigh = ulHigh | (ulHigh << 1);
}
//
// Disable inversion on non-selected low phase.
//
PWMOutputInvert(PWM_BASE,
ulLow ^ (PWM_OUT_1_BIT | PWM_OUT_3_BIT | PWM_OUT_5_BIT),
false);
//
// Disable the non-selected PWM outputs.
//
PWMOutputState(PWM_BASE,
ulHigh ^ (PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT |
PWM_OUT_3_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT),
false);
//
// Enable the selected PWM high phase outputs.
//
PWMOutputState(PWM_BASE, ulHigh, true);
//
// Enable the low phase inverted output.
//
PWMOutputInvert(PWM_BASE, ulLow, true);
//
// Reenable the ADC interrupts that reference the PWM output/invert states.
//
IntEnable(INT_ADC3);
IntEnable(INT_ADC0);
}
//*****************************************************************************
//
//! Turns off all the PWM outputs.
//!
//! This function turns off all of the PWM outputs, preventing them from being
//! propagates to the gate drivers.
//!
//! \return None.
//
//*****************************************************************************
void
PWMOutputOff(void)
{
//
// Disable all six PWM outputs.
//
PWMOutputState(PWM_BASE, (PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT |
PWM_OUT_3_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT),
false);
//
// Ensure that all outputs are not-inverted.
//
PWMOutputInvert(PWM_BASE, (PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT |
PWM_OUT_3_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT),
false);
//
// Set the PWM duty cycles to 50%.
//
g_ulPWMDutyCycleA = 32768;
g_ulPWMDutyCycleB = 32768;
g_ulPWMDutyCycleC = 32768;
//
// Set the PWM period so that the ADC runs at 1 KHz.
//
PWMGenPeriodSet(PWM_BASE, PWM_GEN_0, PWM_CLOCK / 1000);
PWMGenPeriodSet(PWM_BASE, PWM_GEN_1, PWM_CLOCK / 1000);
PWMGenPeriodSet(PWM_BASE, PWM_GEN_2, PWM_CLOCK / 1000);
//
// Update the PWM duty cycles.
//
PWMUpdateDutyCycle();
}
//*****************************************************************************
//
//! Changes the update rate of the motor drive.
//!
//! \param ucUpdateRate is the number of PWM periods between updates.
//!
//! This function changes the rate at which the motor drive waveforms are
//! recomputed. Lower update values recompute the waveforms more frequently,
//! providing more accurate waveforms at the cost of increased processor usage.
//!
//! \return None.
//
//*****************************************************************************
void
PWMSetUpdateRate(unsigned char ucUpdateRate)
{
//
// Temporarily disable the PWM period interrupt. Once disabled, it is no
// longer possible for the waveform update software interrupt to be
// triggered.
//
IntDisable(INT_PWM0);
//
// Change the update rate parameter.
//
g_sParameters.ucUpdateRate = ucUpdateRate;
//
// Re-enable the PWM period interrupt.
//
IntEnable(INT_PWM0);
}
//*****************************************************************************
//
//! Initializes the PWM control routines.
//!
//! This function initializes the PWM module and the control routines,
//! preparing them to produce PWM waveforms to drive the power module.
//!
//! \return None.
//
//*****************************************************************************
void
PWMInit(void)
{
//
// Make the PWM pins be peripheral function.
//
GPIOPinTypePWM(PIN_PHASEA_LOW_PORT,
PIN_PHASEA_LOW_PIN | PIN_PHASEA_HIGH_PIN);
GPIOPinTypePWM(PIN_PHASEB_LOW_PORT,
PIN_PHASEB_LOW_PIN | PIN_PHASEB_HIGH_PIN);
GPIOPinTypePWM(PIN_PHASEC_LOW_PORT,
PIN_PHASEC_LOW_PIN | PIN_PHASEC_HIGH_PIN);
//
// Configure the three PWM generators for up/down counting mode,
// synchronous updates, and to stop at zero on debug events.
//
PWMGenConfigure(PWM_BASE, PWM_GEN_0, (PWM_GEN_MODE_UP_DOWN |
PWM_GEN_MODE_SYNC |
PWM_GEN_MODE_DBG_STOP));
PWMGenConfigure(PWM_BASE, PWM_GEN_1, (PWM_GEN_MODE_UP_DOWN |
PWM_GEN_MODE_SYNC |
PWM_GEN_MODE_DBG_STOP));
PWMGenConfigure(PWM_BASE, PWM_GEN_2, (PWM_GEN_MODE_UP_DOWN |
PWM_GEN_MODE_SYNC |
PWM_GEN_MODE_DBG_STOP));
//
// Set the initial duty cycles to 50%.
//
g_ulPWMDutyCycleA = 32768;
g_ulPWMDutyCycleB = 32768;
g_ulPWMDutyCycleC = 32768;
//
// Configure the PWM period, duty cycle, and dead band. The initial period
// is 1 KHz (for triggering the ADC), which will be increased when the
// motor starts running.
//
PWMSetDeadBand();
PWMSetFrequency();
PWMGenPeriodSet(PWM_BASE, PWM_GEN_0, PWM_CLOCK / 1000);
PWMGenPeriodSet(PWM_BASE, PWM_GEN_1, PWM_CLOCK / 1000);
PWMGenPeriodSet(PWM_BASE, PWM_GEN_2, PWM_CLOCK / 1000);
PWMUpdateDutyCycle();
//
// Enable the PWM generators.
//
PWMGenEnable(PWM_BASE, PWM_GEN_0);
PWMGenEnable(PWM_BASE, PWM_GEN_1);
PWMGenEnable(PWM_BASE, PWM_GEN_2);
//
// Synchronize the time base of the generators.
//
PWMSyncTimeBase(PWM_BASE, PWM_GEN_0_BIT | PWM_GEN_1_BIT | PWM_GEN_2_BIT);
//
// Configure an interrupt on the zero event of the first generator, and an
// ADC trigger on the load event of the first generator.
//
PWMGenIntClear(PWM_BASE, PWM_GEN_0, PWM_INT_CNT_ZERO);
PWMGenIntTrigEnable(PWM_BASE, PWM_GEN_0,
PWM_INT_CNT_ZERO | PWM_TR_CNT_LOAD);
PWMGenIntTrigEnable(PWM_BASE, PWM_GEN_1, 0);
PWMGenIntTrigEnable(PWM_BASE, PWM_GEN_2, 0);
IntEnable(INT_PWM0);
IntEnable(INT_PWM1);
IntEnable(INT_PWM2);
//
// Set all six PWM outputs to go to the inactive state when a fault event
// occurs (which includes debug events).
//
PWMOutputFault(PWM_BASE, (PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT |
PWM_OUT_3_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT),
true);
//
// Disable all six PWM outputs.
//
PWMOutputState(PWM_BASE, (PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT |
PWM_OUT_3_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT),
false);
//
// Ensure that all outputs are not-inverted.
//
PWMOutputInvert(PWM_BASE, (PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT |
PWM_OUT_3_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT),
false);
}
//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -