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

📄 adc_ctrl.c

📁 Luminary Micro BLDC motor control software
💻 C
📖 第 1 页 / 共 4 页
字号:
//*****************************************************************************
//
// adc_ctrl.c - ADC control routines.
//
// Copyright (c) 2007-2008 Luminary Micro, Inc.  All rights reserved.
// 
// Software License Agreement
// 
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
// 
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws.  All rights are reserved.  You may not combine
// this software with "viral" open-source software in order to form a larger
// program.  Any use in violation of the foregoing restrictions may subject
// the user to criminal sanctions under applicable laws, as well as to civil
// liability for the breach of the terms and conditions of this license.
// 
// THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
// 
// This is part of revision 716 of the BLDC motor application.
//
//*****************************************************************************

#include "../../DriverLib/hw_memmap.h"
#include "../../DriverLib/hw_types.h"
#include "../../DriverLib/hw_adc.h"
#include "../../DriverLib/hw_ints.h"
#include "../../DriverLib/hw_pwm.h"
#include "../../DriverLib/src/adc.h"
#include "../../DriverLib/src/interrupt.h"
#include "../../DriverLib/src/sysctl.h"
#include "../../DriverLib/src/timer.h"
#include "adc_ctrl.h"
#include "main.h"
#include "pins.h"
#include "ui.h"
#include "pwm_ctrl.h"

//*****************************************************************************
//
//! \page adc_ctrl_intro Introduction
//!
//! Depending on the mode of operation, the ADC is used to monitor the motor
//! phase current, motor phase back EMF voltage, linear hall sensor voltage,
//! DC bus voltage, analog input voltage, and ambient temperature of the
//! microcontroller.  Each of these values is sampled every PWM period based
//! on a trigger from the PWM module.  Multiple ADC sequences are used to
//! allow optimization of CPU usage.
//!
//! Readings from the ADC may be passed through a single-pole IIR low pass
//! filter.  This helps to reduce the effects of high frequency noise (such as
//! switching noise) on the sampled data.  A coefficient of 0.75 is used to
//! simplify the integer math (requiring only a multiplication by 3, an
//! addition, and a division by four).
//!
//! The individual motor phase RMS currents, motor RMS current, DC bus voltage,
//! and ambient temperature are used outside this module.
//!
//! The code for handling the ADC is contained in <tt>adc_ctrl.c</tt>, with
//! <tt>adc_ctrl.h</tt> containing the definitions for the variables and
//! functions exported to the remainder of the application.
//
//*****************************************************************************

//*****************************************************************************
//
//! \defgroup adc_ctrl_api Definitions
//! @{
//
//*****************************************************************************

//*****************************************************************************
//
//! The bit number of the flag in #g_ulADCFlags that indicates that the
//! next edge should be ignored by the Back EMF speed calculation code.  This
//! is used at startup since there is no previous edge time to be used to
//! calculate the time between edges.
//
//*****************************************************************************
#define FLAG_SKIP_BIT           0

//*****************************************************************************
//
//! The bit number of the flag in #g_ulADCFlags that indicates that an edge
//! has been seen (in the speed processing code).  This will prevent the
//! #ADCTickHandler from resetting the rotor speed.
//
//*****************************************************************************
#define FLAG_EDGE_BIT           1

//*****************************************************************************
//
//! The bit number of the flag in #g_ulADCFlags that indicates that the
//! next edge should be ignored by the Linear Hall speed calculation code.
//! This is used at startup since there is no previous edge time to be used to
//! calculate the time between edges.
//
//*****************************************************************************
#define FLAG_SKIP_LINEAR_BIT    2

//*****************************************************************************
//
//! A set of flags that provide status and control of the ADC Control
//! module.
//
//*****************************************************************************
static unsigned long g_ulADCFlags = 
    ((1 << FLAG_SKIP_BIT) |
     (1 << FLAG_SKIP_LINEAR_BIT));

