Forum: Mikrocontroller und Digitale Elektronik AVR Interrupts "kaskadieren"


von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Hallo zusammen,

sorry für den vielleicht unpassenden Betreff, aber mein Problem ist 
etwas schwer in drei Wörter zu kleiden....

ich möchte einen ATmega 328 mit einem ADC (ADS1248) über SPI sprechen 
lassen. Da ich etwas beengt an freien Signalen bin, habe ich eine 
4-Draht-Verbindung: DIN/MOSI, DOUT/MISO, SCLK und CS.

Der ADS hätte eigentlich noch ein DRDY (Data Ready) Signal, welches er 
auf Low zieht sobald die A/D-Konvertierung fertig ist und Daten 
abzuholen wären. Es gibt aber einen speziellen Modus, wo statt DRDY der 
DOUT-Pin mit genutzt werden kann. Der ADC zieht (bei aktiviertem CS) 
also DOUT/MISO kurz auf high, um zu signalisieren dass Daten da sind.

Da ich mit einer recht geringen Wandlungsrate (~5 SPS) arbeiten will, 
und mein ATmega in der Zwischenzeit recht beschäftigt ist, möchte ich 
DRDY per Pin Change Interrupt überwachen. Nur - PCINT während der 
SPI-Übertragung ist dann wohl nicht so sinnvoll....

ich könnte natürlich in der PCINT-ISR gleich die SPI-Kommunikation 
abwickeln, aber das widerstrebt mir massiv.

SPI würde ich auch gerne über Interrupt abwickeln (ich mag Interrupts).

ich müsste also in der PCINT-ISR den interrupt-Handler "umschalten", und 
danach wieder zurückschalten.

Kriegt man das ohne massiven Knoten im Hirn hin, oder denke ich komplett 
verquert, und man macht das ganz anders?


vielen Dank, und einen guten Rutsch an alle die das lesen, Michi

von Hmm (Gast)


Lesenswert?

>Kriegt man das ohne massiven Knoten im Hirn hin, oder denke ich komplett
>verquert, und man macht das ganz anders?

Nein, nein. Das passt schon. Abgesehen von dem Knoten. Ich habe schon 
einen vom Lesen. :-)

Aber mal im Ernst: Das geht durchaus und ist auch nicht weiter 
geheimnisvoll.
Falls Du Probleme bekommst, frag' einfach hier.

von (prx) A. K. (prx)


Lesenswert?

PCINT Interrupt für diesen Pin erst einschalten, wenn das Kommando zur 
Konvertierung gegeben wurde und sich auf SPI nichts mehr tut. In der 
entsprechenden ISR dann wieder abschalten.

von Peter D. (peda)


Lesenswert?

Michael Reinelt schrieb:
> SPI würde ich auch gerne über Interrupt abwickeln

Eher nicht.
Ein SPI-Transfer dauert 16 CPU-Zyklen, das ganze Brimborium zum 
Interrupt betreten und verlassen dauert erheblich länger.
Mit Interrupt ist das SPI also deutlich langsamer.


Auch können von einer Ressource (SPI) nicht 2 Instanzen laufen. Also SPI 
entweder immer als Interrupt oder nie.


Peter

von Hmm (Gast)


Lesenswert?

Da hat Peter recht, sofern die einzelnen Bits per Interrupt eingelesen 
werden sollen.
Ich bin allerdings davon ausgegangen, das wir hier von dem SPI-RX 
interrupt bezogen auf einen kompletten Frame geredet haben. Zumindest 
würde das zu der Aussage:

>ich könnte natürlich in der PCINT-ISR gleich die SPI-Kommunikation
>abwickeln, aber das widerstrebt mir massiv.

passen.

Das könntest Du mal klarstellen, Michael.

von Hmm (Gast)


Lesenswert?

Also Peter, Du bist ausgewiesenermaßen ein Crack, aber das hier

>Auch können von einer Ressource (SPI) nicht 2 Instanzen laufen. Also SPI
>entweder immer als Interrupt oder nie.

