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
>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.
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.
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
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.
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.
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
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.
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
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.
>>>>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.
@ 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.
@ 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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.