📄 speed_sense.c
字号:
// 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 + -