I am trying to set up my TM4C123GH6PM to record the frequency of an incoming square wave signal (from an RPM sensor). In order to do this, I am using Port E Pin 3 as a GPIO with a rising edge interrupt and a Count Up Timer. Unfortunately, when my GPIO interrupt occurs and tries to reset this count up, it never does so. Thus, I report the frequency correct the first time and incorrect every other time.
Is there a better way of doing this? Or how do I reset that count up timer?
#include <stdint.h> #include <stdbool.h> #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "driverlib/gpio.h" #include "driverlib/pin_map.h" #include "driverlib/sysctl.h" #include "driverlib/uart.h" #include "driverlib/interrupt.h" #include "driverlib/rom.h" #include "driverlib/timer.h" // largest 32-bit int #define MAX_32_TIMER_SIZE 4294967295 // Global variable declaration uint8_t bytes_4[4]; // 4 byte buffer for 32bit ints volatile uint32_t timerLoad; // Used to load values into Timer volatile uint32_t freqRPM; // Used to store and calculate current freq/RPM values volatile uint8_t nextSection; // boolean that tells test program to go to next section volatile uint8_t nextDataBundle; // boolean that tells test program to gather/send next data bundle void DebugProgram(void){ int i; // Set timer to 5 seconds timerLoad = (SysCtlClockGet() * 5) - 1; TimerLoadSet(TIMER0_BASE, TIMER_A, timerLoad); timerLoad = (SysCtlClockGet()/10) - 1; TimerLoadSet(TIMER1_BASE, TIMER_A, timerLoad); TimerLoadSet(TIMER2_BASE, TIMER_A, MAX_32_TIMER_SIZE); // Enable timers TimerEnable(TIMER0_BASE, TIMER_A); TimerEnable(TIMER2_BASE, TIMER_A); // Enable GPIO interrupts on Port E pin 3 IntEnable(INT_GPIOE); GPIOIntEnable(GPIO_PORTE_BASE, GPIO_INT_PIN_3); while(!nextSection){ TimerEnable(TIMER1_BASE, TIMER_A); // Frequency bytes_4[0] = (freqRPM >> 24) & 0xFFFF; bytes_4[1] = (freqRPM >> 16) & 0xFFFF; bytes_4[2] = (freqRPM >> 8) & 0xFFFF; bytes_4[3] = freqRPM & 0xFFFF; for(i=0;i<4;i++){ UARTCharPutNonBlocking(UART0_BASE,bytes_4[i]); } // Wait for /100 of a second to finish while(!nextDataBundle){ } nextDataBundle = false; timeMilli++; } // Signal end of test UARTCharPutNonBlocking(UART0_BASE,'!'); freqRPM = 0; nextSection = false; IntDisable(INT_GPIOE); GPIOIntDisable(GPIO_PORTE_BASE, GPIO_INT_PIN_3); } void Config(void){ /* * Note: ROM_* is a way to call a function for the TIVA's onboard ROM instead * of relying on cluttering its flash drive memory with too many functions */ // Sets clock at 50MHz... 400MHz PLL /2 = 200 then div SYSDIV_4 = 50MHz ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // PWM clock set to SysClock / 16 = 3.125MHz ROM_SysCtlPWMClockSet(SYSCTL_PWMDIV_16); // Enable peripherals... ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); // start mid end sections ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1); // sample bundle control (1 per 10 ms) ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2); // RPM value control ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); // Communication with PC ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); // used in RPM interrupt detection ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); // where LED's are // Configure Port F pins to blink blue, green, and red light ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3); // Configure Port E pin 3 to be a rising edge interrupt input // This will be used to detect when the RPM sensor rises high ROM_GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, GPIO_PIN_3); ROM_GPIOIntTypeSet(GPIO_PORTE_BASE, GPIO_PIN_3, GPIO_RISING_EDGE); // Configure UART pins, clock, and set BAUD RATE to 115200 ROM_GPIOPinConfigure(GPIO_PA0_U0RX); ROM_GPIOPinConfigure(GPIO_PA1_U0TX); ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); ROM_UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE)); // Configure Timer which will control the timing of test legs ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_ONE_SHOT); // Configure Timer which will be used to time data transmission ROM_TimerConfigure(TIMER1_BASE, TIMER_CFG_ONE_SHOT); // Configure Timer which will be used to record RPM information ROM_TimerConfigure(TIMER2_BASE, TIMER_CFG_PERIODIC_UP); // Configure Timer Interrupts // Timer handling test sections (start, mid, end) ROM_IntEnable(INT_TIMER0A); ROM_TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); // Timer handling data group timing (100 sps...) ROM_IntEnable(INT_TIMER1A); ROM_TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT); } void Timer0IntHandler(void){ // Clear the timer interrupt TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT); nextSection = true; } void Timer1AIntHandler(void){ // Clear the timer interrupt TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT); nextDataBundle = true; } void RisEdgeIntHandler(void){ // Clear the Rising Edge interrupt GPIOIntClear(GPIO_PORTE_BASE, GPIO_INT_PIN_3); freqRPM = TimerValueGet(TIMER2_BASE, TIMER_A); TimerDisable(TIMER2_BASE, TIMER_A); TimerLoadSet(TIMER2_BASE, TIMER_A, MAX_32_TIMER_SIZE); TimerEnable(TIMER2_BASE, TIMER_A); if(freqRPM == 0){ freqRPM = 1; } // Flash light GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_2); SysCtlDelay(SysCtlClockGet() / (2000 * 3)); // ~ .5msec GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0); } int main(void) { uint8_t i; uint8_t ui8LED = 2; char optionInput; nextSection = false; nextDataBundle = false; timerLoad = 1; freqRPM = 0; Config(); TimerLoadSet(TIMER0_BASE, TIMER_A, timerLoad); TimerLoadSet(TIMER1_BASE, TIMER_A, timerLoad); TimerLoadSet(TIMER2_BASE, TIMER_A, timerLoad); // Enable all Interrupts IntMasterEnable(); DebugProgram(); while(1){} }