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){}
}