Other Parts Discussed in Thread: TM4C123GH6PM
Howdy!
I am having a few issues with frequency measurements on the TM4C123GH6PM, here is more info:
I am attempting to measure frequencies in the 100 Hz - 200 Hz range, but am only able to detect in the 50 kHz to 150 kHz range.
I have two timers that are important to the operation I am attempting
- Timer 1 is used in edge time capture mode to interrupt whenever a rising edge is detected
- Timer 2 is runs continuously as a full width timer
- When timer 1 detects its interrupt event it takes the value stored in timer 2 and uses the previous value from the previous edge event to determine the length of the pulse in timer ticks
I am configuring the timers with the following code:
void timerConfigure(void){
ROM_SysCtlClockSet(SYSCTL_SYSDIV_12|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
uint32_t ui32Period;
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);
/*//Counter CODE HERE (START)
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1); //enable Timer 1
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); //using PF2 as T1CCP0
GPIOPinTypeTimer(GPIO_PORTF_BASE, GPIO_PIN_2); //configure pin PF2 to the timer peripheral
GPIOPinConfigure(GPIO_PF2_T1CCP0);
TimerConfigure(TIMER1_BASE, TIMER_CFG_A_CAP_COUNT);
//TimerIntEnable(TIMER1_BASE, TIMER_CAPA_EVENT);
*///Counter CODE HERE (END)
//TIMER CCP CODE HERE (START)
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1); //enable Timer 1
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); //using PF2 as T1CCP0
GPIOPinConfigure(GPIO_PF2_T1CCP0);
GPIOPinTypeTimer(GPIO_PORTF_BASE, GPIO_PIN_2); //configure pin PF2 to the timer peripheral
TimerConfigure(TIMER1_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_CAP_TIME);
TimerControlEvent(TIMER1_BASE, TIMER_A, TIMER_EVENT_POS_EDGE);
TimerLoadSet(TIMER1_BASE, TIMER_A, 65535);
//TIMER 2 used for capturing rollover
//TIMER 2 CODE START
TimerConfigure(TIMER2_BASE, TIMER_CFG_A_PERIODIC);
//TimerPrescaleSet(TIMER2_BASE, TIMER_A, 128);
//TimerLoadSet(TIMER2_BASE, TIMER_A, 65535);
//TIMER 2 CODE END
TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
ui32Period = (SysCtlClockGet() / 10) / 2;
TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet()/35);
TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
TimerIntEnable(TIMER1_BASE, TIMER_CAPA_EVENT|TIMER_TIMA_TIMEOUT);
IntMasterEnable();
IntEnable(INT_TIMER1A);
IntEnable(INT_TIMER2A);
TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT);
TimerEnable(TIMER2_BASE, TIMER_A);
TimerEnable(TIMER0_BASE, TIMER_A);
TimerEnable(TIMER1_BASE, TIMER_A|TIMER_B);
TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
}
When the Timer 2 interrupt is triggered this is the interrupt handler:
void Timer2IntHandler(void){
TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT);
TimerLoadSet(TIMER2_BASE, TIMER_A, 65535);
r++;
}
When Timer 1 interrupt is triggered this is its interrupt handler
void Timer1IntHandler(void){
GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_1, ui8PinData);
CurrentSampleCount = TimerValueGet(TIMER2_BASE, TIMER_A);
samplePeriod[t] = (lastSampleCount + (r * 65535)) - CurrentSampleCount;
lastSampleCount = CurrentSampleCount;
r=0;
if(t >= 4)
t=0;
else
t++;
if(ui8PinData==0) {ui8PinData=2;} else {ui8PinData=0;}
TimerIntClear(TIMER1_BASE, TIMER_CAPA_EVENT);
}
After running some test I noticed that the data that comes out from the operation in Timer1IntHandler() is only really accurate between the frequency ranges of 50 kHz and 160 kHz. Below 50 kHz the incoming data is scrambled and nothing of value can be extracted. Above 160 kHz, the microcontroller completely halts.
I got some advice to toggle a spare gpio pin (PD1) in the interrupt to see what it does on an oscilloscope, here are my results.
Note: probe 1 is the incoming signal from a function generator
probe 2 is the gpio pin being toggled
At the 100 Hz frequency I tested, the interrupt doesn't trigger often enough and misses most of the incoming edges that it should be detecting.
When the frequency is raised to the 100 kHz range, the interrupt triggers several times, drops out, then triggers several times again. The following image shows when the interrupt is toggling the gpio pin
There is also noticeable latency in the first interrupt, here it is 8.92 microseconds
But each successive toggle (until the interrupt stops triggering for a random amount of time) has a latency of about 1.7 - 1.9 microseconds after the nearest edge.
Any advice on what to do? I am about to attempt using a gpio interrupt to detect the incoming edges to see if that has any affect. I have also tried using a different pin (PB4) to detect the incoming edges using the same capture peripheral, which yielded the same results...
Many thanks for your time!
