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.

Resetting Timer only works for some time



Hi,

I'm trying to interface a keypad that, when a button is pressed, starts sending a corresponding bitsequence. I've written an interrupthandler that detects the falling edges and counts for 9 interrupts, then it will reset the counter and start a timer. This timer has to be resetted and started over again if an interrupt occurs within the timercycle. This has been done because I only want to receive the 'number' (first 9 interrupts) only once.

Now when I press the button with a corresponding number, I receive the first 9 interrupts and the timer is started. When I keep the button pressed, the timer is resetted several times but then it spits out a number again? Could this be due to a Watchdog Timer? I see in CCS that a Watchdog Timer is Enabled when I a start the code?

My code:

#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "inc/lm4f120h5qr.h"
#include "driverlib/fpu.h"
#include "driverlib/pin_map.h"
#include "driverlib/timer.h"
#include "utils/uartstdio.h"
#include "utils/cmdline.h"

int i = 0;
int j = 0;
int k = 0;
int l = 0;
int GPIOarrays[];
int TimerFlag = 0;

int main(void)
{
    unsigned long ulPeriod;
//Clock & Ports
SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN); //zet kloksnelheid op 40mhz
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

//LEDs
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);

//Interrupt
GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_4);
IntPrioritySet(INT_GPIOF, GPIO_PIN_4);
GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_FALLING_EDGE);
GPIOPinIntEnable(GPIO_PORTF_BASE, GPIO_PIN_4);
IntEnable(INT_GPIOF);

//Set LEDs off
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0x0F);

//Timer
TimerConfigure(TIMER0_BASE, TIMER_CFG_A_ONE_SHOT);
ulPeriod = (SysCtlClockGet()/2);
TimerLoadSet(TIMER0_BASE, TIMER_A, ulPeriod -1);

//UART
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
UARTStdioInit(0);
UARTprintf("UART Shoutbox:");
UARTprintf("\n");
IntMasterEnable();
while(1){}
}
void Timer0IntHandler(void){
    TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    TimerFlag = 0;
}
void TimerDelay(void){
    TimerFlag = 1;
    TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    IntEnable(INT_TIMER0A);
    TimerEnable(TIMER0_BASE, TIMER_A);
    IntMasterEnable();
}
void Counter(void){
    if(i == 8){
        if(TimerFlag == 0){
            for(j=1; j<=i; j++){
                UARTprintf("%i", GPIOarrays[j]);
            }
            UARTprintf("\n");
            TimerDelay();
        }
        i = 0;
    }else{
        i++;
    }
}
void PortFIntHandler(void){
    SysCtlDelay(40000);
    Counter();
    if(TimerFlag == 1){
        TimerDelay();
    }else{
        if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_4)){
            GPIOarrays[i] = 1;
        }else{
            GPIOarrays[i] = 0;
        }
    }
    GPIOPinIntClear(GPIO_PORTF_BASE, GPIO_PIN_4);
}

The signal I'm receiving:

The UART data I'm getting (have set a symbol '-' to show the timer):

Although I keep the button pressed, it does keep sending the number instead of resetting and restarting the timer!
I've changed prolonged the timer up to a second without change so I wonder if this could be something else that I'm not seeing? (Watchdog Timer or so..?)

Kind regards,

Bart

  • When you receive a character, you check to see if the timer has run down.  If it has, you print the character and reset the timer.  But you don't reset the timer if you don't print the character, so after the timer times out, you will receive the character again.

    You need to change your code slightly:

    Bart Remans said:
    void Counter(void){
        if(i == 8){
            if(TimerFlag == 0){
                for(j=1; j<=i; j++){
                    UARTprintf("%i", GPIOarrays[j]);
                }
                UARTprintf("\n");
                TimerDelay();
            }
            i = 0;
        }else{
            i++;
        }
    }

    should be

    void Counter(void){
        if(i == 8){
            if(TimerFlag == 0){
                for(j=1; j<=i; j++){
                    UARTprintf("%i", GPIOarrays[j]);
                }
                UARTprintf("\n");
            }
            TimerDelay();
            i = 0;

        }else{
            i++;
        }
    }

  • Hi Slandrum,

    I've changed this but the problem still remains:

    void Counter(void){
        if(i == 8){
            if(TimerFlag == 0){
                for(j=1; j<=i; j++){
                    UARTprintf("%i", GPIOarrays[j]);
                }
                UARTprintf("\n");
            }
            TimerDelay();
            i = 0;
        }else{
            i++;
        }
    }

    Also is it good to use a SysCtlDelay? A friend tells me I should change this also with a timer because it will influence my main?

  • Hi,

    So i decided to count the amount of resets that are done before it spits out the character again (even though that I keep the button pressed) and these are always exactly 100 resets?

    Kind regards,

    Bart

  • The variable TimerFlag is referenced both inside and outside of interrupts.  Any variable that is referenced both inside and outside of interrupts must be declared as volatile, otherwise the compiler will make assumptions about when and how the variable can change, and may optimize out references to it.


  • Declaring TimerFlag as volatile int doesn't do it.

    Why does it work for a hundred resets? And what is this Watchdog Timer doing that becomes enabled in CCS?
    I'm wondering if this is the cause of my issue since my code works always for exactly 100 resets but then again a watchdog timer reset should not work when a timer is set to use PLL (or is this a mistaken assumption?)

    Grtz,

  • You aren't actually resetting the timer. If it is already enabled, enabling it again doesn't do anything. So it spits the number again because it timed out from the initial start or restart after a previous timeout.

    I don't know if you need to disable it first, but you probably have to reload the period each time. This means the ulPeriod variable should be global.

    void TimerDelay(void){
        TimerFlag = 1;
        TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT); // The timer may have timeout anyway, so we keep that line here
        TimerDisable(TIMER0_BASE, TIMER_A); // Just to be safe
        TimerLoadSet(TIMER0_BASE, TIMER_A, ulPeriod -1);
        TimerEnable(TIMER0_BASE, TIMER_A);
    }

    It seems you could unset the TAILD flag from the GPTMTAMTR register to allow reloading the period without calling TimerDisable to save some cycles. That flag isn't exposed by driverlib's timer API.

    The other lines:

    TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    IntEnable(INT_TIMER0A);
    IntMasterEnable();

    are just part of the timer configuration. They can be moved in the main() function.

  • Hi alexisdm,

    You're right, it also came to my attention yesterday when I did a read out of the timer value.

    You're notes work perfect:

    void TimerDelay(void){
          unsigned long ulPeriod;
          TimerFlag = 1;
          TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
          ulPeriod = (SysCtlClockGet()/50);
          TimerLoadSet(TIMER0_BASE, TIMER_A, ulPeriod -1);
          TimerEnable(TIMER0_BASE, TIMER_A);
    }

    Thanks alot for the great support!