verstehe ich nicht.

Man kann doch erstmal den Pin-Change interrupt benutzen um das 
Ready-Signal zu erkennen und dann den Pin-Change Interrupt wieder 
deaktivieren und stattdessen die SPI-Mimik aktivieren. Und nach der 
Übertragung wieder andersherum.

von Peter D. (peda)


Lesenswert?

Das SPI darf nicht gleichzeitig im Main und im Interrupt benutzt werden 
(2 Instanzen).
Die SPI-Pakete würden sich gegenseitig zerstören.

Das SPI ist nicht reentrant, sowie alle andere HW-Peripherie auch.

Man müßte einen speziellen Devicetreiber implementieren, wie z.B. auf 
dem PC zu Schreiben mehrerer Streams auf eine Festplatte.

Peter

von Hmm (Gast)


Lesenswert?

Tut mir leid, Peter, ich muss Dich um ein wenig Geduld mit mir bitten, 
aber ich verstehe Dich immer noch nicht.

Du setzt voraus, dass

>...gleichzeitig im Main und im Interrupt benutzt...

wird. Warum setzt Du das voraus?

So, wie ich das verstehe, geht es doch nicht darum, gleichzeitig von 
zwei Stellen im Code SPI-Pakte zu senden.

Vielmehr soll an einem Pin der bei SPI Betrieb MISO ist, eine 
Pegeländerung erkannt werden und erst dann SPI aktiviert werden, nachdem 
der Pegeländerungs-Interrupt deaktiviert worden ist.

Ich schreibe das mal als Pseudo-Code.
1
main:
2
   Aktiviere SPI
3
   Sende Wandlungs-Start
4
   Deaktiviere SPI
5
6
   Aktiviere PIN_CHANGE_INT
7
   while (!PIN_CHANGE_INT);
8
   // evtl. auch hier deaktivierung von PIN_CHANGE_INT und aktivierung der SPI
9
10
   while (!SPI_RX);
11
   Speichere ADC Resultat
12
13
   goto MAIN
14
15
SPI_RX_INT:
16
   Setze SPI_RX flag
17
18
PIN_CHANGE_INT:
19
   Deaktiviere PIN_CHANGE_INT
20
   Aktiviere SPI_RX_INT (und was sonst noch dazu gehört)

Vielleicht magst Du Deinen Gedankengang mal etwas ausführlicher und im 
Kontrast mit meinem Ansatz erklären.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Peter Dannegger schrieb:
> Ein SPI-Transfer dauert 16 CPU-Zyklen, das ganze Brimborium zum
> Interrupt betreten und verlassen dauert erheblich länger.

Mit Transfer meinst du 8 Bit, richtig? 16 Zyklen stimmt aber nur, wenn 
die Gegenseite entsprechend schnell kann. Laut Datenblatt verträgt der 
ADS1248 500 ns SCLK-Takt, also 2 MHz. Da die Verbindung über ein (wenn 
auch kurzes) Flachbandkabel geht, bin ich (noch) nicht sicher ob ich 
nicht mit dem SPI-Takt runter muss. Dann wären es entsprechend mehr 
Takte, richtig?

Hmm schrieb:
> Da hat Peter recht, sofern die einzelnen Bits per Interrupt eingelesen
> werden sollen.
> Ich bin allerdings davon ausgegangen, das wir hier von dem SPI-RX
> interrupt bezogen auf einen kompletten Frame geredet haben. Zumindest
> würde das zu der Aussage:
>
>>ich könnte natürlich in der PCINT-ISR gleich die SPI-Kommunikation
>>abwickeln, aber das widerstrebt mir massiv.
>
> passen.
>
> Das könntest Du mal klarstellen, Michael.

Ich meinte damit, direkt in der PCINT-ISR die SPI-Kommunikation 
abzuwickeln (mit busy-waiting und so), dann aber ohne SPI-Interrupts.

