Forum: Mikrocontroller und Digitale Elektronik IAR Interrupt


von Steffen (Gast)


Lesenswert?

Hallo.

Ich habe eine Interruptroutine, die mit 125 kHz aufgerufen wird.
Controller ist ein Mega8515 mit 16 MHz. Programmiert wird die Software
im IAR Workbench.

Meiner Rechnung nach, habe ich ca. 180 (abzüglich dem Interruptaufruf -
sagen wir mindestens 150) Taktzyklen zeit, damit die Interruptroutine
fertig wird, bevor erneut ein Interrupt auftritt.

Bei Versuchen (mit no operation Befehlen aufgefüllt), bin ich gerade
auf 43 Taktzyklen gekommen - das ist mir aber zu wenig.

Wozu verwendet IAR die restlichen Taktzyklen (zum Sichern von
Registern?). Wie kann ich das einschränken, dass ich hier mehr Zeit
bekomme?

Vielen Dank für eure Hilfe
Steffen

von Michael (Gast)


Lesenswert?

Wenn du unter den Compiler- und Linkerdirektiven die Listings
aktivierst, bekommst du ein *.map-File. Darin kannst du sehen wieviel
pushes und popps im Programm sind. Weiterhin optimiere auf Speed und
spiel etwas mit den Parametern.

Michael

von Steffen (Gast)


Lesenswert?

Hallo!
Danke für deine Antwort.
Das steht in der Mapdatei zum Interrupt:

CODE
  Relative segment, address: CODE 00000028 - 0000008B (0x64 bytes),
align: 1
  Segment part 37.            Intra module refs:   Segment part 22
           ENTRY                   ADDRESS         REF BY
           =====                   =======         ======
           Timer0_CompA            00000028
               interrupt, non_banked function
               stack 1 = 00000000 ( 00000002 )
               stack 2 = 00000000 ( 00000002 )

Ich kann leider nicht allzuviel damit anfangen.

Wenn ich auf Speed optimiere - treten bei Low seltsame Effekte auf (er
zählt falsch mit) und bei Mid und High geht die Ausgabe im Interrupt
gar nicht mehr ...

Welche Sachen brauchen denn da so viele Taktzyklen?
Steffen

von Michael (Gast)


Lesenswert?

1. Was für eine Version von IAR benutzt du?
2. Im *.lst File mußt du bei entsprechender Einstellung deinen C-Code
sehen und parallel dazu den vom Compiler erzeugten Code. Darin siehst
du auch deine Interrupt-Routine incl. pushes und popps. Was du mir im
*.map File gezeigt hast, stimmt erst einmal mit deinen vermutungen
überein. Die Größe Hex 64 sind Dez 100.

Michael

von Steffen (Gast)


Angehängte Dateien:

Lesenswert?

Hallo!

Ich verwende die Version 3.20.1.5. Sollte eigentlich das neuste Update
sein.

Ich hab die Interrupt Routine aus dem LST File mal in den Anhang
gestellt - in der ganzen Datei befindet sich kein einziges push oder
pop ...

Viele Grüße & danke!!
Steffen

von Peter D. (peda)


Lesenswert?

Stimmen die 125kHz denn ?

Was macht Dein Hauptprogramm ?


Peter

von Steffen (Gast)


Lesenswert?

Mein Hauptprogramm macht nichts während dessen - Endlosschleife.

Ok, ich merke gerade, dass ich einen kleinen Denkfehler habe. Ich lasse
mittels des Compare Mode den OCA1 toggeln und den Interupt auslösen. Das
Rechtecksignal hat eine Frequenz von 125 kHz. Dh. dann wohl aber, dass
der Interrupt eine Frequenz von 250 KhZ hat - wo ich dann bei 64
Taktzyklen pro Interrupt liege. Das dürfte wohl eher hinkommen, oder?

Ich werde jetzt versuchen die 125 KHz mit dem Timer 0 zu erzeugen. Dann
sollte ich ja mehr Zeit haben ...

Grüße
Steffen

von Steffen (Gast)


Lesenswert?

Jetzt sieht es schon besser aus. Aber ich habe dennoch ein kleines
Problem:

Timer0 wird so initialisiert:

TCCR0 =   0x02; // Prescaler 8
TCNT0 =   0xf1;

Wenn ich nun in der Interruptroutine einen Impuls auf PORTB ausgeben
lasse und eine 16 bit Interger Variable inkrementiere, liegt die
Frequenz der Impulse laut Oszi beu 117,6 kHz. -> ich brauche aber genau
125 kHz.

Das Assemblerfile sagt, dass ich etwas 40-50 Taktzyklen brauche um die
nötigen Dinge in der Interruptroutine abzuarbeiten. Ich habe aber
mindestens 90 Taktzyklen Zeit - wo liegt jetzt schon wieder das
Problem?

Für eine kleine Idee zur Lösung wäre ich sehr dankbar.

Grüße
Steffen

von Steffen (Gast)


Lesenswert?

Ok - ich stell meine Frage nochmal anders - mit den Informationen, die
ich bisher rausgekriegt habe:

Ich habe einen Timer1 Compare Match - der toggelt OCA1 mit 250 kHz - so
dass ein Rechtecksignal mit einer Frequenz von 125 kHz entsteht.

Zusätzlich habe ich einen Timer0 Overflow, der einen Interrupt aufruft
mit 125 kHz. Dieser Interrupt erzeugt an PB0 einen kleinen Impuls.

Wenn ich beide Signale an einem 2 Kanal Oszi darstelle sollten
eigentlich beide Signale 'stehen' - also in Bezug aufeinander immer
an der selben Stelle auftreten.
Das tun sie auch solange, bis ich einen weiteren Befehl in die
Interruptroutine einfüge:
count ++;

count ist eine Integervariable. Nun verschieben sich die Signal und
eines von beiden läuft ... (je nachdem, mit welchem Signal getriggert
wird). Mein erster Gedanke: die Funktion braucht zu viel Zeit - die
folgenden Interrupts werden verzögert.

Den Befehl rausgelöscht und 35 Mal ein no operation eingefügt - siehe
da. es funktioniert wieder. Im Assemblerlisting nachgeschaut. Der
Befehl count ++; benötigt 12 Taktzyklen. Also eigentlich bedeutend
weniger ...

Dennoch wird mit dem Inkrementieren von Counter die Frequenz des Timers
auf ca. 117 kHz zurückgesetzt. Das erklärt das Laufen - aber wieso
schafft der AVR die Befehle nicht innerhalb der Interruptroutine?

Danke für Eure Mühe und Hilfe!!
Steffen

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.