mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Interrupt-Routine zu langsam


Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich möchte Daten empfangen, die während eines Clocksignals von einem
anderen Baustein übetragen werden. Der Controller ist ein At90S2313 und
ich programmiere ihn mit Codevision C-Compiler. Das Clocksignal wird von
dem Baustein generiert. Zur Zeit arbeite ich mit einem externen
Interrupt, der zur steigenden Flanke des Colocksignals auslöst. In der
Interrupt-Routine wird dann den Port abfragt und das Ergebnis in ein
Array geschrieben(0 oder 1).
Die Routine arbeitet allerdings zu langsam, so daß Daten verloren
gehen.
Gibt es eine Möglichkeit, die Routine zu beschleunigen? Ist es
überhaupt sinnvoll einen Interrupt so einzusetzen?
Gruß Daniel

Autor: dave (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In welchem Verhältnis stehen denn die "ankommende Frequenz" und die
Taktfrequenz?

Inline Assembler oder ganz einfache Operationen beschleunigen sicher.
Sobald du irgendwas mit dem Array machst (Berechnungen, Verschieben
etc.) muss das ausgelagert werden.. meiner Meinung nach.

Notfalls einfach in die ISR eine Bool an oder aus machen... an = bit
abholen, aus = kein bit abholen.. und das dann in der Main abhandeln.

dave

Autor: Michael Wilhelm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hört sich irgendwie nach einer Software I2C Routine an. Such mal ein
bischen im Forum, wurde schon oft beschrieben.
MW

Autor: Uwe Große-Wortmann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wenn C zu langsam ist bliebe noch die möglichkeit, (zumindestens in der
interruptroutine) auf assembler umzusteigen. denn nur so kann man die
maxiamle geschwindigkeit des avrs ausnutzen. ein compiler muss immer
kompromisse zu lasten der geschwindigleit eingehen, da er für sämtliche
fälle ein funktionerende lösung liefern soll. wenn du direkt in
assembler programmierst, kansst du selbst entscheiden, welcher befehl
nötig ist und was in deinem speziellen fall weggelassen werden kann.

wie hoch ist in etwa die frequenz des taktsignals, und wieviele daten
müssen dabei eingelesen und gespeichert werden?

Autor: Aleksej Kiselev (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
The automatic saving and restoring of registers R0, R1, R15, R22, R23,
R24, R25, R26, R27, R30, R31 and SREG, during interrupts can be turned
on or off using the #pragma savereg directive.

So was steht in Gebrauchanleitung von CodeVision, wenn du diese
automatische Speicherung abschaltest, bringt es dir ein Ersparnis von
mindestens 26 Befehlen.
Wenn es doch nicht ausreichend wird, dann hilft nur Assembler...

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ganau das wird die Lösung sein.
Listing anschauen, welche Register in der ISR wirklich gebraucht werden
und nur diese sichern. Allerdings aufpassen bei Programmänderungen.

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für eure Antworten.
Es handelt sich nicht um I2C. Die Taktflanke kommt ca alle 60us und die
Taktfrequenz ist 9,216MHz. #pragma savereg hatte ich schon eingebaut.
Mit Assembler kenne ich mich leider nicht wirklich gut aus.

Der Inhalt meiner Interruptroutine (Sichern einiger Register ist
natürlich auch noch enthalten)ist dieser:

if (PIND.4 == 1)
{messung[i]='1';}
else
{messung[i]='0';
}
TCNT0=0;
i++;

Könnte mir das jemand in Assembler übersetzen? Das Array kann auch vom
Typ Bit sein.
Wäre prinzipiell eine Routine ohne Interrupt schneller?
Daniel

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wie gross ist denn messung[x]?

Autor: wb1 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du ein Array aus 8 bit hast, kann es so aussehen:

.def temp = r16
.def temp1 = r17
Einsprung_von_interrupt:
sbis pind,0     ;teste bit0 und ueberspringe befehl wenn wenn pind,0=1
sbr temp,1  ;setze im register temp bit 0 auf 1
rol temp  ;rotiere nach links
clr temp1  ;lade temp 1 mit 0
out tcnt0,temp1  ;schreibe temp1 nach tcnt0
reti

Das sind inclusive interruptaufruf, sprung zur Serviceroutine und
Interruptruecksprung 24 Takte.
Bei 9,2 MHz also 2,6 ex-6 Sekunden

Autor: wb1 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Entschuldigung
Im temp ist jetzt der Kehrwert von pind,0
statt sbis pind,0 muss es sbic pind,0 heissen.
Dann herrscht wieder Gleichlauf

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ehe Du überhaupt anfängst zu programmieren, mußt Du erstmal wissen, wie
lang der Impuls an PIND.4 nach der Taktflanke stabil anliegt.

Da die Impulse ale 60µs kommen dürfte das arg wenig sein.

Dann kannst Du ausrechnen, wieviel CPU-Zyklen Du Zeit hast und ob
überhaupt eine minimale Chance besteht.

Ein leerer Interrupt kostet ja schon 10 Zyklen.

Andere Interrupts kannst Du getrost vergessen.

Der AVR ist für schnelle Interrupts schlecht geeignet, da er keine
Interruptprioritäten unterstützt.


Peter

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es sollen ca. 90 Bits empfangen werden. messung[90]. Habe den Takt
gerade noch mal genau gemessen. Der Takt steht ca. 75us stabil an, die
Taktflanke kommt nach 150us wieder. Wie lange sollte der Takt denn
stabil anstehen? Nach einigen Modifikationen wird meistens auch nur 1
Bit registriert. Gestern vormittag waren es noch ca. 20 Bits.
Danke für den Assemblercode, werde ihn probieren.

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich sehe keinerlei Probleme, 75µs Signale sauber zum empfangen, auch
wenn alle Register gerettet würden. Allerdings sollte die INT-Routine
nur empfangen und nicht noch 'rumtüddeln'. Das kann man Deinem Code
aber nicht ansehen.

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es läuft jetzt einwandfrei!!!
Sogar ohne Assembler, nur #pragma savereg- und manuelles Sichern
einiger Register. Hab Verzögerungsschleifen in die Interruptroutine
eingebaut. Hab den Eindruck, sie ist zu schnell durchgelaufen.
Irgendwie schon seltsam, aber hauptsache es geht jetzt.
Vielen Dank an alle.
Gruß Daniel

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Hab Verzögerungsschleifen in die Interruptroutine eingebaut. "

Bitte nicht ! Hast Du vielleicht die falsche Flanke erwischt ?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.