Der pseudo-Code passt halbwegs zu meinem Vorhaben, allerdings sollte die 
main-loop "unwichtig" sein, da diese durchaus mal mehrere 100 msec 
"busy" sein kann. Damit scheidet Polling einigermaßen aus.

ich müste wirklich in der PCINT-ISR die Kommunikation vorbereiten, in 
der ISR den PCINT deaktivieren und den SPI-Interrupt aktivieren, sodass 
mehr oder weniger nahtlos die SPI-Kommunikation interrupt-gesteuert 
losgeht. Innerhalb der SPI-ISR müsste das Ende des SPI-Transfers sauber 
erkannt werden, der SPI-Int deaktiviert und der PCINT wieder aktiviert 
werden. Genau dieser teil bereitet mir Sorgen, dass er hier irgendwie 
hängenbleibt. Andererseits: soweit ich SPI verstehe, gibts hier keinen 
"Receiver Mode" wie bei I2C, sondern empfangen tut der master nur 
während er sendet. Es kann also kein empfangendes Bit "verlorengehen", 
sodass der Master ewig im Empfangsmodus hängen bleibt.....

irgendwie viel Neuland für mich für einen Tag. Immerhin hab ich heute 
meine erste doppelseitige Platine geätzt, und meinen ersten TSSOP28 
aufgelötet. Ich denke das reicht erstmal für ein Belohnungsbier :-)

lg Michi

von Fabian O. (xfr)


Lesenswert?

Auch wenn Du den SPI-Takt auf 1 MHz senkst dürfte sich SPI per Interrupt 
nicht lohnen. Du musst ja in der SPI-ISR eine Art State-Machine 
verwalten, um zu unterscheiden, welche Bytes übertragen bzw. wo die 
Daten gespeichert werden.

Per Polling ist der Programmfluss wesentlich besser nachzuvollziehen und 
Du sparst Dir den Overhead für die Zustandsverwaltung und 
SPI-Interrupts. Selbst wenn man (bei niedriger SPI-Frequenz) ein paar 
Takte noch was für was anderes statt Polling nutzen könnte, lohnt sich 
der Aufwand nicht. Vor allem wenn Du eh nur 5 Samples pro Sekunde messen 
willst, da fällt die SPI-Übertragungszeit überhaupt nicht ins Gewicht.

von Hmm (Gast)


Lesenswert?

>>>>ich könnte natürlich in der PCINT-ISR gleich die SPI-Kommunikation
>>>>abwickeln, aber das widerstrebt mir massiv.
>>>
>>> passen.
>>>
>>> (Auslassung durch mich)

>>Ich meinte damit, direkt in der PCINT-ISR die SPI-Kommunikation
>>abzuwickeln (mit busy-waiting und so), dann aber ohne SPI-Interrupts.

>Ich meinte damit, direkt in der PCINT-ISR die SPI-Kommunikation
>abzuwickeln (mit busy-waiting und so), dann aber ohne SPI-Interrupts.
>Möglicherweise ein Missverständnis.

Wohl ein Missverständnis: Die Phrase "ich könnte" habe ich so gedeutet, 
das Du das nachfolgende eigentlich nicht tun willst. Was Du inhaltlich 
mit dem darauf folgenden meintest war schon klar.

Falls Du das aber doch so machen willst, dann passt mein Pseudo-Code 
überhaupt nicht.

Der wesentliche Unterschied ist folgender:
1. Entweder handelst Du den SPI-Transfer per Hardware ab und der 
Interrupt tritt nach dem Ende eines kompletten Transfers auf. Das meine 
ich mit SPI-Interrupt und darauf bezieht sich mein Pseudocode.
2. Oder Du überträgst die Bits einzeln. Dann aber handelt es sich 
strenggenommen nicht um einen SPI-Interrupt (der wird nämlich von der 
SPI-Hardware ausgelöst) sondern um einen Timer-Interrupt. Du bist ja der 
Master, musst also den Takt erzeugen.

Eine Unklarheit im Ablauf kann es da eigentlich nicht geben da ja 
entweder Du oder die SPI-Hardware den Takt erzeugst, also auch weisst ob 
schon alle Bits übertragen wurden. Auch die von Peter unterstellte 
Doppelnutzung der SPI-Hardware tritt bei beiden Varianten nicht auf.

Es mag ja sein, das ich hier völlig falsch liege, aber ich sehe nicht 
wo.

von Falk B. (falk)


Lesenswert?

@  Michael Reinelt (fisa)

>Mit Transfer meinst du 8 Bit, richtig? 16 Zyklen stimmt aber nur, wenn
>die Gegenseite entsprechend schnell kann. Laut Datenblatt verträgt der
>ADS1248 500 ns SCLK-Takt, also 2 MHz.

Damit ist ein Byte in 4 us eingelesen, macht maximal 48 Takte bei 16 
MHz.
Da lohnt sich kein Interrupt.

> Da die Verbindung über ein (wenn
>auch kurzes) Flachbandkabel geht, bin ich (noch) nicht sicher ob ich
>nicht mit dem SPI-Takt runter muss.

2 MHz SPI Takt über Flachbandkabel ist kein Problem, WENN man es richtig 
macht. Siehe Wellenwiderstand.

> Dann wären es entsprechend mehr Takte, richtig?

Sicher. Mehr CPU-Takte.

von Falk B. (falk)


Lesenswert?

@  Michael Reinelt (fisa)

>ich möchte einen ATmega 328 mit einem ADC (ADS1248) über SPI sprechen
>lassen. Da ich etwas beengt an freien Signalen bin, habe ich eine
>4-Draht-Verbindung: DIN/MOSI, DOUT/MISO, SCLK und CS.

>abzuholen wären. Es gibt aber einen speziellen Modus, wo statt DRDY der
>DOUT-Pin mit genutzt werden kann. Der ADC zieht (bei aktiviertem CS)
>also DOUT/MISO kurz auf high, um zu signalisieren dass Daten da sind.

>Da ich mit einer recht geringen Wandlungsrate (~5 SPS) arbeiten will,
>und mein ATmega in der Zwischenzeit recht beschäftigt ist, möchte ich
>DRDY per Pin Change Interrupt überwachen. Nur - PCINT während der
>SPI-Übertragung ist dann wohl nicht so sinnvoll....

>ich könnte natürlich in der PCINT-ISR gleich die SPI-Kommunikation
>abwickeln, aber das widerstrebt mir massiv.

Ist auch Unsinn. Man braucht ein gescheites Konzept mit einer 
statemachine, Multitasking und den passenden Handshakesignalen 
über Interrupts. Eine Kaskadierung von Interrupts braucht hier kein 
Mensch.

>SPI würde ich auch gerne über Interrupt abwickeln (ich mag Interrupts).

Wurde schon als unsinnig erkannt.

>ich müsste also in der PCINT-ISR den interrupt-Handler "umschalten", und
>danach wieder zurückschalten.

Nö.

>Kriegt man das ohne massiven Knoten im Hirn hin, oder denke ich komplett
>verquert, und man macht das ganz anders?

Ja, ganz anders. Einfach per sauberer statemachine.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Hallo zusammen,

das Problem hat sich in Luft aufgelöst :-)

der ADC konvertiert mit 10 SPS, nach erfolgreicher Konvertierung zieht 
er MISO auf Low, und beginnt mit der nächsten Konvertierung. Ich hab 
also fast 100 msec Zeit das Ergebnis abzuholen. Ich muss nicht mal auf 
die fallende Flanke pollen, sondern nur auf das Low-Signal.

Geht jetzt ausgezeichnet, und zwar ganz ohne Interrupts!

Ich hab mich von einer verwirrenden Darstellung im Datenblatt ins 
Bockshorn jagen lassen, wo MISO nur ganz kurz auf high geht, den Impuls 
hätte ich u.U. mit Polling "versäumt".


Danke an alle, und guten Rutsch!

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.