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.

EK-TM4C123GXL: Loop's "split lap timer"

Part Number: EK-TM4C123GXL


Hi!

I'm trying to implement a "split lap timer"-function to count how much time each loop takes to complete. The algorithm is as followed:

I initialized the timer with:

    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_INT | SYSCTL_XTAL_16MHZ); //set frequency to 50MHz
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    SysCtlDelay(3);
    TimerDisable(TIMER0_BASE,TIMER_A);                   //Stop timer
    TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC_UP);  //Full-width periodic timer that counts up.
    TimerLoadSet(TIMER0_BASE, TIMER_A, 0x098967F);       //Max value 9999999
    TimerEnable(TIMER0_BASE, TIMER_A);                   //Start timer

The program goes the following way:

while(1) 
{
    time = TimerValueGet(TIMER0_BASE, TIMER_A);
    retrieve values from sensor
    do some calculation
    send time and values over serial USB
} 

After that, I convert the time values into float and divide them by 50e6. But the time values are far off the real ones. I have taken in account that the timer starts back from 0 after it reaches 9999999.
Has anyone any idea of what I am doing wrong? Thank you for your time!

  • Hello John

    Your code looks fine for counting up mode from 0 to 9999999. The resulting timer value get should not exceed the load value. Did you check that it is the case that the raw value does note exceed the load value?
  • Hi Amit!
    Thank you for your quick answer! I'm not sure I understand. Do you mean that I have to reset the timer every time after it counted the time? So, that it does not exceed the load value? I thought the counter just starts again from 0 after it reaches 9999999. Do I have to use the functions TimerEnable() and Timerdisable() to reset the counter?
  • I reset the timer values with HWREG(TIMER0_BASE + TIMER_O_TAV) = 0. Now the timer value never exceed the load value. I had to change the SYSCTL_SYSDIV_4 to SYSCTL_SYSDIV_1 in SysCtlClockSet() because one of my sensor stopped working with SYSCTL_SYSDIV_4. Do I have now to divide the values from the timer by 200e6?
  • I forgot about the SysCtlClockGet() function. Now I get more accurate values!
  • Hello John.

    So what were you using to divide the value of the timer?
  • I got the value from SysCtlClockGet() which was 12500000. I divided then the values from (float)TimerValueGet(TIMER0_BASE, TIMER_A) by that number. I set the clock with SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_PLL | SYSCTL_OSC_INT | SYSCTL_XTAL_16MHZ) because with SYSCTL_SYSDIV_4 one of my sensors didn't work anymore.
  • John Leporcq said:
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_PLL | SYSCTL_OSC_INT | SYSCTL_XTAL_16MHZ)

    Isn't the parameter, "SYSCTL_SYSDIV_1" verboten when using the PLL?   (via "SYSCTL_USE_PLL")    The MCU simply cannot run that fast.

    Your report of "Sensor not working" is unlikely to be the result of a (proper) frequency input.   (far more likely is misconnection, reversed polarity, ESD or over-voltage.)

  • Hello John

    As cb1 correctly identified, SYSCTL_SYSDIV_1 is not valid when using PLL. it can be at most be SYSCTL_SYSDIV_2_5 for 80MHz operation for TM4C123x devices.
  • Thank you & Hello Amit,

    In addition - poster has "over-loaded" function SysCtlClockSet() by employing (both) " SYSCTL_OSC_INT AND SYSCTL_XTAL_16MHZ)." In this particular case - there is NOT, "Safety in numbers!"
  • Hello cb1 and Amit!
    I think when I used SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_PLL | SYSCTL_OSC_INT | SYSCTL_XTAL_16MHZ) the µP used the default value 12.5MHz, which is the value I got from the SysCtlClockSet(). I tried using SYSCTL_SYSDIV_4 when I first saw in the datasheet (p.223) that the frequency was set as "reserved" for SYSCTL_SYSDIV_1. One of the sensors seems to be only working with a frequency of 12.5MHz. I change SYSCTL_SYSDIV_1 to SYSCTL_SYSDIV_16 and now everything is working. Thank you for your observation!
  • Your presentation of the sensor spec may enable a confirmation of the "Upper Frequency Limit" of your sensor.
  • The sensor is a Bosch BNO055. The max I2C frequency is 400Khz and it is set to 100 kHz with I2CMasterInitExpClk(I2C3_BASE, SysCtlClockGet(), false). I'm don't even understand why the frequency set by SysCtlClockSet() have to do with the sensor not working. The other sensors are MPU-9250 and MPU-9255. I can set any frequency and they still work.
  • As stated earlier - it is (extremely) unlikely that your altering of System Clock has impacted your I2C data rate. (provided you've properly set & referenced System Clock)

    Higher speed I2C forces more exactness & attention to detail upon (both) you & your system.

    You may wish to read/review the MCU's mechanism for relating System Clock to I2C clock rate...
  • Hello John,

    I agree with cb1. The I2C data rate can be achieved from any of the system clocks by correctly setting the Baud Rate divider (I2CMTPR) and this is specified in a table in the I2C section of the datasheet.
  • Hi Amit!
    I thought that I2CMasterInitExpClk(I2C3_BASE, SysCtlClockGet(), false) set the baud rate? In that case, it is set to 100kHz. Isn't the register I2CMTPR used if you want uncommon data rate, ie. other than 100kHz or 400kHz?
  • John Leporcq said:
    I have taken in account that the timer starts back from 0 after it reaches 9999999.

    One additional thought here: don't get too human on your MCU! Prefer powers of two. And since you are using a 32bit timer, it is more useful to load it to full 0xFFFFFFFF, for:

    - You can use the same counter to measure elapsed time of other things on your system (at 80MHz, you will be able to time events up to ~53 seconds);

    - If the counter overflows, a simple "Current Value minus Previous Value" will still give you a real result without the need for additional if's (given that all the variables involved are uint32's).

    Cheers,

  • Hi Bruno!
    Thank you for your remark! I decided to reset the counter every time I read a value. Now it works well without having to subtract anything.
  • Hello John

    The API I2CMasterInitExpClk provides for the 100KHz or 400KHz based on the 3rd argument. It also programs the MTPR register. So you could do the same with the API or by accessing the MTPR. Exclusive access to the MTPR is for the uncommon bit rates.
  • Bruno Saraiva said:
    If the counter overflows, a simple "Current Value minus Previous Value" will still give you a real result

    Or not!   Such (avoids) the case when the counter overflows (several) times!    Tracking the number of such "overflows" would be required for this method to (really) succeed.

  • cb1_mobile said:
    Tracking the number of such "overflows" would be required for this method to (really) succeed.

    Always a valid input!
    Although I did make sure that my statement was valid, for I mentioned that such solution "was good for about 53 seconds..."   ;)

  • Note that (only) "true fanatics" (you, Luis, moi) will be "saved" by your "footnote!"
    No one else is likely to care that much - read that far.

    Best contracts get all the key elements "Up Front!" (where SURE to be noted)