TC0 timer in Xmega

Go To Last Post
18 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I have a problem with the overflow time in TC0 timer. here's my code:

 

interrupt [PORTH_INT0_vect] void porth_int0_isr(void)
{

    #asm("wdr")     

    if (!(s19==0))
    {
        if(s19==1)
            TCE0.PERBUF=131;
        else if(s19==2)
            TCE0.PERBUF=133;
    }
    else
    {
        TCE0.PERBUF=132;
    }

}

 

This interrupt will be triggered in every falling_edge of an input signal (19 KHz clock). TCE0.PER initial value is 132 and the Xmega clock is 4332 KHz. I have another interrupt which is related to TCE0 overflow:

 

interrupt [TCE0_OVF_vect] void timer_int0_isr(void)
{
   #asm("wdr")
    
    s19+=1;
    if (s19==4)

        s19=0;
 
    s57+=1;        

    if (s57==192) 
    {
        s57=0;

        ...

     }

     ...

}

 

s57 and s19 initial values are 191 and 0, respectively. My question is how many times interrupt [TCE0_OVF_vect] will be triggered in a 19 KHz input clock cycle? and what is the reason of assigning 131, 132 and 133 to TCE0.PERBUF with respect to s19.

 

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There's not enough information given. You say it is your code, so why ask about 131,132,133? Surely if you wrote the code you would know?
What is the code expected to do?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dear Kartman,

No I didn't write this part, somebody else did and I should understand it to complete the rest of the code. The target of the code is to make a 1187.5 Hz clock signal using the 19 KHz input clock. So, two interrupts has been used to do this. An interrupt on the pin which is 19 KHz input clock signal (interrupt [PORTH_INT0_vect] (this interrupt is falling_edge triggered)), and the other is TCE0 timer overflow interrupt (interrupt [TCE0_OVF_vect]). I know that the 1187.5 Hz clock is produced in if (s57==192) but I don't understand what is going between s19 and TCE0.PERBUF to trigger interrupt [TCE0_OVF_vect] and increment s57 by one to make 1187.5 Hz clock. 

Last Edited: Sat. Jan 7, 2017 - 12:32 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Still not enough information. Dividing 19k by 16 gives you 1187.5. So why the shenanigans? What is the significance of the 19kHz and 1187.5Hz? Are you trying to extract data from RDS or something like that?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes exactly, I want to send RDS data to DAC. I need 1187.5 Hz clk because of that. You are right we can divide 19 KHz by 16 but I can't understand this code. Here's the complete functions:

 

TCE0.CTRLE=0x01;       
TCE0.INTCTRLA=0x02;   
TCE0.PER=132; 
TCE0.PERBUF=132;

TCE0.CTRLA=0x01;

//interrupt on PORTH6 which is PILOT 19 KHz
interrupt [PORTH_INT0_vect] void porth_int0_isr (void)
{

    #asm("wdr")     

    if ( !(s19 == 0) )
    {
        if(s19 == 1)
            TCE0.PERBUF = 131;
        else if(s19 == 2)
            TCE0.PERBUF = 133;
    }
    else
    {
        TCE0.PERBUF = 132;
    }

}

 

/////////////////////

