Other Parts Discussed in Thread: TM4C123AH6PM,
Some time ago I made this post:
https://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/607014
Which was essentially never answered.
I have a problem where the QEI index interrupt is never generated, i.e., QEIRIS.INTINDEX never becomes 1.
This is the stripped-down code to initialize QEI and service the interrupt:
void IsrQei0Handler(void) { uint32_t Status; Status = MAP_QEIIntStatus(QEI0_BASE, true); MAP_QEIIntClear(QEI0_BASE, Status); if (Status & QEI_INTERROR) { // Handle QEI error // ... } if (Status & QEI_INTINDEX) { // Handle index pulse // ---> THIS CONDITION NEVER TRIGGERS <--- } if (Status & QEI_INTDIR) { // Handle direction change // ... } } bool InitQei(void) { if (!MAP_SysCtlPeripheralPresent(SYSCTL_PERIPH_QEI0)) return false; // Reset and enable peripheral MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_QEI0); MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_QEI0); MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI0); while (MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_QEI0) != true) { // Wait for peripheral to activate } // Configure GPIO pins MAP_GPIOPinConfigure(GPIO_PL1_PHA0); MAP_GPIOPinConfigure(GPIO_PL2_PHB0); MAP_GPIOPinConfigure(GPIO_PL3_IDX0); MAP_GPIOPinTypeQEI(GPIO_PORTL_BASE, GPIO_PIN_1); MAP_GPIOPinTypeQEI(GPIO_PORTL_BASE, GPIO_PIN_2); MAP_GPIOPinTypeQEI(GPIO_PORTL_BASE, GPIO_PIN_3); // Configure QEI peripheral MAP_QEIConfigure(QEI0_BASE, QEI_CONFIG_CAPTURE_A_B | QEI_CONFIG_NO_RESET | QEI_CONFIG_QUADRATURE | QEI_CONFIG_NO_SWAP, 0xffffffff); MAP_QEIPositionSet(QEI0_BASE, 0); MAP_QEIVelocityConfigure(QEI0_BASE, QEI_VELDIV_1, Global.SysClockFreqHz / 100); MAP_QEIVelocityEnable(QEI0_BASE); MAP_QEIEnable(QEI0_BASE); MAP_QEIIntEnable(QEI0_BASE, (QEI_INTERROR | QEI_INTINDEX | QEI_INTDIR)); MAP_IntPrioritySet(INT_QEI0, 0x20); MAP_IntEnable(INT_QEI0); return true; }
The condition that does not trigger is Status == QEI_INTINDEX, as marked in a comment.
I have verified that our quadrature encoders are indeed producing an index pulse as expected, and that the signal is routed to (and reaches) the correct MCU pin.
So I tested another way:
void IntGpioPortLHandler(void) { uint32_t Status; Status = GPIOIntStatus(GPIO_PORTL_BASE, true); GPIOIntClear(GPIO_PORTL_BASE, Status); if (Status == GPIO_INT_PIN_3) { // This condition does trigger // ... } } bool InitQei(void) { if (!MAP_SysCtlPeripheralPresent(SYSCTL_PERIPH_QEI0)) return false; // Reset and enable peripheral MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_QEI0); MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_QEI0); MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI0); while (MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_QEI0) != true) { // Wait for peripheral to activate } // Configure GPIO pins MAP_GPIOPinConfigure(GPIO_PL1_PHA0); MAP_GPIOPinConfigure(GPIO_PL2_PHB0); MAP_GPIOPinTypeQEI(GPIO_PORTL_BASE, GPIO_PIN_1); MAP_GPIOPinTypeQEI(GPIO_PORTL_BASE, GPIO_PIN_2); // Configure QEI peripheral MAP_QEIConfigure(QEI0_BASE, QEI_CONFIG_CAPTURE_A_B | QEI_CONFIG_NO_RESET | QEI_CONFIG_QUADRATURE | QEI_CONFIG_NO_SWAP, 0xffffffff); MAP_QEIPositionSet(QEI0_BASE, 0); MAP_QEIVelocityConfigure(QEI0_BASE, QEI_VELDIV_1, Global.SysClockFreqHz / 100); MAP_QEIVelocityEnable(QEI0_BASE); MAP_QEIEnable(QEI0_BASE); MAP_QEIIntEnable(QEI0_BASE, (QEI_INTERROR | QEI_INTDIR)); MAP_IntPrioritySet(INT_QEI0, 0x20); MAP_IntEnable(INT_QEI0); // Index pin interrupt MAP_GPIOIntClear(GPIO_PORTL_BASE, GPIO_INT_PIN_3); MAP_GPIOPinTypeGPIOInput(GPIO_PORTL_BASE, GPIO_PIN_3); MAP_GPIOIntTypeSet(GPIO_PORTL_BASE, GPIO_PIN_3, GPIO_RISING_EDGE); MAP_GPIOIntEnable(GPIO_PORTL_BASE, GPIO_INT_PIN_3); MAP_IntPrioritySet(INT_GPIOL, 0x20); MAP_IntEnable(INT_GPIOL); return true; }
This second code initializes the QEI without the INDEX pin, then initializes the INDEX pin as a GPIO with interrupt on rising edge.
In this code, the GPIO interrupt does trigger when the quadrature encoder passes through the INDEX pulse.
Why does the QEI INDEX interrupt never trigger?