This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Reseting Timer Count up to 0

Other Parts Discussed in Thread: TM4C123GH6PM

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

}

  • Hi Timothy,

    The problem is that you are just changing the value the timer starts counting from, not exactly the timer value.
    I don't really know how to set the timer value with the API but you can instead use direct register access. The register GPTMTAV is the one that holds the value for timer A.

    Maybe you should instead consider to use a timer in capture mode. It would be more precise and would avoid this problem
  • Afonso,

    I read the documentation for TimerConfigure about the Capture Time configuration but I couldn't get my head around how it works or what functions to call in order to start this timer, read the timer value, then reset the timer. Could you show me an example or point me to some documentation that is a bit easier to understand. I'm using TivaWare Peripheral Library.

    Respectfully,

    Tim