//*****************************************************************************
//
//! Arrays containing the raw low pass filtered ADC readings.  These are
//! maintained in a raw form since they are required as an input to the next
//! iteration of the IIR low pass filter.  There is at most one array for each
//! ADC sequence in use.
//
//*****************************************************************************
static unsigned short g_pusFilteredData0[3];
static unsigned short g_pusFilteredData1[3];

//*****************************************************************************
//
//! The current passing through the three phases of the motor, specified in
//! milliamperes as a signed value.
//
//*****************************************************************************
short g_psPhaseCurrent[3];

//*****************************************************************************
//
//! An array containing the maximum phase currents seen during the last half
//! cycle of each phase.  This is used to perform a peak detect on the phase
//! currents.
//
//*****************************************************************************
static unsigned short g_pusPhaseMax[3];

//*****************************************************************************
//
//! The index for the phase current being processed in the ADC sequence
//! handler.
//
//*****************************************************************************
static unsigned char g_ucPhaseCurrentIndex = 0;

//*****************************************************************************
//
//! The total current passing through the motor, specified in milliamperes as
//! a signed value.
//
//*****************************************************************************
short g_sMotorCurrent;

//*****************************************************************************
//
//! The DC bus voltage, specified in millivolts.
//
//*****************************************************************************
unsigned long g_ulBusVoltage;

//*****************************************************************************
//
//! The state of the Back EMF processing state machine.
//
//*****************************************************************************
static unsigned char g_ucBEMFState = 0;

//*****************************************************************************
//
//! A flag to indicate whether the Back EMF trigger point has been found.
//
//*****************************************************************************
static tBoolean g_bBEMFEdge = false;

//*****************************************************************************
//
//! The time at which the last Back EMF speed edge occurred.
//
//*****************************************************************************
static unsigned long g_ulBEMFSpeedPrevious = 0;

//*****************************************************************************
//
//! The time at which the last Back EMF edge occurred.
//
//*****************************************************************************
static unsigned long g_ulBEMFEdgePrevious = 0;

//*****************************************************************************
//
//! The rotor speed as measured by the BEMF processing code.
//
//*****************************************************************************
unsigned long g_ulBEMFRotorSpeed = 0;

//*****************************************************************************
//
//! The next Back EMF Hall state value.
//
//*****************************************************************************
static unsigned long g_ulBEMFNextHall = 0;

//*****************************************************************************
//
//! The Hall state value as determined by the Back EMF processing code.
//
//*****************************************************************************
unsigned long g_ulBEMFHallValue = 0;

//*****************************************************************************
//
//! The Analog Input voltage, specified in millivolts.
//
//*****************************************************************************
unsigned short g_usAnalogInputVoltage;

//*****************************************************************************
//
//! The ambient case temperature of the microcontroller, specified in degrees
//! Celsius.
//
//*****************************************************************************
unsigned char g_ucAmbientTemp;

//*****************************************************************************
//
//! The Linear Hall Sensor ADC values (scaled).
//
//*****************************************************************************
static unsigned short g_pusLinearHallSensor[3];

//*****************************************************************************
//
//! The Linear Hall Sensor ADC Maximum Value.
//
//*****************************************************************************
static unsigned short g_pusLinearHallMax[3] = {1023, 1023, 1023};

//*****************************************************************************
//
//! The Linear Hall Sensor ADC Minimum Value.
//
//*****************************************************************************
static unsigned short g_pusLinearHallMin[3] = {0, 0, 0};

//*****************************************************************************
//
//! The Hall state value as determined by the linear Hall sensor processing
//! code.
//
//*****************************************************************************
unsigned long g_ulLinearHallValue = 0;

//*****************************************************************************
//
//! The time at which the last linear Hall sensor speed edge occurred.
//
//*****************************************************************************
static unsigned long g_ulLinearSpeedPrevious = 0;

//*****************************************************************************
//
//! The rotor speed as measured by the linear Hall sensor processing code.
//
//*****************************************************************************
unsigned long g_ulLinearRotorSpeed = 0;