interrupt [TCE0_OVF_vect] void timer_int0_isr (void)
{
    uchar uchar1;
       
    #asm("wdr")
    
    s19 += 1;
    if (s19 == 4) 

         s19 = 0;
 
    s57 += 1;        // count 1187.5 counter

    if (s57 == 192)  // if 1187.5
    {
        s57 = 0;
        bit_count += 1;

        if(bit_count == 8)
        {
            bit_count = 0;
            byte_count += 1;
            if(byte_count == 12)
                change_send_group = 1;
            if(byte_count == send_buff_size)
                byte_count = 0;

            rds_send_buff = rds_data[byte_count];
        }
        else 
        {
            rds_send_buff=rds_send_buff << 1;
        } 

      

        uchar1 = rds_send_buff&0x80;
        crnt_rds_bit = uchar1 ^ prvs_rds_bit;

      

        if (crnt_rds_bit == 0)
        {
            if (prvs_rds_bit == 0)
             { bit_mode = 0; }
            else 
             { bit_mode = 2; }
        }   
        else if (prvs_rds_bit == 0)
        {
            bit_mode = 1;
        }
        else
        {
            bit_mode = 3;
        }         
        
        prvs_rds_bit = crnt_rds_bit;

        s_dps += 1;              
    }    
    switch (bit_mode)
    {
        case 0:DACB.CH0DATA = rds_mod0[s57];break;    // rds_mod0
        case 1:DACB.CH0DATA=rds_mod1[s57];break;    // rds_mod1                
        case 2:DACB.CH0DATA=rds_mod2[s57];break;    // rds_mod2         
        case 3:DACB.CH0DATA=rds_mod3[s57];break;    // rds_mod3         
    }
   

    if (change_send_group == 1)
    {
        change_send_group = 0;
        rds_data = Send_group_array[Send_group_counter];
        Send_group_counter = Send_group_counter + 0x01;
        if (Send_group_counter==Send_groups_num)
        {
            Send_group_counter=0x00;
            PORTE.OUT &= 0xfd;
        }
        if (Send_group_counter == 1)
        {
            PORTE.OUT |= 0x02;
        }
        if (Send_group_counter == 0x02) 
            flag_encode_stream_next = 1; 
    }
}

 

rds_mod0(1,2 or 3) is a table with 192 constant integers.

 

Thanks for your help

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In situations like this, it's nice if you tell us this crucial information up front rather than have us guess. I guessed at 19kHz as it is the fm pilot frequency and from that I guessed RDS. I might also be nice is you tell us the source of your code so we can read the whole thing rather than your abridged version of the facts.

 

I'd suggest you read up on the Xmega timer operation. Since I've never used an Xmega, I'm finding it hard to figure out how the numbers relate - eg 1187.5 times 192 = 228000. Divide your 4332000 by 19 gives you this. So I don't see how this relates to the timer values - unless the 4.332MHz is multiplied by the xmega pll. Just crunched some numbers at it might seem your 4.332MHz crystal is multiplied. As to why the divisor is changed I can only suggest it is to average out a beat with the 19kHz source.

 

if we multiply 4.332MHz by 7 we get 30.324MHz. Divide this by 133 we get 228000. Divide that by 192 we get 1187.5

 

Since the code cycles between 131,133,132,132 this averages to 132. There's probably a +1 for the timer compare to give us 133. You've tested the powers of my deduction.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dear Kartman, Thank you so much for your help. You were right. The Xmega clock is multiplied by 7 by the pll. So now All of the numbers make sense. Thanks so mush for your attention.

Last Edited: Sun. Jan 8, 2017 - 08:49 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dear Kartman, Do you have any idea about that why the timer period changed from 132 to 131, 133 and then 132 again? I think we could set timer period to 132 for all the time. Am I right?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would guess he is trying to compensate for a small error by changing the count by one on some cycles.

274,207,281-1 The largest known Mersenne Prime

Measure twice, cry, go back to the hardware store

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've already commented on the reason for the changing divisor. If you want a more specific answer you'll need to provide more information - like a schematic and the code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes I got that but I meant we can set the timer to 132 (It counts from 0 to 132, so 133 times), and then we can have a overflow every 133 times that the counter resets. I can't understand why it got an average between 132,131,133 and 132. The rest of the code isn't related to this part, so I don't think it can help.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes maybe you are right. It got an average for being sure about that the average overflow time is every 133 times. Thanks Torby. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The 19kHz is probably asynchronous to the xmega, thus you'll get a phase drift due to the slightly different frequencies. Normally you'd use a phase locked loop to eliminate this so I guess ( and i mean guess as i have little evidence to work from) the changing of the divisor is to introduce some 'wiggle' into the system.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Kartman for your help.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you using timer as counter? Does it count propperly? Cause i try it and it's not counting propperly. when i give 192Khz pwm then it shows ~188000Hz

and little bit floating, and when i give for example triangle 22Khz it shows like 2x more, or something not to close. But it definetly counting, something...

