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

📄 adc_ctrl.c

📁 Luminary Micro BLDC motor control software
💻 C
📖 第 1 页 / 共 4 页
字号:
    //
    g_usAnalogInputVoltage =
        (((unsigned long)g_pusFilteredData1[0] * 3000 * 240) / 140) / 1024;
}

//*****************************************************************************
//
//! Handles the ADC sample sequence two interrupt.
//!
//! This function is called when sample sequence two asserts an interrupt.  It
//! handles clearing the interrupt, processing any sequence overflow
//! conditions, and processing the new ADC data in the FIFO.  This sequence is
//! used to measure the linear Hall sensor inputs.  This sequence is only 
//! enabled when the Hall sensors are enabled and configured as linear Hall
//! sensors.  The linear Hall data is read and converted to an equivalent
//! "digital" Hall data value.  When change in the "digital" Hall state is
//! detected, the speed calculation routines are run if a complete electical
//! revolution has occurred.
//!
//! \return None.
//
//*****************************************************************************
void
ADC2IntHandler(void)
{
    unsigned long ulIdx;
    unsigned short pusADCData[3];
    static unsigned long ulLinearCount = 0;
    unsigned long ulNewTime, ulTime;

    //
    // Get the time for this interrupt.
    //
    ulNewTime = UIGetTicks();

    //
    // Clear the ADC interrupt.
    //
    HWREG(ADC_BASE + ADC_O_ISC) = ADC_ISC_IN2;

    //
    // Reset the sequence if an overflow has occurred.
    //
    if(HWREG(ADC_BASE + ADC_O_OSTAT) & ADC_OSTAT_OV2)
    {
        //
        // Disable the sequence.
        //
        HWREG(ADC_BASE + ADC_O_ACTSS) &= ~ADC_ACTSS_ASEN2;

        //
        // Drain the Sequence FIFO.
        //
        while(!(HWREG(ADC_BASE + ADC_O_SSFSTAT2) & ADC_SSFSTAT2_EMPTY))
        {
            //
            // Read the next sample.
            //
            pusADCData[0] = HWREG(ADC_BASE + ADC_O_SSFIFO2);
        }

        //
        // Clear any overflow/underflow conditions that might exist.
        //
        HWREG(ADC_BASE + ADC_O_OSTAT) = ADC_OSTAT_OV2;
        HWREG(ADC_BASE + ADC_O_USTAT) = ADC_USTAT_UV2;

        //
        // Renable the sequence and return.
        //
        HWREG(ADC_BASE + ADC_O_ACTSS) = ADC_ACTSS_ASEN2;
        return;
    }

    //
    // Read the samples from the ADC FIFO.
    //
    ulIdx = 0;
    while(!(HWREG(ADC_BASE + ADC_O_SSFSTAT2) & ADC_SSFSTAT2_EMPTY) &&
          (ulIdx < 3))
    {
        //
        // Read the next sample.
        //
        pusADCData[ulIdx] = HWREG(ADC_BASE + ADC_O_SSFIFO2);

        //
        // Increment the count of samples read.
        //
        ulIdx++;
    }

    //
    // See if three samples were read.
    //
    if(ulIdx != 3)
    {
        //
        // Since there were not precisely three samples in the FIFO, it is not
        // known what analog signal is represented by each sample.  Therefore,
        // return without doing any processing on these samples.
        //
        return;
    }

    //
    // Expand the Linear Hall Sensor data to full 10-bit range.
    // 
    for(ulIdx = 0, ulLinearCount++; ulIdx < 3; ulIdx++)
    {
        unsigned short usRange, usMin;

        //
        // Adjust the min/max values inward to keep the values dynamic.
        //
        if(((ulLinearCount % 2000) == 0) && MainIsRunning())
        {
            g_pusLinearHallMax[ulIdx]--;
            g_pusLinearHallMin[ulIdx]++;
        }

        //
        // Find max/min hall sensor values.
        //
        if(pusADCData[ulIdx] > g_pusLinearHallMax[ulIdx])
        {
            g_pusLinearHallMax[ulIdx] = pusADCData[ulIdx];
        }
        if(pusADCData[ulIdx] < g_pusLinearHallMin[ulIdx])
        {
            g_pusLinearHallMin[ulIdx] = pusADCData[ulIdx];
        }

        //
        // Adjust the ADC values to full-scale 10-bit ADC values.
        //
        usRange = g_pusLinearHallMax[ulIdx];
        usRange -= g_pusLinearHallMin[ulIdx];
        if(!usRange)
        {
            usRange++;
        }
        usMin = g_pusLinearHallMin[ulIdx];
        g_pusLinearHallSensor[ulIdx] = (unsigned short)
            (((unsigned long)(pusADCData[ulIdx] - usMin) * 1023) / usRange);
    }
    
    //
    // Convert Linear Hall data to a Hall Sensor Value (A)
    //
    if(g_pusLinearHallSensor[0] > 614)
    {
        g_ulLinearHallValue |= 0x01;
    }
    else if (g_pusLinearHallSensor[0] < 410)
    {
        g_ulLinearHallValue &= ~0x01;
    }

    //
    // Convert Linear Hall data to a Hall Sensor Value (B)
    //
    if(g_pusLinearHallSensor[1] > 614)
    {
        g_ulLinearHallValue |= 0x02;
    }
    else if (g_pusLinearHallSensor[1] < 410)
    {
        g_ulLinearHallValue &= ~0x02;
    }

    //
    // Convert Linear Hall data to a Hall Sensor Value (C)
    //
    if(g_pusLinearHallSensor[2] > 614)
    {
        g_ulLinearHallValue |= 0x04;
    }
    else if (g_pusLinearHallSensor[2] < 410)
    {
        g_ulLinearHallValue &= ~0x04;
    }

    //
    // Compute the new speed from the time between edges if the Hall
    // state value has changed and the motor has completed one electrical
    // revolution.
    //
    if((g_ulLinearHallValue != g_ulLinearLastHall) &&
       (g_ulLinearHallValue == 5))
    {
        //
        // Set the flag to indicate that we have seen an edge.
        // 
        HWREGBITW(&g_ulADCFlags, FLAG_EDGE_BIT) = 1;

        //
        // See if this edge should be skipped.
        //
        if(HWREGBITW(&g_ulADCFlags, FLAG_SKIP_LINEAR_BIT))
        {
            //
            // This edge should be skipped, but an edge time now exists so the
            // next edge should not be skipped.
            //
            HWREGBITW(&g_ulADCFlags, FLAG_SKIP_LINEAR_BIT) = 0;

            //
            // Save the time of the current edge.
            //
            g_ulLinearSpeedPrevious = ulNewTime;

            //
            // Save the current linear hall value.
            //
            g_ulLinearLastHall = g_ulLinearHallValue;

            //
            // There is nothing further to be done.
            //
            return;
        }
            
        //
        // Compute the time between this edge and the previous edge.
        //
        ulTime = ulNewTime - g_ulLinearSpeedPrevious;

        //
        // Save the time of the current edge.
        //
        g_ulLinearSpeedPrevious = ulNewTime;

        //
        // Compute the new speed from the time between edges, running it
        // through a low pass filter with a coefficient of .875.
        //
        g_ulLinearRotorSpeed = ((g_ulLinearRotorSpeed * 7) +
            (((unsigned long)SYSTEM_CLOCK * (unsigned long)60) /
            (ulTime * (g_sParameters.ucNumPoles + 1)))) / 8;
    }

    //
    // Save the current linear Hall state value.
    //
    g_ulLinearLastHall = g_ulLinearHallValue;
}

