⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pwm_ctrl.c

📁 Luminary Micro BLDC motor control software
💻 C
📖 第 1 页 / 共 3 页
字号:

            //
            // Done with this PWM frequency.
            //
            break;
        }

        //
        // The PWM frequency is 16 KHz.
        //
        case FLAG_PWM_FREQUENCY_16K:
        {
            //
            // Set the PWM frequency variable.
            //
            g_ulPWMFrequency = 16000;

            //
            // Get the number of PWM clocks in a 16 KHz period.
            //
            g_ulPWMClock = PWM_CLOCK / 16000;

            //
            // Done with this PWM frequency.
            //
            break;
        }

        //
        // The PWM frequency is 20 KHz.
        //
        case FLAG_PWM_FREQUENCY_20K:
        default:
        {
            //
            // Set the PWM frequency variable.
            //
            g_ulPWMFrequency = 20000;

            //
            // Get the number of PWM clocks in a 20 KHz period.
            //
            g_ulPWMClock = PWM_CLOCK / 20000;

            //
            // Done with this PWM frequency.
            //
            break;
        }
    }

    //
    // Indicate that the PWM frequency needs to be updated.
    //
    HWREGBITW(&g_ulPWMFlags, PWM_FLAG_NEW_FREQUENCY) = 1;

    //
    // Re-enable the PWM interrupt.
    //
    IntEnable(INT_PWM0);
}

//*****************************************************************************
//
//! Updates the duty cycle in the PWM module.
//!
//! This function programs the duty cycle of the PWM waveforms into the PWM
//! module.  The changes will be written to the hardware and the hardware
//! instructed to start using the new values the next time its counters reach
//! zero.
//!
//! \return None.
//
//*****************************************************************************
static void
PWMUpdateDutyCycle(void)
{
    unsigned long ulWidth;

    //
    // Get the pulse width of the A phase of the motor.
    //
    ulWidth = (g_ulPWMDutyCycleA * g_ulPWMClock) / 65536;
    if(ulWidth > g_ulPWMClock)
    {
        ulWidth = g_ulPWMClock;
    }
    if(ulWidth < g_ulMinPulseWidth)
    {
        ulWidth = g_ulMinPulseWidth;
    }
    if((g_ulPWMClock - ulWidth) < g_ulMinPulseWidth)
    {
        ulWidth = g_ulPWMClock - g_ulMinPulseWidth;
    }

    //
    // Set the pulse width of the A phase of the motor.
    //
    PWMPulseWidthSet(PWM_BASE, PWM_OUT_0, ulWidth);

    //
    // Update duty cycle for trapezoid current calculation.
    //
    g_ulTrapDutyCycle = (ulWidth * 100) / g_ulPWMClock;

    //
    // Get the pulse width of the B phase of the motor.
    //
    ulWidth = (g_ulPWMDutyCycleB * g_ulPWMClock) / 65536;
    if(ulWidth > g_ulPWMClock)
    {
        ulWidth = g_ulPWMClock;
    }
    if(ulWidth < g_ulMinPulseWidth)
    {
        ulWidth = g_ulMinPulseWidth;
    }
    if((g_ulPWMClock - ulWidth) < g_ulMinPulseWidth)
    {
        ulWidth = g_ulPWMClock - g_ulMinPulseWidth;
    }

    //
    // Set the pulse width of the B phase of the motor.
    //
    PWMPulseWidthSet(PWM_BASE, PWM_OUT_2, ulWidth);

    //
    // Get the pulse width of the C phase of the motor.
    //
    ulWidth = (g_ulPWMDutyCycleC * g_ulPWMClock) / 65536;
    if(ulWidth > g_ulPWMClock)
    {
        ulWidth = g_ulPWMClock;
    }
    if(ulWidth < g_ulMinPulseWidth)
    {
        ulWidth = g_ulMinPulseWidth;
    }
    if((g_ulPWMClock - ulWidth) < g_ulMinPulseWidth)
    {
        ulWidth = g_ulPWMClock - g_ulMinPulseWidth;
    }

    //
    // Set the pulse width of the C phase of the motor.
    //
    PWMPulseWidthSet(PWM_BASE, PWM_OUT_4, ulWidth);

    //
    // Perform a synchronous update of all three PWM generators.
    //
    PWMSyncUpdate(PWM_BASE, PWM_GEN_0_BIT | PWM_GEN_1_BIT | PWM_GEN_2_BIT);
}

