I am trying to configure wide timer 0 to calculate the frequency of a pulse train (~1 kHz) using the edge timer function.
Configuration code:
//
// Set the clocking to run at 50 MHz from the PLL.
//
ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
SYSCTL_OSC_MAIN);
/*
* Configure the input pin (PC4) to use CCP
*/
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOC)) {}
GPIOPinConfigure(GPIO_PC4_WT0CCP0);
GPIOPadConfigSet (GPIO_PORTC_BASE, GPIO_PIN_4, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPD);
GPIODirModeSet (GPIO_PORTC_BASE, GPIO_PORTC_BASE, GPIO_DIR_MODE_IN);
GPIOPinTypeTimer(GPIO_PORTC_BASE, GPIO_PIN_4);
/*
* Configure the timer A module of wide timer 0 in rising edge timer mode, configure timer B in periodic mode
*/
SysCtlPeripheralEnable(SYSCTL_PERIPH_WTIMER0);
while (!SysCtlPeripheralReady(SYSCTL_PERIPH_WTIMER0)) {}
TimerConfigure(WTIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME | TIMER_CFG_B_PERIODIC);
TimerControlEvent(WTIMER0_BASE, TIMER_A, TIMER_EVENT_POS_EDGE);
/*
* Set the timer prescale and load value
*/
TimerLoadSet(WTIMER0_BASE, TIMER_BOTH, 250000);
/*
* Setup the interrupts for the timer CCP and timer timeout
*/
TimerIntRegister(WTIMER0_BASE, TIMER_A, TimerW0AInt);
TimerIntEnable(WTIMER0_BASE, TIMER_CAPA_EVENT);
IntEnable(INT_WTIMER0A);
/*
* Enable master interrupts
*/
IntMasterEnable();
/*
* Enable the timers
*/
TimerEnable(WTIMER0_BASE, TIMER_BOTH);
ISR:
/*
* Get the type of timer interrupt occurred and then clear it
*/
TimerIntClear(WTIMER0_BASE, TIMER_CAPA_EVENT);
/*
* The CCP edge capture has occurred, calculate the period of the signal if another edge
* has been captured before this
*/
uint32_t ui32_snapshot = TimerValueGet(WTIMER0_BASE, TIMER_A);
if (gui8_edge_flag) {
int32_t i32_delta;
// Calculate the time delta
i32_delta = gui32_last_timer_val - ui32_snapshot;
/*
* Check for timer overflow: since the timer is in down-count mode the new snapshot
* value will be greater than the last if overflow occurred (hence the time delta will
* be negative. If there is overflow add the timer load value to the difference to
* calculate the true time delta.
*/
if (i32_delta < 0) {
i32_delta += TIMER_PERIOD + 1;
}
/*
* Store the time delta to a buffer
*/
xSemaphoreTakeFromISR(gp_time_delta_semaphore, NULL);
circbuf_write(&g_freq_buffer, (uint32_t) i32_delta);
xSemaphoreGiveFromISR(gp_time_delta_semaphore, NULL);
} else {
// Set the flag
gui8_edge_flag = 1;
}
// Update the last value of the timer edge
gui32_last_timer_val = ui32_snapshot;
I am using a timer load value of 250000, which by my calculations should allow a minimum input frequency of 50MHz / 250000 = 200 Hz. The circbuf_write just adds a value to an array acting as a circular buffer and updates a running sum of the buffer contents (I have had this working with other code). I am using a test square wave input signal (50% DC, 500 Hz, 0-3.5 V) to cause the interrupts. I am reading the value of i32_delta using the debugger and it is fluctuating pretty dramatically: I'm not sure if this is due to the Tiva missing the edges or something else that I am missing.