//*****************************************************************************
//
//! The previous Hall state value as determined by the linear Hall sensor
//! processing code.
//
//*****************************************************************************
static unsigned long g_ulLinearLastHall = 0;

//*****************************************************************************
//
//! The angle of the motor drive on the previous ADC interrupt.
//
//*****************************************************************************
static unsigned long g_ulPrevAngle;

//*****************************************************************************
//
//! Handles the Back EMF Timer Interrupt.
//!
//! This function is called when the Back EMF timer expires.  This code will
//! set the Back EMF Hall state value to the next value, as determined by
//! the Back EMF processing code.  The actual commutation of the motor takes
//! place in the main module.
//!
//! \return None.
//
//*****************************************************************************
void
Timer0AIntHandler(void)
{
    //
    // Clear the Timer interrupt.
    //
    TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

    //
    // Set the new Hall Sensor value.
    //
    g_ulBEMFHallValue = g_ulBEMFNextHall;
}

//*****************************************************************************
//
//! Handles the ADC sample sequence zero interrupt for trapezoid mode.
//!
//! This functions processes the ADC sequence zero for trapezoid mode.  In
//! this handler, a single phase of current is processed from the sequence.
//! To account for noise, especially during short PWM duty cycles, five
//! readings are taken, the high and low values are discarded, and the
//! remaining three values are averaged.  The reported motor current value
//! is averaged over the entire time the phase is active.  When the PWM
//! drive changes, the sequence is reset and measurements are started for
//! the next phase.
//!
//! \return None.
//
//*****************************************************************************
static void
ADC0IntHandlerTrapezoid(void)
{
    unsigned long ulIdx;
    unsigned short pusADCData[6];
    long lTemp = 0;
    static unsigned char ucLastPhaseIndex = 4;
    static unsigned long ulPhaseSum = 0;
    static unsigned long ulPhaseCount = 0;
    static unsigned long ulLastPWMEnable = 0;
    unsigned long ulPWMEnable;
    unsigned short usMin, usMax, usSum;

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

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

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

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

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

        //
        // If the low side of Phase A is active, enable current readings
        // on the Phase A ADC current input signal.
        //
        if(ulPWMEnable & 0x2)
        {
            ulIPhase = PIN_IPHASEA;
            g_ucPhaseCurrentIndex = 0;
        }

        //
        // If the low side of Phase B is active, enable current readings
        // on the Phase B ADC current input signal.
        //
        else if(ulPWMEnable & 0x8)
        {
            ulIPhase = PIN_IPHASEB;
            g_ucPhaseCurrentIndex = 1;
        }

        //
        // Here, assume Phase C is active, enable current readings
        // on the Phase C ADC current input signal.
        //
        else
        {
            ulIPhase = PIN_IPHASEC;
            g_ucPhaseCurrentIndex = 2;
        }
        
        //
        // Reprogram the sequence to read Back EMF voltage first (with the
        // PWM Pulse Active) and 5 Phase current readings to follow.
        //
        ADCSequenceStepConfigure(ADC_BASE, 0, 0, ulIPhase);
        ADCSequenceStepConfigure(ADC_BASE, 0, 1, ulIPhase);
        ADCSequenceStepConfigure(ADC_BASE, 0, 2, ulIPhase);
        ADCSequenceStepConfigure(ADC_BASE, 0, 3, ulIPhase);
        ADCSequenceStepConfigure(ADC_BASE, 0, 4,
                                 ADC_CTL_END | ADC_CTL_IE | ulIPhase);

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

    //
    // Read the samples from the ADC FIFO.
    //
    ulIdx = 0;
    while(!(HWREG(ADC_BASE + ADC_O_SSFSTAT0) & ADC_SSFSTAT0_EMPTY) &&
          (ulIdx < 5))
    {
        //
        // Read the next sample.
        //

⌨️ 快捷键说明

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