Interrupt-Routine zu langsam

Gast #150145
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
Gast #150146
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
Gast #150148
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?
Gast #150149
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...
Gast #150151
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
Gast #150153
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
Gast #150155
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
Gast #150156
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.
Gast #150157
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.
Gast #150158
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren