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

📄 speed_sense.c

📁 Luminary Micro BLDC motor control software
💻 C
📖 第 1 页 / 共 2 页
字号:
    // See if this edge should be skipped.
    //
    if(HWREGBITW(&g_ulSpeedFlags, FLAG_SKIP_BIT))
    {
        //
        // This edge should be skipped, but an edge time now exists so the next
        // edge should not be skipped.
        //
        HWREGBITW(&g_ulSpeedFlags, FLAG_SKIP_BIT) = 0;

        //
        // There is nothing further to be done.
        //
        return;
    }

    //
    // Indicate that an edge has been seen to prevent the QEI interrupt handler
    // from forcing the rotor speed to zero.
    //
    HWREGBITW(&g_ulSpeedFlags, FLAG_EDGE_BIT) = 1;

    //
    // Compute the new speed from the time between edges.
    //
    SpeedNewValue(((unsigned long)SYSTEM_CLOCK * (unsigned long)60) /
                  (ulTime * (g_sParameters.usNumEncoderLines + 1)));

    //
    // See if the edge time has become too small, meaning that the number of
    // edges per second is too large.
    //
    if(ulTime < (SYSTEM_CLOCK / (MAX_EDGE_COUNT + EDGE_DELTA)))
    {
        //
        // Edge counting mode should be used instead of edge timing mode.
        //
        HWREGBITW(&g_ulSpeedFlags, FLAG_COUNT_BIT) = 1;

        //
        // Disable the GPIO interrupt while using edge counting mode.
        //
        IntDisable(INT_GPIOC);

        //
        // Indicate that the first timing period should be skipped in edge
        // count mode.
        //
        HWREGBITW(&g_ulSpeedFlags, FLAG_SKIP_BIT) = 1;
    }
}

//*****************************************************************************
//
//! Handles the QEI velocity interrupt.
//!
//! This function is called when the QEI velocity timer expires.  If using the
//! edge counting mode for rotor speed determination, the number of edges
//! counted during the last velocity period is used as a measure of the rotor
//! speed.
//!
//! \return None.
//
//*****************************************************************************
void
QEIIntHandler(void)
{
    unsigned long ulPrev, ulCount;

    //
    // Clear the QEI interrupt.
    //
    QEIIntClear(QEI0_BASE, QEI_INTTIMER);

    //
    // Increment the accumulated time to extend the range of the QEI timer,
    // which is used by the edge timing mode.
    //
    g_ulSpeedTime += SYSTEM_CLOCK / QEI_INT_RATE;

    //
    // See if edge counting mode is enabled.
    //
    if(HWREGBITW(&g_ulSpeedFlags, FLAG_COUNT_BIT) == 0)
    {
        //
        // Edge timing mode is currenting operating, so see if an edge was seen
        // during this QEI timing period.
        //
        if(HWREGBITW(&g_ulSpeedFlags, FLAG_EDGE_BIT) == 0)
        {
            //
            // No edge was seen, so set the rotor speed to zero.
            //
            g_ulRotorSpeed = 0;

            //
            // Since the amount of time the rotor is stopped is indeterminate,
            // skip the first edge when the rotor starts rotating again.
            //
            HWREGBITW(&g_ulSpeedFlags, FLAG_SKIP_BIT) = 1;
        }
        else
        {
            //
            // An edge was seen, so clear the flag so the next period can be
            // checked as well, and restart the edge reset counter.
            //
            HWREGBITW(&g_ulSpeedFlags, FLAG_EDGE_BIT) = 0;
        }

        //
        // There is nothing further to do.
        //
        return;
    }

    //
    // Get the number of edges during the most recent period.
    //
    ulCount = QEIVelocityGet(QEI0_BASE);

    //
    // Get the count of edges in the previous timing period.
    //
    ulPrev = g_ulSpeedPrevious;

    //
    // Save the count of edges during this timing period.
    //
    g_ulSpeedPrevious = ulCount;

    //
    // See if this timing period should be skipped.
    //
    if(HWREGBITW(&g_ulSpeedFlags, FLAG_SKIP_BIT))
    {
        //
        // This timing period should be skipped, but an edge count from a
        // previous timing period now exists so the next timing period should
        // not be skipped.
        //
        HWREGBITW(&g_ulSpeedFlags, FLAG_SKIP_BIT) = 0;

        //
        // There is nothing further to be done.
        //
        return;
    }

    //
    // Average the edge count for the previous two timing periods.
    //
    ulCount = (ulPrev + ulCount) / 2;

    //
    // Compute the new speed from the number of edges.  Note that both
    // edges are counted by the QEI block, so the count for a full revolution
    // is double the number of encoder lines.
    //
    SpeedNewValue((ulCount * QEI_INT_RATE * 30) /
                  (g_sParameters.usNumEncoderLines + 1));

    //
    // See if the number of edges has become too small, meaning that the edge
    // time has become large enough.
    //
    if(ulCount < (((MAX_EDGE_COUNT - EDGE_DELTA) * 2) / QEI_INT_RATE))
    {
        //
        // Edge timing mode should be used instead of edge counting mode.
        //
        HWREGBITW(&g_ulSpeedFlags, FLAG_COUNT_BIT) = 0;

        //
        // Indicate that the first edge should be skipped in edge timing mode.
        //
        HWREGBITW(&g_ulSpeedFlags, FLAG_SKIP_BIT) = 1;

        //
        // Enable the GPIO interrupt to enable edge timing mode.
        //
        IntEnable(INT_GPIOC);
    }
}

//*****************************************************************************
//
//! Initializes the speed sensing routines.
//!
//! This function will initialize the peripherals used determine the speed of
//! the motor's rotor.
//!
//! \return None.
//
//*****************************************************************************
void
SpeedSenseInit(void)
{
    //
    // Configure the encoder A pin for use by the QEI block.  Even though this
    // pin is now used to drive the QEI block, its state is still visible to
    // the GPIO block.
    //
    GPIOPinTypeQEI(PIN_ENCA_PORT, PIN_ENCA_PIN);

    //
    // A GPIO interrupt should be generated on rising edges of the encoder A
    // pin.
    //
    GPIOIntTypeSet(PIN_ENCA_PORT, PIN_ENCA_PIN, GPIO_RISING_EDGE);

    //
    // Enable the encoder A pin GPIO interrupt.
    //
    GPIOPinIntEnable(PIN_ENCA_PORT, PIN_ENCA_PIN);
    IntEnable(INT_GPIOC);

    //
    // Configure the QEI block for capturing the velocity of the encoder A pin
    // (which it does by counting the number of edges during a fixed time
    // period).
    //
    QEIConfigure(QEI0_BASE, (QEI_CONFIG_CAPTURE_A | QEI_CONFIG_NO_RESET |
                             QEI_CONFIG_CLOCK_DIR | QEI_CONFIG_NO_SWAP), 0);
    QEIVelocityConfigure(QEI0_BASE, QEI_VELDIV_1, SYSTEM_CLOCK / QEI_INT_RATE);

    //
    // Enable the QEI block and the velocity capture.
    //
    QEIEnable(QEI0_BASE);
    QEIVelocityEnable(QEI0_BASE);

    //
    // Enable the QEI velocity interrupt.
    //
    QEIIntEnable(QEI0_BASE, QEI_INTTIMER);
    IntEnable(INT_QEI0);
}

//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************

⌨️ 快捷键说明

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