//*****************************************************************************
//
//! Handles the PWM interrupt.
//!
//! This function is called as a result of the interrupt generated by the PWM
//! module when the counter reaches zero.  If an updated PWM frequency or duty
//! cycle is available, they will be updated in the hardware by this function.
//!
//! \return None.
//
//*****************************************************************************
void
PWM0IntHandler(void)
{
    //
    // Clear the PWM interrupt.  This is done twice since the clear will be
    // ignored by hardware if it occurs on the same cycle as another interrupt
    // event; the second clear takes care of the case wehre the first gets
    // ignored.
    //
    PWMGenIntClear(PWM_BASE, PWM_GEN_0, PWM_INT_CNT_ZERO);
    PWMGenIntClear(PWM_BASE, PWM_GEN_0, PWM_INT_CNT_ZERO);

    //
    // Increment the count of PWM periods.
    //
    g_ulPWMPeriodCount++;

    //
    // See if it is time for a new PWM duty cycle, based on the correct number
    // of PWM periods passing and the availability of new duty cycle values.
    //
    if((g_ulPWMPeriodCount > g_sParameters.ucUpdateRate) &&
       (HWREGBITW(&g_ulPWMFlags, PWM_FLAG_NEW_DUTY_CYCLE) == 1))
    {
        //
        // See if the PWM frequency needs to be updated.
        //
        if(HWREGBITW(&g_ulPWMFlags, PWM_FLAG_NEW_FREQUENCY) == 1)
        {
            //
            // Set the new PWM period in each of the PWM generators.
            //
            PWMGenPeriodSet(PWM_BASE, PWM_GEN_0, g_ulPWMClock);
            PWMGenPeriodSet(PWM_BASE, PWM_GEN_1, g_ulPWMClock);
            PWMGenPeriodSet(PWM_BASE, PWM_GEN_2, g_ulPWMClock);

            //
            // Indicate that the PWM frequency has been updated.
            //
            HWREGBITW(&g_ulPWMFlags, PWM_FLAG_NEW_FREQUENCY) = 0;
        }

        //
        // Update the duty cycle.
        //
        PWMUpdateDutyCycle();

        //
        // Clear the duty cycle update flag.
        //
        HWREGBITW(&g_ulPWMFlags, PWM_FLAG_NEW_DUTY_CYCLE) = 0;
    }

    //
    // Start a precharge cycle.
    //
    if(HWREGBITW(&g_ulPWMFlags, PWM_FLAG_NEW_PRECHARGE) == 1)
    {
        //
        // Enable the low side switches.
        //
        PWMOutputState(PWM_BASE, PWM_OUT_1_BIT | PWM_OUT_3_BIT | PWM_OUT_5_BIT,
                       true);

        //
        // Clear the flag.
        //
        HWREGBITW(&g_ulPWMFlags, PWM_FLAG_NEW_PRECHARGE) = 0;
    }

    //
    // If the required number of PWM periods have expired, request an update of
    // the duty cycle computations.
    //
    if(g_ulPWMPeriodCount >= (g_sParameters.ucUpdateRate + 1))
    {
        //
        // Trigger the waveform update software interrupt.
        //
        HWREG(NVIC_SW_TRIG) = INT_PWM1 - 16;
    }

    //
    // Increment the millisecond counter.  By adding 1000 for each PWM
    // interrupt, it will take one millisecond for the counter to reach the PWM
    // frequency.
    //
    g_ulPWMMillisecondCount += 1000;

    //
    // See if a millisecond has expired.
    //
    if(g_ulPWMMillisecondCount >= g_ulPWMFrequency)
    {
        //
        // Trigger the millisecond software interrupt.
        //
        HWREG(NVIC_SW_TRIG) = INT_PWM2 - 16;

        //
        // Decrement the millisecond counter by the PWM frequency, which
        // corresponds to one millisecond.
        //
        g_ulPWMMillisecondCount -= g_ulPWMFrequency;
    }
}

//*****************************************************************************
//
//! Gets the number of PWM interrupts that have occurred.
//!
//! This function returns the number of PWM interrupts that have been counted.
//! Used in conjunction with the desired update rate, missed waveform updates
//! can be detected and compensated for.
//!
//! \return The number of PWM interrupts that have been counted.
//
//*****************************************************************************
unsigned long
PWMGetPeriodCount(void)
{
    //
    // Return the count of PWM periods.
    //
    return(g_ulPWMPeriodCount);
}

//*****************************************************************************
//
//! Reduces the count of PWM interrupts.
//!
//! \param ulCount is the number by which to reduce the PWM interrupt count.
//!
//! This function reduces the PWM interrupt count by a given number.  When the
//! waveform values are updated, the interrupt count can be reduced by the
//! appropriate amount to maintain a proper indication of when the next
//! waveform update should occur.
//!
//! If the PWM interrupt count is not reduced when the waveforms are
//! recomputed, the waveform update software interrupt will not be triggered as
//! desired.
//!
//! \return None.
//
//*****************************************************************************
void
PWMReducePeriodCount(unsigned long ulCount)
{
    //
    // Disable the PWM interrupt temporarily.
    //
    IntDisable(INT_PWM0);

    //
    // Decrement the PWM period count by the given number.
    //
    g_ulPWMPeriodCount -= ulCount;

    //
    // Re-enable the PWM interrupt.
    //
    IntEnable(INT_PWM0);
}

//*****************************************************************************
//
//! Sets the duty cycle of the generated PWM waveforms.
//!
//! \param ulDutyCycleA is the duty cycle of the waveform for the U phase of
//! the motor, specified as a 16.16 fixed point value between 0.0 and 1.0.
//! \param ulDutyCycleB is the duty cycle of the waveform for the V phase of
//! the motor, specified as a 16.16 fixed point value between 0.0 and 1.0.
//! \param ulDutyCycleC is the duty cycle of the waveform for the W phase of
//! the motor, specified as a 16.16 fixed point value between 0.0 and 1.0.
//!
//! This function configures the duty cycle of the generated PWM waveforms.
//! The duty cycle update will not occur immediately; the change will be
//! registered for synchronous application to the output waveforms to avoid
//! discontinuities.
//!
//! \return None.
//
//*****************************************************************************
void
PWMSetDutyCycle(unsigned long ulDutyCycleA, unsigned long ulDutyCycleB,
                unsigned long ulDutyCycleC)
{
    //
    // Punch the watchdog to make sure we don't get reset.
    // (only if we are SINE modulation mode)
    //
    if(HWREGBITH(&(g_sParameters.usFlags), FLAG_DRIVE_BIT) == FLAG_DRIVE_SINE)
    {
        WatchdogReloadSet(WATCHDOG_BASE, WATCHDOG_RELOAD_VALUE);
    }

    //
    // Disable the PWM interrupt temporarily.
    //
    IntDisable(INT_PWM0);

    //
    // Save the duty cycles for the three phases.
    //
    g_ulPWMDutyCycleA = ulDutyCycleA;
    g_ulPWMDutyCycleB = ulDutyCycleB;
    g_ulPWMDutyCycleC = ulDutyCycleC;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -