Forum: Mikrocontroller und Digitale Elektronik Interrupt UART und normaler SPI


von mager (Gast)


Lesenswert?

Hallo,

ich habe mir einen UART mit Interrupts geschrieben der single bytes 
sendet/empfängt und einen SPI der ganze Strings lesen kann.

Problem ist jetzt natürlich, dass mein SPI ewig alles blockiert.

Sollte ich mir die Zeit nehmen und meinen SPI mit Interrupts aufbauen?

Ich bekomme ja einen Interrupt, wenn die Übertragung komplett ist.
Dann wird ja SPIF gesetzt. Aber es wär ja blöd dieses Bit abzufragen.

Welche adresse hat dann der Interruptvector? 0x0022?

Sorry, falls die fragen zu doof sind.

von Peter II (Gast)


Lesenswert?

mager schrieb:
> Welche adresse hat dann der Interruptvector? 0x0022?

ohne zu wissen um welchen µC es sich handelt wird es schwer hie weiter 
zu helfen.

von mager (Gast)


Lesenswert?

Seite 57 im Datenblatt des Atmega64

"0x0022 SPI, STC SPI Serial Transfer Complete"

mach ich dann:
1
#define SPI_INTERRUPT 0x0022
2
3
und dann?
4
5
IST(SPI_INTERRUPT)

von mager (Gast)


Lesenswert?

Perdon..
1
ISR(SPI_INTERRUPT)
2
{
3
4
}

von Peter II (Gast)


Lesenswert?

mager schrieb:
> mach ich dann:#define SPI_INTERRUPT 0x0022

das sollte doch schon alles von jemand gemacht wurden sein. Das braucht 
man nicht selber zu machen! Das steht in einer der include dateien für 
den µC mit drin.

von mager (Gast)


Lesenswert?

Ok, das wäre schön.

Aber wo finde ich es und wie füge ich es ein?

von mager (Gast)


Lesenswert?

Im iom64.h
1
/* SPI Serial Transfer Complete */
2
#define SPI_STC_vect_num    17
3
#define SPI_STC_vect      _VECTOR(17)
4
#define SIG_SPI        _VECTOR(17)

von mager (Gast)


Lesenswert?

Es heißt ja "Transfer complete", wird dann die ISR aufgerufen wenn ich 
ein byte gesendet habe oder wenn ich eines empfangen habe? Oder beides?

Im Master Modus lese ich ja mit einem Dummy byte, dann löst er doch den 
Interrupt auch aus.

von Thomas E. (thomase)


Lesenswert?

mager schrieb:
> Perdon..
>
>
1
> ISR(SPI_INTERRUPT)
2
> {
3
> 
4
> }
5
>

Also wenn das C sein soll, dann überlass es deinem Compiler, sich um den 
Interruptvektor zu kümmern.
Du schreibst nur:
ISR(SPI_STC_vect)
{

}
Und gibst die Interrupts frei.

> Ok, das wäre schön.
> Aber wo finde ich es und wie füge ich es ein?
Das wird dir auf einem silbernen Tablett beim Erstellen deines Projektes 
serviert. Darum brauchst du dich überhaupt nicht zu kümmern. Du solltest 
alerdings mal das GCC-Tutorial durcharbeiten. Oder was für einen Exoten 
von Compiler verwendest du?

> Es heißt ja "Transfer complete", wird dann die ISR aufgerufen wenn ich
> ein byte gesendet habe oder wenn ich eines empfangen habe? Oder beides?
Kannst du dir aussuchen. Wenn der Spi-Clock 8 mal gewackelt hat, ist die 
Übertragung fertig. Dann gibt es einen Interrupt. Senden und Empfangen 
passiert dabei gleichzeitig. Und Master oder Slave ist auch egal.

mfg.

von Peter D. (peda)


Lesenswert?

Schau mal in das Datenblatt Deines AVR.
Dort steht eine Tabelle mit den Interruptnamen.
Leerzeichen ersetzt man durch _ und hinten fügt man ein _vect an, fertig 
ist der Vector-Name.
Und dann noch:
1
#include <avr/io.h>

von mager (Gast)


Lesenswert?

Ok das hab ich jetzt ein für alle mal abgespeichert, danke für die 
Antworten.



Nun zur wichtigsten Frage, ich bin immer Master. Dann bringt mir ja der 
Interupt eigentlich gar nichts oder?

von Thomas E. (thomase)


Lesenswert?

mager schrieb:
> Nun zur wichtigsten Frage, ich bin immer Master. Dann bringt mir ja der
> Interupt eigentlich gar nichts oder?
Kommt drauf an. Wenn der Spi-Clock F_CPU/2 ist, dauert die Übertragung 
16 Takte. Die Ausführung eines Interrupts, das nächste Byte aus dem 
Buffer holen und ins Spdr schreiben dauert wesentlich länger. Da wartet 
man dann.
Anders sieht es natürlich aus, wenn die Peripherie nur eine wesentlich 
niedrigere Geschwindigkeit zulässt. Dann willst du bei F_CPU/256 nicht 
wirklich 4096 Takte auf der Stelle treten. Da macht der Interrupt wieder 
Sinn.