I know frequencys cause i have Atmega16 frequency counter and work pretty great. And atmega settings are very simple.

Settings for xmega are strange.

There is propably problem with hardware rising/falling recognition.

These are settings for xmega128a3:

  Config Tcd1 = Normal , Prescale = 1024
         Tcd1_per = 39063                                 '1/sec for 40Mhz clock src
      On Tcd1_ovf 1sec
  Enable Tcd1_ovf , Lo

Config Event_system = Dummy , Mux0 = Portc.3  'pin of signal'

' 'Config Tcc0 = Normal , Prescale = E0 , Event_source = E0 , Event_action = Freq  

Tcc0_ctrla = &B00001000  'E0 event                                 
Tcc0_ctrlb = &B10000000
Tcc0_ctrld = &B10100000
Tcc0_intctrla = &B00000001 'Low level int
Tcc0_intctrlb = &B01000000  
Tcc0_per = 0
On Tcc0_ovf inrease
Enable Tcc0_ovf , Lo
Enable Interrupts
Do
loop

1sec:     'every 1 second int'                                     
 'Stop Tcd1
 'Stop Tcc0

Frq = Frq * 2 
  Frq = Frq + Tcc0_cnt
  
   Frq = 0 
Tcc0_cnt = 0 
 'Start Tcd1
 'Start Tcc0 
Return


Count: 
Frq = Frq + 1 'increasing counter'
Return

This is bascom but i guess it is clear. Anything i do i get only bad results.

 

I was also doing this in a simple way, there was no overflow, just Interrupt on pin was going to "Count:" interrupt and when 1 second passed it was showing the result.

It was working in the same way...also was counting bad in lower frequencys.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, apparently pull ups not pull down helped. But it need adjusted timer to little bit more than 2Hz reading (and multiplying the result by 2).

Thats the code if you will:

 Dim Freq_result As Long
 Dim Frq As Long
 
 Const Licznik_per = 19910  'for 40Mhz, should be 19532'
 
   Config Tcd0 = Normal , Prescale = 1024
         Tcd0_per = Licznik_per                                 '2/sec
      On Tcd0_ovf 2sec 'jump to twice a second'
  Enable Tcd0_ovf , Lo
  
      Portc_pin3ctrl = &B00111010  ' thats the pin config pullups and falling edge'
      
      Config Event_system = Dummy , Mux0 = Portc.3 , Mux2 = Tcc0_ovf

 Config Tcc0 = Normal , Prescale = E0 , Event_source = E0 , Event_action = Capture , Resolution = 16

 Tcc0_per = 0
 On Tcc0_ovf count 'pulses'
 Enable Tcc0_ovf , Lo
 
Enable Interrupts

Do
Loop

2sec: 
 Stop Tcc0

 Frq = Frq * 2 
  Freq_result = Frq + Tcc0_cnt
 
'here jump to reading or put results in other variable

 Frq = 0
 Tcc0_cnt = 0 
 Start Tcc0 
Return


Zlicz:
Incr Frq         '' = Frq + 1''
Return

For some reason tcc0_cnt is always 0. Have no idea how this timer works.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dear ItCrowd, sorry for the delay. This timer is like a counter in my code; it counts to 132 and then returns to 0. I don't know much about this timer but this is my code which works well:

this is the initialization of the timer: 

 

void te0_init(void) 
{
    TCE0.CTRLE = 0x01;         // set timer in 8bit mode (default is 16 bits)
    TCE0.INTCTRLA = 0x02;     // Interrupt Enable register A (enable INT for tc0 (medium level))
    TCE0.PER = 132;                // set period to 228 khz
    TCE0.PERBUF = 132;         // buffer for writing to TCE0.PER.

    TCE0.CTRLA = 0x01;         // clk=30324000 H
}

 

This is my interrupt routine:

 

interrupt[TCE0_OVF_vect] void timer_int0_isr(void) 
{...}

 

This interrupt invokes every 132 times (timer PER value) in my code. You can check your code by the timer interrupt. You can for example,  increment a variable in this interrupt routine to check whether or not the timer triggers the corresponding interrupt.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks i will try that settings.