//*****************************************************************************
//
//! Handles the ADC sample sequence three interrupt.
//!
//! This function is called when sample sequence three asserts an interrupt.
//! It handles clearing the interrupt, processing any sequence overflow
//! conditions, and processing the new ADC data in the FIFO.  This sequence is
//! used to process the Back EMF input data.  The Back EMF data is monitored
//! to detect crossing of the 0.5 DC Bus Voltage point.  When this occurs, an
//! equivalent "digital" Hall state value is generated.  Speed is also
//! calculated when a complete electrical revolution has occured.
//!
//! \return None.
//
//*****************************************************************************
void
ADC3IntHandler(void)
{
    unsigned short usADCData;
    volatile unsigned long ulTemp;
    static unsigned long ulLastPWMEnable = 0;
    unsigned long ulPWMEnable;
    unsigned long ulNewTime, ulTime;

    //
    // Clear the ADC interrupt.
    //
    HWREG(ADC_BASE + ADC_O_ISC) = ADC_ISC_IN3;

    //
    // Reset the sequence if an overflow has occurred.
    //
    if(HWREG(ADC_BASE + ADC_O_OSTAT) & ADC_OSTAT_OV3)
    {
        //
        // Disable the sequence.
        //
        HWREG(ADC_BASE + ADC_O_ACTSS) &= ~ADC_ACTSS_ASEN3;

        //
        // Drain the Sequence FIFO.
        //
        while(!(HWREG(ADC_BASE + ADC_O_SSFSTAT3) & ADC_SSFSTAT3_EMPTY))
        {
            //
            // Read the next sample.
            //
            ulTemp = HWREG(ADC_BASE + ADC_O_SSFIFO3);
        }

        //
        // Clear any overflow/underflow conditions that might exist.
        //
        HWREG(ADC_BASE + ADC_O_OSTAT) = ADC_OSTAT_OV3;
        HWREG(ADC_BASE + ADC_O_USTAT) = ADC_USTAT_UV3;

        //
        // Renable the sequence and return.
        //
        HWREG(ADC_BASE + ADC_O_ACTSS) = ADC_ACTSS_ASEN3;
        return;
    }

    //
    // Reset/Reconfigure the sequence if a change in PWM output drive
    // state is detected.
    //
    ulPWMEnable = HWREG(PWM_BASE + PWM_O_ENABLE) |
            HWREG(PWM_BASE + PWM_O_INVERT);
    if(ulPWMEnable != ulLastPWMEnable)
    {
        unsigned long ulBEMF;

        //
        // Disable the sequence.
        //
        HWREG(ADC_BASE + ADC_O_ACTSS) &= ~ADC_ACTSS_ASEN3;

        //
        // Drain the Sequence FIFO.
        //
        while(!(HWREG(ADC_BASE + ADC_O_SSFSTAT3) & ADC_SSFSTAT3_EMPTY))
        {
            //
            // Read the next sample.
            //
            usADCData = HWREG(ADC_BASE + ADC_O_SSFIFO3);
        }

        //
        // Clear any overflow/underflow conditions that might exist.
        //
        HWREG(ADC_BASE + ADC_O_OSTAT) = ADC_OSTAT_OV3;
        HWREG(ADC_BASE + ADC_O_USTAT) = ADC_USTAT_UV3;

        //
        // Save the PWM output state.
        //
        ulLastPWMEnable = ulPWMEnable;

        //
        // Based on the new PWM output state, determine which Back EMF
        // detection state we should be in.
        //
        //           Forward            Reverse
        // B+ C- ==> Rising  A (0) ==> Falling B (3)
        // B- C+ ==> Falling A (1) ==> Rising  B (2)
        // A- C+ ==> Rising  B (2) ==> Falling C (5)
        // A+ C- ==> Falling B (3) ==> Rising  C (4)
        // A+ B- ==> Rising  C (4) ==> Falling A (1)
        // A- B+ ==> Falling C (5) ==> Rising  A (0)
        //
        if((ulPWMEnable & 0x03) == 0)
        {
            ulBEMF = PIN_VBEMFA;
            g_ucBEMFState = ((ulPWMEnable & 0x0C) == 0x08) ? 1 : 0 ;
            g_bBEMFEdge = false;
        }
        else if((ulPWMEnable & 0x0C) == 0)
        {
            ulBEMF = PIN_VBEMFB;
            g_ucBEMFState = ((ulPWMEnable & 0x03) == 0x02) ? 2 : 3 ;
            g_bBEMFEdge = false;
        }
        else
        {
            ulBEMF = PIN_VBEMFC;
            g_ucBEMFState = ((ulPWMEnable & 0x03) == 0x02) ? 5 : 4 ;
            g_bBEMFEdge = false;
        }
        if(MainIsReverse())
        {
            static const unsigned char ucRevTable[] = {3, 2, 5, 4, 1, 0};
            g_ucBEMFState = ucRevTable[g_ucBEMFState];
        }
        
        //
        // Reprogram the sequence to read Back EMF voltage first (with the
        // PWM Pulse Active) and 5 Phase current readings to follow.
        //
        ADCSequenceStepConfigure(ADC_BASE, 3, 0,
                                 ADC_CTL_END | ADC_CTL_IE | ulBEMF);

        //
        // Enable the sequence and return.
        //
        HWREG(ADC_BASE + ADC_O_ACTSS) |= ADC_ACTSS_ASEN3;
        return;
    }

    //
    // Read the sample from the ADC FIFO.
    //
    usADCData = HWREG(ADC_BASE + ADC_O_SSFIFO3);

    //
    // If motor drive is in the stopped state (i.e. not running), then return.
    //
    if(!MainIsRunning())
    {
        return;
    }

    //
    // If Back EMF trigger point has been found, return.
    //
    if(g_bBEMFEdge)
    {
        return;
    }

    //
    // Check for Back EMF Trigger Point.
    //
    ulNewTime = UIGetTicks();
    switch(g_ucBEMFState)
    {
        //
        //           Forward            Reverse
        // B+ C- ==> Rising  A (0) ==> Falling B (3)
        // B- C+ ==> Falling A (1) ==> Rising  B (2)
        // A- C+ ==> Rising  B (2) ==> Falling C (5)
        // A+ C- ==> Falling B (3) ==> Rising  C (4)
        // A+ B- ==> Rising  C (4) ==> Falling A (1)
        // A- B+ ==> Falling C (5) ==> Rising  A (0)
        // 
        case 0:
            if(usADCData < (g_pusFilteredData1[1] / 2))
            {

⌨️ 快捷键说明

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