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.

TM4C129DNCPDT: Timer counter without interrupt

Part Number: TM4C129DNCPDT
Other Parts Discussed in Thread: EK-TM4C1294XL

Hi, 

    I am working on TM4C129DNCPDT and TI-RTOS and Tivaware driver lib.

    How to setup timer counter increment every 1us?  we don't want any interrupt, we want to pull the counter value.

For setup

void init_timerCounter()

{

SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

while(!SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER0))
{

}
TimerClockSourceSet(TIMER_B, TIMER_CLOCK_SYSTEM);
TimerConfigure(TIMER_B, TIMER_CFG_PERIODIC_UP);
TimerLoadSet(TIMER0_BASE,TIMER_B,ui32SysClock/1000);
TimerPrescaleSet(TIMER0_BASE,TIMER_B,16);
TimerIntDisable(TIMER0_BASE,TIMER_B);
TimerEnable(TIMER0_BASE, TIMER_B);

}

For counter value get

uint32_t = time1;

 time1 = TimerValueGet(TIMER0_BASE, TIMER_B);

I am getting some run time error.

Maybe i am doing something wrong. 

Regards,

Sumit

  • HI,

      The below two lines are wrong. The first argument to the API should TIMER0_BASE. When you specify the source clock to the timer, it will apply to both TIMER_A and TIMER_B. 

    TimerClockSourceSet(TIMER_B, TIMER_CLOCK_SYSTEM);
    TimerConfigure(TIMER_B, TIMER_CFG_PERIODIC_UP);

    There are few timer examples in TivaWare library. You can find them in 

     C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\timers

    C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\timer_edge_capture

    and several examples in:

    C:\ti\TivaWare_C_Series-2.2.0.295\examples\peripherals\timer

  • Hi, Charles thank you for help.

        Actual Charles i am measuring pulse with of 10us to 150us. Most of the time i am getting very close value like 12us/11us/10us. But sometime i am getting 20us/17us. one or two sample(pulse width) out off 10 sample(pulse width) i am getting like this. I am following your suggest example (C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\timer_edge_capture). I am using only one Timer. we are generating pulse from Function generator.

    How to solve this problem?

    Please Check my configuration once.

    void timer_Init(void)
    {
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER0))
    {

    }
    MAP_TimerClockSourceSet(TIMER0_BASE, TIMER_CLOCK_SYSTEM);
    MAP_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC_UP);
    MAP_TimerLoadSet(TIMER0_BASE,TIMER_A,0xFFFF);
    MAP_TimerPrescaleSet(TIMER0_BASE,TIMER_A,0xFF);
    MAP_TimerIntDisable(TIMER0_BASE,TIMER_A);
    MAP_TimerEnable(TIMER0_BASE, TIMER_A);
    }

    void PP3_ISR()

    {

    MAP_GPIOIntClear(GPIO_PORTP_BASE, GPIO_INT_PIN_3);
    EdgD = MAP_GPIOPinRead(GPIO_PORTP_BASE, GPIO_PIN_3);
    switch (EdgD)
    {
            case 8:    //Rising edge
            PR = (MAP_TimerValueGet(TIMER0_BASE, TIMER_A)) +(MAP_TimerPrescaleGet(TIMER0_BASE, TIMER_A) << 16);
            break;

            case 0:     // Falling Edge
            PF = (MAP_TimerValueGet(TIMER0_BASE, TIMER_A))+ (MAP_TimerPrescaleGet(TIMER0_BASE, TIMER_A) << 16);
            if(PF> PR)
            {
              PLSWArry[Pc++]=((PF-PR)/120); // clock = 120
            }
            else
                 PLSWArry[Pc++]= ((PF + 16777215) - PR)/120; //clock =120

            break;
    }
    }

    Regards,

    Sumit 

  • Hi,

    Please refer the example I provided at C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\timer_edge_capture. If you want to measure the an input pin then you should configure the timer in ' Input Edge Time Capture' mode as in TIMER_CFG_A_CAP_TIME_UP. Refer to Input Edge-Time mode in the datasheet. 

    Since you are not measuring a  long pulse, you can just use either Timer_A or Timer_B in 24bit resolution. You can configure the capture event to be both edges so it will measure both the high and low phases of the input. 

  • Hi, Charles.

          Actually Timer capture and compare mode is not available for PP3, and in our hardware it is connected to PP3 for both edge.

     init_PP3_ISR()

    {

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);
    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOP))
    {

    }
    MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_3);
    MAP_GPIODMATriggerEnable(GPIO_PORTP_BASE, GPIO_PIN_3);
    MAP_GPIOIntTypeSet(GPIO_PORTP_BASE, GPIO_PIN_3, GPIO_BOTH_EDGES); // GPIO_RISING_EDGE and falling edge
    MAP_GPIOIntEnable(GPIO_PORTP_BASE, GPIO_INT_PIN_3);

    }

    gpioPulse_hwi = Hwi_create(INT_GPIOP3_TM4C129, Pulse_Detect_ISR, &gpioPulse_hwiParams, &eb_HiPulse); // hardware interrupt enable
    if( gpioPulse_hwi == NULL)
    {
    System_abort(" *** Hardware interrupt create fail for pulse monitor");
    }

    Hwi_enableInterrupt(INT_GPIOP3_TM4C129);   

    So, Is there any other way to solve with this hardware(PP3)? 

    Thanks and Regards,

    Sumit Chaulya

  • Hi,

      There is an issue to your approach. If the next edge comes too quick you may just miss it using one timer. Think about that you get a PP3 interrupt for a rise edge. It takes some time/cycles for the processor to respond to it and jumps to the ISR. In your ISR, you are clearing the PP3 interrupt flag. What if the next falling edge comes quickly around the same time you are clear the flag? Since you just clear the flag, you lose the falling edge event. In the next rise edge interrupt, you will be measuring the period instead of duty cycle. The solution is to use two timers on two different pins with one generating an interrupt for rise edge and the other generating interrupt on fall edge. This is how the example was developed to address capturing short pulses. 

  • Hi, Charles.

          My pulse measurement is working fine with TIMER0_BASE, TIMER_A.

          But  if  use TIMER0_BASE,TIMER_B i am not getting correct value.

          Am i doing something wrong ??

    void timer_config(void)
    {
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER0))
    {

    }
    MAP_TimerClockSourceSet(TIMER0_BASE, TIMER_CLOCK_SYSTEM);
    MAP_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC_UP);
    MAP_TimerLoadSet(TIMER0_BASE,TIMER_B,0xFFFF); 
    MAP_TimerPrescaleSet(TIMER0_BASE,TIMER_B,0xFF);
    MAP_TimerIntDisable(TIMER0_BASE,TIMER_B);
    MAP_TimerDisable(TIMER0_BASE, TIMER_B);
    }

    //measurement 

    void measure_func()

    {

    MAP_GPIOIntClear(GPIO_PORTP_BASE, GPIO_INT_PIN_3);
    EdgD = MAP_GPIOPinRead(GPIO_PORTP_BASE, GPIO_PIN_3);
    switch (EdgD)
    {
    case 8: // Rising edge
    PR = (MAP_TimerValueGet(TIMER0_BASE, TIMER_B)) +(MAP_TimerPrescaleGet(TIMER0_BASE, TIMER_B) << 16);
    break;

    case 0: // falling edge
    PF = (MAP_TimerValueGet(TIMER0_BASE, TIMER_B))+ (MAP_TimerPrescaleGet(TIMER0_BASE, TIMER_B) << 16);
    Swi_post(Pulse_Detect_Swi); // call Pulse_Detect_Swi_func
    break;
    }

    }

    Regards,

    Sumit 

  • Hi,

    MAP_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC_UP);

    This line is wrong if you want to use Timer-B. When you use TIMER_CFG_PERIODIC_UP, this is to use the full-width timer, meaning to combine Timer_A and Timer_B as one 32-bit timer.

    You should use as follows if you want to use just timer_B. 

    TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_PERIODIC_UP);