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-TM4C1294XL: 65 count error in period measurement (using T0CCP0)

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

Hi,

I am using eval board and CCS and written application to measure frequency on timer CCP0 (timer configured in capture edge time, count-up, detect positive edge).

Frequency is being generated using PWM of board with 50% duty cycle on pin PG0 and is physically connected to T0CCP0 pin (PD0).

Code is measuring frequency consistently for different PWM frequencies (>32Hz due to limitation of 24 bit timer). 

However, for all measurement, i found that there is error of 65 count in each case. As such for lower frequency, error is small, but for higher frequency, error becomes considerable.

I am not sure if the source of this error of 65 count is PWM or timer. Please let me know what is that i am missing.

My code is as below:

#include <stdint.h>
#include <stdbool.h>
#include "inc/tm4c1294ncpdt.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/debug.h"
#include "driverlib/pwm.h"
#include "driverlib/pin_map.h"
#include "inc/hw_gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/timer.h"

#define PWM_FREQUENCY 50

static volatile uint32_t lastValue=0;
static volatile float frequency;

int main(void)
{
volatile uint32_t ui32Load; // PWM period
volatile uint32_t ui32PWMClock; // PWM clock frequency
volatile uint32_t ui32SysClkFreq; // Value returned by SysClockFreqSet()

ui32SysClkFreq = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG); //Port G enabled since PWM4 is on PG0.
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); //Port D enabled since T0CCP0 is on PD0.
SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0); //PWM module 0 enabled.
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); //Timer0 enabled.
SysCtlDelay(3); //delay of 3 cycle before accessing PWM registers.

PWMClockSet(PWM0_BASE,PWM_SYSCLK_DIV_64); //PWM cloack = sysclk/64

GPIOPinConfigure(GPIO_PG0_M0PWM4); //GPIO pin configuration for PWM
GPIOPinTypePWM(GPIO_PORTG_BASE, GPIO_PIN_0); //GPIO pin configuration for PWM

GPIOPinConfigure(GPIO_PD0_T0CCP0); //GPIO pin configuration for timer capture
GPIOPinTypeTimer(GPIO_PORTD_BASE, GPIO_PIN_0); //GPIO pin configuration for timer capture

TimerConfigure(TIMER0_BASE, (TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP)); //Config timer A of for capture mode in time-up
TimerControlEvent(TIMER0_BASE, TIMER_A, TIMER_EVENT_POS_EDGE); //Config timer A to capture positive edge
TimerControlStall(TIMER0_BASE, TIMER_A, true); //Timer stalls while CPU is in debug mode

TimerPrescaleSet(TIMER0_BASE, TIMER_A, 255); //Load timer pre-scaler with max value
TimerLoadSet(TIMER0_BASE, TIMER_A, 65535); //Load timer with max value

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

ui32PWMClock = ui32SysClkFreq / 64; // 120MHz/64
ui32Load = (ui32PWMClock / PWM_FREQUENCY) - 1; // 1875000/PWM_FREQUENCY

PWMGenConfigure(PWM0_BASE, PWM_GEN_2, PWM_GEN_MODE_DOWN);
PWMGenPeriodSet(PWM0_BASE, PWM_GEN_2, ui32Load);
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_4, ui32Load/2);
PWMOutputState(PWM0_BASE, PWM_OUT_4_BIT, true);
PWMGenEnable(PWM0_BASE, PWM_GEN_2);

TimerEnable(TIMER0_BASE, TIMER_A); //Timer enable

while(1)
{

}

}


void Timer0IntHandler(void)
{
uint32_t newValue, period;

// Clear the timer interrupt
TimerIntClear(TIMER0_BASE, TIMER_CAPA_EVENT);

newValue = TimerValueGet(TIMER0_BASE, TIMER_A);

if(newValue <= lastValue)
period = (16777215-lastValue) + newValue;
else
period = newValue - lastValue;

frequency = 120000000.0f / (float)period ;

lastValue = newValue;

}

  • Hi Pranav,

    Some comments:

    You said you are missing 65 counts. Might this be due to the PWM clock division of 64 you use? Can you change from the PWMClockSet(PWM0_BASE,PWM_SYSCLK_DIV_64) to PWM_SYSCLK_DIV_1 and see if it makes a difference. If you have a function generator, it will be good to use and rule out issues in the PWM generation. It is easier to debug one thing at a time. Another thing in your timer configuration you configure the timer to count up as in TIMER_CFG_A_CAP_TIME_UP, in this case the timer counter should just start from 0 until it times out at 0xFFFF. You shouldn't need to preload the timer with 65535.
  • Hi Charles,

    Thanks a lot for your comments.
    It solved issue. I did change PWM period from

    ui32Load = (ui32PWMClock / PWM_FREQUENCY) - 1;

    to

    ui32Load = (ui32PWMClock / PWM_FREQUENCY);

    and thats all.
    It is now measuring exact frequency without any error.

    For the comment on timer pre-load value, i tried by removing pre-load instruction. But then it started measuring incorrect frequency.
    I understand that in count-up mode, it do start with at 0 upto pre-load value.


    BR,
    Pranav.