mfg.

von mager (Gast)


Lesenswert?

Ich hab jetzt schon einiges ausprobiert, weiß aber ehrlich gesagt nicht 
so recht, was ich in der ISR eigentlich machen soll.

Ich würde jetzt nur einen Buffer inkrementieren.

von Peter D. (peda)


Lesenswert?

mager schrieb:
> Problem ist jetzt natürlich, dass mein SPI ewig alles blockiert.

Sicher?
Wie hast Du festgestellt, daß genau das der Flaschenhals ist.

von mager (Gast)


Lesenswert?

Soll ich dann in der ISR ein Flag abfragen, also write und read? und 
dementsprechend die buffer inkrementieren etc?

Gibts dazu evtl ein beispiel?

Interrupt driven spi fand ich nichts passendes im web.

von Karl H. (kbuchegg)


Lesenswert?

mager schrieb:
> Soll ich dann in der ISR ein Flag abfragen, also write und read? und
> dementsprechend die buffer inkrementieren etc?

Was für ein Flag?

Beim SPI gibt es doch sowieso nur ein einziges Ereignis.
Der Transfer ist fertig.

Punkt.
Mehr gibt es da nicht. Wenn also der Interrupt kommt, dann weißt du, das 
das letzte zeichen komplett draussen ist (und im Gegenzug ein Zeichen 
von der Gegenseite rübergeschoben wurde). Was also wirst du machen?
Es gibt 2 Möglichkeiten
* entweder gibt es noch was zu transferieren, dann stopfst du das 
nächste
  Zeichen ins SPDR Register, damit das ebenfalls transferiert wird
* oder es gibt nichts mehr zu tun. IN dem Fall macht dann eben die ISR
  nichts.

Wo ist da jetzt das Problem?

>
> Gibts dazu evtl ein beispiel?

Wie wärs, wenn du mal selber ein wenig nachdenkst, was da eigentlich vor 
sich geht. Wie das SPI System funktioniert?

> Interrupt driven spi fand ich nichts passendes im web.

Googeln können ist wichtig. Aber noch wichtiger ist es, sich selbst mal 
ein bischen was zu überlegen.

SPI funktioniert so, wie wenn sich 2 Personen am Tisch gegenüber sitzen.
Jeder hat ein Kuvert, in welches er eine Nachricht stecken kann (die nur 
aus einer einzigen Zahl im Bereich 0 bis 255 besteht). Die eine der 
Personen ist der Master. Der hat das sagen.
Der Master nimmt sein Kuvert in die rechte Hand (genauso wie der Slave). 
Beide strecken nun ihre rechte Hand aus und schieben das Kuvert über den 
Tisch zum jeweiligen Gegenüber. Und zwar gleichzeitig. Der Master nimmt 
mit seiner linken das Kuvert vom Slave und der Slave nimmt mit seiner 
linken das Kuvert vom Master.
Damit ist der Datenaustausch vollzogen. Jeder der beiden (Master und 
Slave) können jetzt ins Kuvert schauen und nachsehen, was der jeweils 
andere mitteilt.
Aber Auslöser des Ganzen ist immer der Master. Der Slave kann seinen 
Namen tanzen wenn er will, das hilft nichts. Der Master ist der, der das 
sagen hat. Er beginnt damit den Kuvertaustausch anzustossen.

Jetzt kommen Interrupts ins Spiel. Der Interrupt wird genau dann 
ausgelöst, wenn das Kuvert komplett ausgetauscht wurde. Kunststück. Was 
anderes erwähnenswertes gibt es da ja auch nicht. Und das ist jetzt der 
Punkt, an dem die Ehefrau ins Spiel kommt (das Hauptprogramm in Form der 
ISR). Sobald der Master das Kuvert hat, läutet eine Glocke, die Ehefrau 
tritt hinzu und macht, was immer sie für richtig hält. Sie kann sich 
ansehen was im Kuvert stand, sie kann dem Master auftragen, dass er was 
neues ins Kuvert schreiben und rüberschieben soll, sie kann aber auch 
nichts dergleichen tun. Je nachdem.

Zack: Das ist im wesentlichen SPI. Mehr ist da nicht. Es gibt kein 
dezidiertes 'Senden'  oder 'Empfangen'. Die beiden SPI Teilnehmer 
tauschen Bytes aus, wobei der Master der ist, der alles anstösst und 
taktet.

Und aus dieser Basisfunktionalität musst du jetzt eben was machen, so 
das du die Funktionalität kriegst, die du brauchst. Der grundlegende 
Transfermechanismus ist da, alles weitere ist jetzt dein Bier.

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.