📄 adc_ctrl.c
字号:
pusADCData[ulIdx] = HWREG(ADC_BASE + ADC_O_SSFIFO0);
//
// Increment the count of samples read.
//
ulIdx++;
}
//
// See if five samples were read.
//
if(ulIdx != 5)
{
//
// Since there were not precisely five 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;
}
//
// See if the motor drive is running.
//
if(!MainIsRunning())
{
//
// Since the motor drive is not running, there is no current through
// the motor, nor is there any Back EMF voltage.
//
g_psPhaseCurrent[0] = 0;
g_psPhaseCurrent[1] = 0;
g_psPhaseCurrent[2] = 0;
g_sMotorCurrent = 0;
//
// There is nothing further to be done since the motor is not running.
//
return;
}
//
// Get the average Phase Current ADC input value, discarding the high and
// low value.
//
usMin = usMax = usSum = pusADCData[0];
for(ulIdx = 1; ulIdx < 5; ulIdx++)
{
usSum += pusADCData[ulIdx];
if(pusADCData[ulIdx] < usMin)
{
usMin = pusADCData[ulIdx];
}
if(pusADCData[ulIdx] > usMax)
{
usMax = pusADCData[ulIdx];
}
}
usSum -= usMin;
usSum -= usMax;
usSum /= 3;
//
// Calculate Phase current.
//
lTemp = (usSum * 43032) / 1000;
lTemp = (lTemp - 16580);
lTemp = (lTemp * g_ulTrapDutyCycle) / 100;
//
// Run it through an IIR low pass filter, with coefficient of 0.75.
//
g_psPhaseCurrent[g_ucPhaseCurrentIndex] =
(short)((((long)g_psPhaseCurrent[g_ucPhaseCurrentIndex] * 3) + lTemp)
/ 4);
//
// Accumulate the phase current sum.
//
ulPhaseSum += usSum;
ulPhaseCount++;
//
// If we have changed phases, calculate the phase current average.
//
if(g_ucPhaseCurrentIndex != ucLastPhaseIndex)
{
if(ucLastPhaseIndex <= 2)
{
lTemp = (((ulPhaseSum / ulPhaseCount) * 43032) / 1000);
lTemp = (lTemp - 16580);
lTemp = (lTemp * g_ulTrapDutyCycle) / 100;
g_sMotorCurrent = ((g_sMotorCurrent * 3) + lTemp) / 4;
ulPhaseSum = 0;
ulPhaseCount = 0;
}
ucLastPhaseIndex = g_ucPhaseCurrentIndex;
}
}
//*****************************************************************************
//
//! Handles the ADC sample sequence zero interrupt for sine mode.
//!
//! This functions processes the ADC sequence zero for sine mode. In this
//! handler, all three phases of current are processed from the sequence.
//! The peak value is detected for a complete electrical revolution of the
//! motor. The phase current is converted to an RMS value, and the motor
//! current is taken as the average of all three phases.
//!
//! \return None.
//
//*****************************************************************************
static void
ADC0IntHandlerSine(void)
{
unsigned long ulIdx;
unsigned short pusADCData[8];
long lTemp;
//
// Read the samples from the ADC FIFO.
//
ulIdx = 0;
while(!(HWREG(ADC_BASE + ADC_O_SSFSTAT0) & ADC_SSFSTAT0_EMPTY) &&
(ulIdx < 3))
{
//
// Read the next sample.
//
pusADCData[ulIdx] = HWREG(ADC_BASE + ADC_O_SSFIFO0);
//
// 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;
}
//
// Filter the new samples.
//
for(ulIdx = 0; ulIdx < 3; ulIdx++)
{
//
// Pass the new data sample through a single pole IIR low pass filter
// with a coefficient of 0.75.
//
g_pusFilteredData0[ulIdx] = (((g_pusFilteredData0[ulIdx] * 3) +
pusADCData[ulIdx]) / 4);
}
//
// See if the motor drive is running.
//
if(!MainIsRunning())
{
//
// Since the motor drive is not running, there is no current through
// the motor, nor is there any Back EMF voltage.
//
g_psPhaseCurrent[0] = 0;
g_psPhaseCurrent[1] = 0;
g_psPhaseCurrent[2] = 0;
g_sMotorCurrent = 0;
//
// There is nothing further to be done since the motor is not running.
//
return;
}
//
// See if the drive angle just crossed zero in either direction.
//
if(((g_ulAngle > 0xf0000000) && (g_ulPrevAngle < 0x10000000)) ||
((g_ulAngle < 0x10000000) && (g_ulPrevAngle > 0xf0000000)))
{
//
// Loop through the three phases of the motor drive.
//
for(ulIdx = 0; ulIdx < 3; ulIdx++)
{
//
// Convert the maximum reading detected during the last cycle into
// amperes. This is the peak current, which is then divided by
// 1.4 to get the RMS current.
//
lTemp = ((long)g_pusPhaseMax[ulIdx] * 43032) / 1000;
lTemp = lTemp - 16580;
lTemp = lTemp * 10 / 14;
g_psPhaseCurrent[ulIdx] = lTemp;
//
// Reset the maximum phase current seen to zero to prepare for the
// next cycle.
//
g_pusPhaseMax[ulIdx] = 0;
}
//
// Average the RMS current of the three phases to get the RMS motor
// current.
//
lTemp = (long)g_psPhaseCurrent[0];
lTemp += (long)g_psPhaseCurrent[1];
lTemp += (long)g_psPhaseCurrent[2];
g_sMotorCurrent = (short)(lTemp / 3);
}
//
// Loop through the three phases of the motor drive.
//
for(ulIdx = 0; ulIdx < 3; ulIdx++)
{
//
// See if this ADC reading is larger than any previous ADC reading.
//
if(g_pusFilteredData0[ulIdx] > g_pusPhaseMax[ulIdx])
{
//
// Save this ADC reading as the maximum.
//
g_pusPhaseMax[ulIdx] = g_pusFilteredData0[ulIdx];
}
}
//
// Save the current motor drive angle for the next set of samples.
//
g_ulPrevAngle = g_ulAngle;
}
//*****************************************************************************
//
//! Handles the ADC sample sequence zero interrupt.
//!
//! This function is called when sample sequence zero asserts an interrupt. It
//! handles clearing the interrupt and processing any sequence overflow
//! conditions. Then, depending on the modulation scheme that is active, the
//! appropriate sub-handler is called.
//!
//! \return None.
//
//*****************************************************************************
void
ADC0IntHandler(void)
{
volatile unsigned long ulTemp;
//
// Clear the ADC interrupt.
//
HWREG(ADC_BASE + ADC_O_ISC) = ADC_ISC_IN0;
//
// Reset the sequence if an overflow has occurred.
//
if(HWREG(ADC_BASE + ADC_O_OSTAT) & ADC_OSTAT_OV0)
{
//
// 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.
//
ulTemp = 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;
//
// Renable the sequence and return.
//
HWREG(ADC_BASE + ADC_O_ACTSS) = ADC_ACTSS_ASEN0;
return;
}
//
// Process the phase current, one leg at a time, for trapezoid mode.
//
if(HWREGBITH(&(g_sParameters.usFlags), FLAG_DRIVE_BIT) ==
FLAG_DRIVE_TRAPEZOID)
{
ADC0IntHandlerTrapezoid();
}
//
// Process the phase current as sum of peak phases for sine mode.
//
else if(HWREGBITH(&(g_sParameters.usFlags), FLAG_DRIVE_BIT) ==
FLAG_DRIVE_SINE)
{
ADC0IntHandlerSine();
}
}
//*****************************************************************************
//
//! Handles the ADC sample sequence one interrupt.
//!
//! This function is called when sample sequence one 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 read the DC Bus Voltage, the Analog Input signal, and the
//! temperature.
//!
//! \return None.
//
//*****************************************************************************
void
ADC1IntHandler(void)
{
unsigned long ulIdx;
unsigned short pusADCData[3];
//
// Clear the ADC interrupt.
//
HWREG(ADC_BASE + ADC_O_ISC) = ADC_ISC_IN1;
//
// Reset the sequence if an overflow has occurred.
//
if(HWREG(ADC_BASE + ADC_O_OSTAT) & ADC_OSTAT_OV1)
{
//
// Disable the sequence.
//
HWREG(ADC_BASE + ADC_O_ACTSS) &= ~ADC_ACTSS_ASEN1;
//
// Drain the Sequence FIFO.
//
while(!(HWREG(ADC_BASE + ADC_O_SSFSTAT1) & ADC_SSFSTAT1_EMPTY))
{
//
// Read the next sample.
//
pusADCData[0] = HWREG(ADC_BASE + ADC_O_SSFIFO1);
}
//
// Clear any overflow/underflow conditions that might exist.
//
HWREG(ADC_BASE + ADC_O_OSTAT) = ADC_OSTAT_OV1;
HWREG(ADC_BASE + ADC_O_USTAT) = ADC_USTAT_UV1;
//
// Renable the sequence and return.
//
HWREG(ADC_BASE + ADC_O_ACTSS) = ADC_ACTSS_ASEN1;
return;
}
//
// Read the samples from the ADC FIFO.
//
ulIdx = 0;
while(!(HWREG(ADC_BASE + ADC_O_SSFSTAT1) & ADC_SSFSTAT1_EMPTY) &&
(ulIdx < 3))
{
//
// Read the next sample.
//
pusADCData[ulIdx] = HWREG(ADC_BASE + ADC_O_SSFIFO1);
//
// Increment the count of samples read.
//
ulIdx++;
}
//
// See if three samples were read.
//
if(ulIdx != 3)
{
//
// Since there were not precisely thre 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;
}
//
// Filter the new samples.
//
for(ulIdx = 0; ulIdx < 3; ulIdx++)
{
//
// Pass the new data sample through a single pole IIR low pass filter
// with a coefficient of 0.75.
//
g_pusFilteredData1[ulIdx] = (((g_pusFilteredData1[ulIdx] * 3) +
pusADCData[ulIdx]) / 4);
}
//
// Convert the ADC DC bus reading to millivolts. Each volt at the ADC
// input corresponds to 40 volts of bus voltage.
//
g_ulBusVoltage = ((unsigned long)g_pusFilteredData1[1] * 120000) / 1024;
//
// Convert the ADC junction temperature reading to ambient case temperature
// in Celsius.
//
g_ucAmbientTemp = (59960 - (g_pusFilteredData1[2] * 100)) / 356;
//
// Convert the ADC Analog Input reading to milli-volts. Each volt at the
// ADC input corresponds to ~1.714 volts at the Analog Input.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -