Forum: Mikrocontroller und Digitale Elektronik AT xmega 16A4 - Problem mit Timerinterrupt Zeiten


von Senna Hoj (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen.

Ich bin gerade dabei einen xmega16A4 zu programmieren. Nun bin ich 
allerdings auf ein Problem gestoßen, für dass ihr (hoffentlich) eine 
Lösung wisst.

Ich habe mal ein sehr abgespecktes Miniaturbeispiel angehängt. In diesem 
Bsp möchte ich einfach "nur" in einer Timerinterrupt-Routine alle 6,25µs 
(160kHz) eine Variable hoch zählen lassen. Funktioniert alles wies soll. 
Bei Messung der Zeiten sehe ich aber, dass für Sicherung der 
Rücksprungadresse genau soviel Zeit eingenommen wird, wie der 
eigentliche Interrupt selbst (beim zurück laden das gleiche). Wenn ich 
in meiner Interrupt-Routine nun noch mehr verarbeiten will, reicht meine 
Zykluszeit von 6,25µ nicht aus, da jeweils 1µs zum Sichern (push) und 
Rücksichern (pop) der Register "vergeudet" werden. Habe den 
Assembler-Code für den Interrupt nochmal eingefügt.

Kann das irgendwie geschickter gelöst werden?
1
ISR(TCC0_OVF_vect){
2
 226:  1f 92         push  r1
3
 228:  0f 92         push  r0
4
 22a:  0f b6         in  r0, 0x3f  ; 63
5
 22c:  0f 92         push  r0
6
 22e:  11 24         eor  r1, r1
7
 230:  8f 93         push  r24
8
 232:  9f 93         push  r25
9
 234:  ef 93         push  r30
10
 236:  ff 93         push  r31
11
  PORTE.OUTSET = 0x01;
12
 238:  e0 e8         ldi  r30, 0x80  ; 128
13
 23a:  f6 e0         ldi  r31, 0x06  ; 6
14
 23c:  81 e0         ldi  r24, 0x01  ; 1
15
 23e:  85 83         std  Z+5, r24  ; 0x05
16
  
17
  // Zählt von 0 bis 31
18
  ui8_signal_counter++;
19
 240:  90 91 02 20   lds  r25, 0x2002
20
 244:  9f 5f         subi  r25, 0xFF  ; 255
21
  ui8_signal_counter &= 0x0F;
22
 246:  9f 70         andi  r25, 0x0F  ; 15
23
 248:  90 93 02 20   sts  0x2002, r25
24
25
  PORTE.OUTCLR = 0x01;
26
 24c:  86 83         std  Z+6, r24  ; 0x06
27
}
28
 24e:  ff 91         pop  r31
29
 250:  ef 91         pop  r30
30
 252:  9f 91         pop  r25
31
 254:  8f 91         pop  r24
32
 256:  0f 90         pop  r0
33
 258:  0f be         out  0x3f, r0  ; 63
34
 25a:  0f 90         pop  r0
35
 25c:  1f 90         pop  r1
36
 25e:  18 95         reti

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Lass den XMega doch mit 32Mhz laufen. Ein Cycle sind dann 31.25 nSec.

von Senna Hoj (Gast)


Lesenswert?

Ich lasse den schon mit 32MHz laufen, zumindest glaub ich das oder?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Aus der Kiste läuft der XMega erstmal mit dem internen 2 Mhz Oszillator. 
Zähl doch mal die Zyklen, ob das passt. Für die 32 Mhz auf meinem 128A3:
1
// Configure XMega Clock 
2
// clock system @ 32Mhz , PERCLK is 16 Mhz
3
void ConfigClockSystem( void )
4
{
5
  /* Start internal 32MHz RC oscillator. */
6
  OSC.CTRL = OSC_RC32MEN_bm;
7
8
  do {
9
    /* Wait while oscillator stabilizes. */
10
  } while ( ( OSC.STATUS & OSC_RC32MRDY_bm ) == 0 );
11
12
  /* Enable prescaler B div 1 and C to div by 2 */
13
  CCP = CCP_IOREG_gc;
14
  CLK.PSCTRL = (CLK_PSADIV_1_gc | CLK_PSBCDIV_1_2_gc);
15
16
  /* Select 32 MHz as master clock. */
17
  CCP = CCP_IOREG_gc;
18
  CLK.CTRL = CLK_SCLKSEL_RC32M_gc;
19
20
}

von Senna Hoj (Gast)


Lesenswert?

Wenn ich deine Clock Init verwende halbiert sich meine Takt auf 80kHz 
statt auf 160kHz wegen dem "CLK_PSBCDIV_1_2_gc". Kommentiere ich das 
aus, läuft der wieder so wie bei mir.

Habe mir auch schonmal meinen Takt an nem Pin ausgegeben... das kommen 
schon 32MHz raus.

Das einzige was sein könnte, dass die Timer Peripherie langsamer 
angesteuert wird, aber ich wüsste nicht wo.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Check mal die peripheren Clocks. Ich hab hier nur A1 und A3 , der A4 
könnte da auch wieder anders sein. Allerdings wäre das Hochzählen mit 
dem Eventsystem transparent ohne jede CPU Belastung zu machen. Du 
müsstest ja nur mit dem 6,25 uS Timer einen anderen hochzählen.

von Senna Hoj (Gast)


Lesenswert?

Meinen Timer Clock habe ich auf "TCC1.CTRLA = TC_CLKSEL_DIV1_gc" also 
"Prescaler: clk"

Mein Problem liegt wahrscheinlich nicht in der Geschwindigkeit des Chip, 
sondern dass der µC die Register nicht direkt adressieren kann und immer 
in einen Zwischenspeicher laden muss, wodurch diese vielen Push und Pop 
Befehle entstehen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.