Go Down

Topic: Due Counter Overflow Interrupt Problem (Read 611 times) previous topic - next topic

otobus

Hi guys;
I worked on due a little and I am very new to Arduino community. I manage to build pulse counter or frequency reader whatever you say, however 32 b?t counter is not enough for what I want.  I thought I can get some overflow flag when the counter reaches to 4294967296 (2^32) therefore I get a carry and ? can count pulses more than 4294967296.
The problem is I cannot manage to do some overflow interrupt. Here is my code so far :

Code: [Select]
#include <DueTimer.h>
#define TC_CHANNEL_0 0
#define TC_CHANNEL_1 1
#define TC_CHANNEL_2 2
#define PIN_TC0_TCLK0_ARD (22u)

volatile long unsigned int data[1000];
word i = 0;

void setup(){
  pinMode(PIN_TC0_TCLK2_ARD,INPUT);
  pmc_enable_periph_clk(ID_TC0);
  Serial.begin(9600);
  TC_Configure(TC0, TC_CHANNEL_2, TC_CMR_TCCLKS_XC0); 
  TC_Start(TC0, TC_CHANNEL_2);
  Timer4.attachInterrupt(myHandler);
  Timer4.start(1000000);
  NVIC_EnableIRQ(TC0_IRQn);   
}
                                                                                                             
void loop() {

}

void myHandler ()
{
  data[i]= TC_ReadCV(TC0,TC_CHANNEL_2);
  //REG_TC0_BCR = 0x1;
  //if (i == 0){
  Serial.print(i), Serial.print(" "), Serial.println(data[i]);
 
  }
  else{
  Serial.print(i), Serial.print(" "), Serial.println(data[i] - data[i-1]);
 
  }
  i++;
 
}


https://github.com/ivanseidel/DueTimer this is the link for library. however i used that to get more accurate delay. Just for your information.

So how could i do it? Any suggestions...
Thanks in advance.

AussieSusan

I don't have an answer but what is it you are trying to do?
I'm not sure how the timer code works, but I assume that it is calling your handler once a second and therefore you are getting an overflow every 71.58 minutes (1 hour, 11 and a bit minutes). [The alternative means you would not overflow for over 8000 years!].
If the resolution of your sampling is one second, then you will have a limit of 4,29GHz (that is 2^32 pulses in a second). If you need more than that, then try sampling every 10th or 100th of a second and applying the appropriate multiplier to the result.
Susan

Magician

It's not clear what external freq. is. You mixing up a library code with your own, and I'm afraid it's not gonna to work. Library seems to me doesn't have external events counting, so it's always running from internal clock, and what worse its setting different clock (preselector) based of the freq. you are setting up.
If the objective of your project to count external pulses with highest possible resolution , max freq. 42 MHz - limited by input pin synchronization circuits, than timer overrun in 4294967296/42000000 = 102 sec. 
Anyway here a code snippets , that you will have to adjust in some way:
Code: [Select]
void tmB_setup ()
{
  uint32_t reg_val;
  pmc_enable_periph_clk (TC_INTERFACE_ID + 0 *3 + 1) ;  // clock the TC0 channel 1

  reg_val = TC_BMR_TC1XC1S_TIOA0;   <<<---- TC_BMR_TC1XC1S_TCLK1;  in your case, replace, and use Analog pin 5
  TC0->TC_BMR = reg_val;  <<<<--- selects External clock

    TcChannel * t = &(TC0->TC_CHANNEL)[1];
    t->TC_CCR = TC_CCR_CLKDIS; 
    t->TC_IDR = 0xFFFFFFFF;     
    t->TC_SR;                   
    t->TC_CMR = TC_CMR_TCCLKS_XC1 | //  Because TC0 Channel-1
          TC_CMR_WAVE |                  // waveform mode
          TC_CMR_WAVSEL_UP_RC |          // I'd leave it's as it is, and set 1000 000 or another "good" number instead of FFFFF
          TC_CMR_EEVT_XC1 |     //
          TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR |
          TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR ;
         
  t->TC_RC = frm_rate * 227;    // < here, 1000 000   
  t->TC_RA = 3;                 // whatever
  t->TC_CMR = (t->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET ;  // probably you don't need this
  t->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ;  // re-enable local clocking and switch to hardware trigger source. 
  t->TC_IER =  TC_IER_CPCS;
  t->TC_IDR = ~TC_IER_CPCS;
//  NVIC_EnableIRQ(TC1_IRQn); // enable TC0 interrupts
}

void TC1_Handler(){
  uint32_t reg_val0 = REG_TC0_SR1; // vital - reading this clears some flag
                                   // otherwise you get infinite interrupts

// your code
}


otobus

Sorry about that i'm not very clear for my problem. Actually I'm counting pulses around 25 MHz which gives me 170ish seconds for data collection before overflow. I know that both library and I am using the same clock that's why i choose to use library's 4th clock instead of any other. But I only use that interrupt for delay. i mean i can put the code inside the handler into loop function and add for example 1 sec delay i get the same thing. the only reason i'm using library is that it timing accuracy it much more better than delay() function itself. so i can get the accurate results. Anyway; my point is to get some other interrupt than in the code i sent, which let me create some handler so i can count number of interrupts.  Other than that that code works great.
@Magician looks like i can find some information from you code snippet. Let's see... :D

otobus

@Magician btw if you give me some more comment about the code you give; i'll be glad.

Magician

The code in reply #2 I use in my latest project, where I need to cascade two timers,  chaining output TC0-0 to TC0-1, that gives me two freq. primary and another lower by /N, both synchronous. I'm setting SYNC in interrupt handler .

Library, as I can see doesn't have an API to select external source.  SAM3X data sheet 'd explain all other details in the snippet,

Go Up