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.

TM4C123GH6PM: Timer value is wrong?

Part Number: TM4C123GH6PM


I'm using a timer to count how long a pin is high for. I'm currently getting a value that is 80% of the value that it should be for example if the pin is high for 2 seconds I get 1.66 seconds.

  • Respected sir,
    Please give us a more information about your application and how you are measuring period.
    regards,
    digvijay
  • void receive()
    {
    received = GPIOPinRead(GPIO_PORTC_BASE, GPIO_PIN_5);

    if (received != 0 && binaryReceived == 0) {
    binaryReceived = 1;
    HWREG(TIMER1_BASE + TIMER_O_TAV) = 0;
    TimerEnable(TIMER1_BASE, TIMER_A);
    }

    if (binaryReceived == 1 && received == 0) {
    binaryReceived = 0;
    timePassed = TimerValueGet(TIMER1_BASE, TIMER_A);
    TimerDisable(TIMER1_BASE, TIMER_A);
    time = ((double)timePassed) / 80000.0;
    if (time > 10.0)
    UARTprintf("time: %d\n", (int) time);
    }
    }
  • Zach Szczesniak said:
    I'm using a timer to count how long a pin is high

    Good that - yet you've not revealed your problem-solving technique in (usable) detail - is that not so?

    It often proves wise to analyze the potential "cause" of such issues.      Have you considered your (possible) error sources?

    • how is your "measuring timer" clocked - is the clock source "known" and/or "measured?"
    • how do you start (or trigger) the "MCU-based" measurement process?     Does the measurement start immediately - and consistently?
    • how do you end the "MCU-based" measurement process?      Does the measurement end immediately - and consistently?
    • how have you measured  your 2 second period?     (independently from your MCU - your reported error of 0.34 seconds (may) result from "typical" stopwatch or other mechanical errors)      Should you be measuring against a "stopwatch" or other mechanical means - you can reduce "typical/stopwatch" type errors - by extending your target "Pin High" time to 10 seconds - for example...

    It is extremely unlikely that the Timer - or any value it acquires - proves wrong.       Your methods - and the accuracy of the MCU's System Clock - rise FAR Higher on the "suspect list."    

    Questions posed aim at assisting "you" to implement the necessary "code implementation" corrections...

    [edit]  while there is a 30 minute difference between poster's timestamp & my own - his 2nd post here was not present when I composed the above.

    The code you show fails to "loop" - thus it is a "one & done" - surely that's NOT what you intended.

    I continue in the belief that your "Answers to the questions posed" will lead to your success...

  • Follows - a brief attempt to strengthen the code blurb  earlier provided:

    • To secure any accuracy you must loop on your read of the  "Target pin"     (your code revealed "NO/ZERO" such looping)
    • Upon the target pin's "setting" - you escape that "Read Target pin loop" - clear & enable the timer - and after that - set your "binary_received" variable.     (setting it earlier ADDS ERROR!)
    • Code then flows thru to a new loop - again reading the "Target pin" - but this time awaiting its transition to logic low
    • Upon  that low detection - you again escape the 2nd "Read Target pin loop."    TimerValueGet() is then executed immediately - NOT after your setting of "binary received"    (again - that ADDS ERROR!)

    This method "follows" your earlier code's lead - yet adds the (required) looping structure.     It must be noted - that "sitting w/in those loops" blocks the MCU from anything but "interrupt servicing."    For a simple measurement - that (may) be ok - but not for general MCU usage.

    Converting your code from such "loops" into "Interrupt based" prevents the code from "blocking" - enabling the MCU to perform (other) needed tasks.

    To achieve such "interrupt operation of your timer:"

    • Program your GPIO Port (and pin) to interrupt upon a "rising edge"    (this detects the transition from low to high)
    • W/in that GPIO "Rising Edge" service - Clear & Enable your timer 
    • then - w/in that same service - a) call a function to change the interrupt from "rising to falling" edge; or b) hardwire your target pin - in parallel - to a different Port - and program that port to "falling edge" interrupt
    • upon entry into the "reconfigured, falling edge ISR  or  entry into the separate Port's falling edge ISR - execute "TimerValueGet().     The timer's content will contain your measured interval - yet add - at minimum 24 MCU cycles.    (12 each - required to arrive @ each ISR)    (the effect of those added cycles should prove nominal - or as they are "known" may be subtracted from the timer's content

    Again - this interrupt-based method "Frees the MCU for other activities" - and while adding complexity - most always is preferred...

    Unknown is how you arrived at the variable "time" being divided by 80,000.     It is assumed your System Clock was at/near 80MHz - thus each Timer "Tick" is 12.5nS.      It is suspected that your use of a 32 bit timer will "Prevent Timer Roll-Over" - thus expanding the range of your measurement capability...    (to at/around 53 seconds - if my late night math proves correct)