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.

TM4C129XNCZAD: Frequency compare at higher value

Part Number: TM4C129XNCZAD

Dear Sir,

We are using TM4c129xCZAD design. 

In  our project we use external interuupt handler to sense -ve edge trigger pulses for frequency 60 KHZ.

The above fast frequency pulse are input to the controller two  diffrent pin.

We have compare  two 60kHZ pulses and calculate the % error through timer and getting % error =0. Its working fine

Now the frequency got change to 200 Khz and when we compare these we  get %errror=0.00009 or 0.00019

Is it issue with such high frequency because  when we checked with 100KHZ  then also it is working fine.

We checked voltage level and amplitude that also OK.

Kindly suggest

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

void External_pulseIntHandler(void)
{
MAP_GPIOIntClear(GPIO_PORTM_BASE, GPIO_PIN_6);


pulse_count++;
if(pulse_count==1000)
{
Edge_count++;
C_Edge_count++;
pulse_count=0;
}

if(timer_start_flag==0)
{
MAP_TimerIntClear(TIMER6_BASE, TIMER_CAPB_MATCH); // Clear the timer interrupt.

Timer6_start();
timer_start_flag=1;
Edge_count=0;
C_Edge_count=0;
pulse_count=0; //New added after observation

}
if((Edge_count!=0)&&((Edge_count)==master_meter_pulse)&&(Edge_mode_flag==0)&&(timer_start_flag))
{
MAP_TimerDisable(TIMER6_BASE, TIMER_B); //Disable Timer2
N_Actual = fout_intCount*0xffff + 65535 - MAP_TimerValueGet(TIMER6_BASE, TIMER_B); // counter fout pulses at the end of sacnner pulses
display_flag=1;
Flag.N_Actual_Ready=1; //Received all scanner pulses
Edge_count=0;
C_Edge_count=0;
pulse_count=0; //New added after observation
timer_start_flag=0;
zero_flag=1;
Flag.Pulse_Received = 0;

}

void Timer6_start(void)
{
MAP_TimerLoadSet(TIMER6_BASE, TIMER_B, 0xffff);
MAP_TimerMatchSet(TIMER6_BASE, TIMER_B, 0x0000);
MAP_TimerEnable(TIMER6_BASE, TIMER_B); //Enable fout counter
MAP_IntEnable(INT_TIMER6B);
fout_intCount=0;
}

N_Must  is fixed value 

error_calc = (((N_Must - N_Actual)/N_Actual) * 100) 

  • Hi,

      Can you extrapolate the error percentage for 300kHz and 400kHz? As you increase the input frequency, the interrupt will trigger faster as well. You have quite some code in the ISR to process. When the input frequency increases, it is possible an interrupt is generated before the ISR is completely existed for the last interrupt. I will suggest you move the processing code outside of the ISR. Keep the ISR as short as possible. 

      

  • Dear Charles,

    I also thought the same as you replied. I already tried to keep ISR as short as possible and did the processing outside the code then problem arises of not refreshing % Error because the things are so fast that % error is not refreshing so quickly.

    Regarding 300Khz and 400Khz we don't have any source which generate the frequency. 

  • Hi,

      I'm not really following your code. You seem to start and halt the timer in the GPIO interrupt ISR. Can you explain the purpose of timer? Why don't you handle the timer interrupt on its own ISR?

  • Dear Charles,

    Actually We used external interrupt handler for receiving the external pulses i.e 200kHz square wave signal.

    and after receiving the first pulse of external pulse we started timer for measurement and  stop the timer when user input pulse received .

    We use this time and compare with known time for calculation of % error.

    This things are working fine when the input pulse is upto 100kHZ .

  • Waiting for your reply

  • Hi,

      As I mentioned, there will be some latency from the time a edge is detected on your 200kHz input to the time the ISR is entered. When you are in the ISR, it also takes some time to initiate the timer module. I also mentioned that as the interrupt comes too fast, by the time you are starting the timer, another edge is detected on your 200kHz input. Perhaps, you should disable the external interrupt after you detect the first edge of your 200Khz and let the timer counts until the user input is detected. 

  • Dear Charles,

    Our requirement  first edge of external interrupt we start the timer and 100th or 1000th edge we stop the timer. 

    We also disable master interrupt while entering in to external interrupt handler and Enable while exit from handler.

    As you mentioned "you should disable the external interrupt after you detect the first edge of your 200Khz and let the timer counts until the user input is detected." 

    if we disable external interrupt after 1st edge then how will count 100th or 1000th edge ?

  • 1) There is a latency between the time your ISR is entered (the final pulse) and the time you read the timer. This introduces a constant error, dependent on the code path length (number of instructions) but independent of the speed of your signal. As you speed up the signal, the timer values you measure get smaller; thus this constant latency error becomes a larger proportion of your measurement. Using your method, you can't really get rid of this latency, but a very simple mitigation would be to always read the timer value up at the top of the ISR, then decide later whether to use it.

    2) As Mr Tsai said, there's a good chance you're starting to overrun the ISR, i.e. the time it takes to run the ISR is longer than the time between pulses. A clue is that you said the code doesn't run (starved) when moved to main(). Once this happens, you will (sooner or later) miss pulses. One solution is to use a(nother) timer in Edge Count mode to count the pulses. Another is just to pare down your ISR code.