Hallo,
ich wollte jetzt mal vom Polling auf Interrupt umsteigen um eine saubere
Kommunikation am SPI-Bus zu haben.
Mit dem "poll" Verfahren klappt soweit alles prima...
Aktiviere ich jetzt aber die dazugehörige "ISR" bricht alles zusammen
und nichts funktioniert mehr.
Ich weiß nicht woran das liegt?! :(
Hat jemand eine Idee?
Main
Jan H. schrieb:> um eine saubere Kommunikation am SPI-Bus zu haben.
Sauber ist die SPI-Kommunikation auch im polled mode.
Bei hinreichend hohem SPI-Takt lohnt sich Interruptbetrieb überhaupt
nicht. Am ehesten wäre es noch sinnvoll, wenn du einige Daten „am
Stück“ übertragen musst, dafür DMA zu nutzen, sodass er am Ende eines
Transfers ohne CPU-Zutun den nächsten starten kann.
> Ich weiß nicht woran das liegt?! :(
Vielleicht daran, dass deine Indexvariable in der ISR über alle
Maßen wachsen kann, und somit der ganze Speicher zugemüllt wird?
Jörg W. schrieb:> Jan H. schrieb:>> um eine saubere Kommunikation am SPI-Bus zu haben.>> Sauber ist die SPI-Kommunikation auch im polled mode.>> Bei hinreichend hohem SPI-Takt lohnt sich Interruptbetrieb überhaupt> nicht. Am ehesten wäre es noch sinnvoll, wenn du einige Daten „am> Stück“ übertragen musst, dafür DMA zu nutzen, sodass er am Ende eines> Transfers ohne CPU-Zutun den nächsten starten kann.>>> Ich weiß nicht woran das liegt?! :(>> Vielleicht daran, dass deine Indexvariable in der ISR über alle> Maßen wachsen kann, und somit der ganze Speicher zugemüllt wird?
Ich habe die ISR auch leer gelassen und genau den selben Effekt
vorgefunden.
Daran kann es nicht liegen.
Jan H. schrieb:> Daran kann es nicht liegen.
Wie geschrieben: überleg' dir erstmal, ob ein Interruptbetrieb
überhaupt irgendeinen Sinn hat. Wenn du dein SPI mit f_CPU/2
taktest, dann hast du nach 16 CPU-Takten ein Byte komplett durch.
In dieser Zeit hat die ISR gerade mal die nötigen CPU-Register
gerettet.
Ich kann nicht so recht den Sinn erkennen bei einem SPI Master
den Recieve Interrupt zu nutzen. Ich weiss ja dass ich (sowieso)
ein Receive durch einen Transmit initiiere. Die Daten sind ja
"schon da" wenn ich auf den "Transmit-Knopf" gedrückt habe ...
SPIProgrammierer schrieb:> Ich kann nicht so recht den Sinn erkennen bei einem SPI Master> den Recieve Interrupt zu nutzen.
Das ist ja ohnehin kein Receive-Interrupt, sondern ein "Transfer
complete".
Für sehr langsames SPI kann man sowas schon machen, wenn man in
der Zwischenzeit auf der CPU was anderes tun könnte.
SPIProgrammierer schrieb:> Ich kann nicht so recht den Sinn erkennen bei einem SPI Master> den Recieve Interrupt zu nutzen. Ich weiss ja dass ich (sowieso)> ein Receive durch einen Transmit initiiere. Die Daten sind ja> "schon da" wenn ich auf den "Transmit-Knopf" gedrückt habe ...
Mein "Problem" ist es so :
Jan H. schrieb:> mehrere bytes hintereinander zu empfangen.
Hast du das Prinzip von SPI überhaupt verstanden?
SPI ist ein Schieberegister. Du schiebst 8 Bits raus (indem du
das SPDR „abgehend“ beschreibst, die Hardware leiert dann die
Taktbits an), und gleichzeitig werden 8 Bits von MISO reingeschoben.
Die kannst du danach aus SPDR „ankommend“ einlesen.
Wenn du mehrere Bytes lesen willst, musst du auch genauso viele Bytes
schreiben.
Jörg W. schrieb:> Jan H. schrieb:>> mehrere bytes hintereinander zu empfangen.>> Hast du das Prinzip von SPI überhaupt verstanden?>> SPI ist ein Schieberegister. Du schiebst 8 Bits raus (indem du> das SPDR „abgehend“ beschreibst, die Hardware leiert dann die> Taktbits an), und gleichzeitig werden 8 Bits von MISO reingeschoben.> Die kannst du danach aus SPDR „ankommend“ einlesen.>> Wenn du mehrere Bytes lesen willst, musst du auch genauso viele Bytes> schreiben.
Jan H. schrieb:> Hier für meine 3 bytes.
Immer noch nicht komplett …
„Komplett“ ist etwas, wenn man es compilieren kann.
Ich hab' keine Lust mehr, dir jedes Detail einzeln aus der Nase zu
ziehen.
Jörg W. schrieb:> Jan H. schrieb:>> Hier für meine 3 bytes.>> Immer noch nicht komplett …>> „Komplett“ ist etwas, wenn man es compilieren kann.
Was willst du denn jetzt sehen?
In der Main rufe ich nur diese Routine auf...
Jan H. schrieb:> Was willst du denn jetzt sehen?
Ein komplettes, in sich schlüssiges, compilierbares Beispiel.
Nicht hier ein Stück, da ein Stück, und spi_master_transmit()
fehlt immer noch.
S. Landolt schrieb:> Stimmt dieses '__AVR_ATmega32U4__'?
Ja, die werden so vom Compiler definiert.
Wobei ich mich schon frage, warum man (in spi_master_receive())
überhaupt dergestalt eine Fallunterscheidung machen möchte, wenn
dann beide Implementierungen gleich sind.
Jörg W. schrieb:> S. Landolt schrieb:>> Stimmt dieses '__AVR_ATmega32U4__'?>> Ja, die werden so vom Compiler definiert.>> Wobei ich mich schon frage, warum man (in spi_master_receive())> überhaupt dergestalt eine Fallunterscheidung machen möchte, wenn> dann beide Implementierungen gleich sind.
Es vebraucht keinen speicher auf meinem AVR, wieso sollte ich es nicht
machen? Es kann bei einem anderen AVR auch ein anderes Register mal
sein.
OK, ist zwar immer noch blöd, dass du nicht mal einfach alles in
eine Datei packst, die man auch durch den Compiler schicken kann
(so muss ich mir all deine Puzzelsteine im Kopf zusammensetzen),
aber dein Problem wird es einfach sein, dass du zweimal auf das
Ende eines Transfers warten möchtest: einmal in spi_master_transmit()
und dann noch einmal in spi_master_receive().
Das Flag wird aber nur einmal gesetzt.
Entweder wartest du am Ende von transmit(), oder am Anfang von
receive(). Ersteres ist dahingehend sinnvoll, dass du auf diese
Weise zwei transmit() direkt hintereinander setzen kannst, ansonsten
müsstest du vor dem zweiten nochmal separat warten.
Jan H. schrieb:>> Wobei ich mich schon frage, warum man (in spi_master_receive())>> überhaupt dergestalt eine Fallunterscheidung machen möchte, wenn>> dann beide Implementierungen gleich sind.>> Es vebraucht keinen speicher auf meinem AVR, wieso sollte ich es nicht> machen?
Weil es den Code umständlicher macht (code obfuscation).
Fallunterscheidungen macht man dann, wenn man sie braucht, und
nicht „für den Fall der Fälle“.
Da du sowieso schon zwei verschiedene Klassen von AVRs hast (einmal
MegaAVR und einmal Xmega) und bei beiden Senden und Empfang gleich
sind, und die Routine jenseits von AVRs ohnehin völlig anders
aussehen dürfte, kannst du die Fallunterscheidung dort getrost
weglassen. Dann blieben nur noch ein paar Bits in der
Initialisierung, für die man wirklich eine Unterscheidung braucht.
Der größte Teil davon ist selbst dort bei beiden Klassen gleich.
Jörg W. schrieb:> Jan H. schrieb:>>> Wobei ich mich schon frage, warum man (in spi_master_receive())>>> überhaupt dergestalt eine Fallunterscheidung machen möchte, wenn>>> dann beide Implementierungen gleich sind.>>>> Es vebraucht keinen speicher auf meinem AVR, wieso sollte ich es nicht>> machen?>> Weil es den Code umständlicher macht (code obfuscation).>> Fallunterscheidungen macht man dann, wenn man sie braucht, und> nicht „für den Fall der Fälle“.>> Da du sowieso schon zwei verschiedene Klassen von AVRs hast (einmal> MegaAVR und einmal Xmega) und bei beiden Senden und Empfang gleich> sind, und die Routine jenseits von AVRs ohnehin völlig anders> aussehen dürfte, kannst du die Fallunterscheidung dort getrost> weglassen. Dann blieben nur noch ein paar Bits in der> Initialisierung, für die man wirklich eine Unterscheidung braucht.> Der größte Teil davon ist selbst dort bei beiden Klassen gleich.
Du hast ja Recht. Habe es geändert.
Du meinst mit warten sicherlich die "while(bedingung" Abfrage.
Habe es im spi_receive(); rausgenommen
Jan H. schrieb:
> Mein "Problem" ist es so :
...
> mehrere bytes hintereinander zu empfangen.
Und dieses Problem besteht jetzt, trotz korrigiertem 'spi_receive', noch
immer?
S. Landolt schrieb:> Jan H. schrieb:>> Mein "Problem" ist es so :> ...>> mehrere bytes hintereinander zu empfangen.>> Und dieses Problem besteht jetzt, trotz korrigiertem 'spi_receive', noch> immer?
Ja.
Jan H. schrieb:> Ja.
Glaub' ich nicht.
Also, ein Problem wirst du wohl noch haben, aber ich denke nicht,
dass an den SPI-Transfers jetzt immer noch was foul ist.
Halt doch mal einen Oszi an die Leitungen und schau nach, was auf
dem Draht passiert.
Was ist denn dein Fehlerbild?
Jörg W. schrieb:> Jan H. schrieb:>> Ja.>> Glaub' ich nicht.>> Also, ein Problem wirst du wohl noch haben, aber ich denke nicht,> dass an den SPI-Transfers jetzt immer noch was foul ist.>> Halt doch mal einen Oszi an die Leitungen und schau nach, was auf> dem Draht passiert.>> Was ist denn dein Fehlerbild?
Ich kann nicht wirklich nachvollziehen ob mein Sensor mir wirklich 24
Bit schickt oder ob ich die Rechnung falsch angehe.
Wenn ich das richtig sehe, muss man den ADE7758 mit CPHA=1 CPOL=0
betreiben.
Dafür hat dein spi_master_init() beim ATmega32 keinen Code, und
der Wert 2 bei der Xmega-Initialisierung müsste wohl eher eine 1
sein, oder täusche ich mich da?
Ich versteh' auch nicht ganz, warum du so einen riesigien Prescaler
von 64 nimmst. Der ADE7758 verkraftet doch maximal 10 MHz.
Wie schon geschrieben: ich würde mir die Signale jetzt auf einem Oszi
oder LA ansehen.
Jörg W. schrieb:> Wenn ich das richtig sehe, muss man den ADE7758 mit CPHA=1 CPOL=0> betreiben.>> Dafür hat dein spi_master_init() beim ATmega32 keinen Code, und> der Wert 2 bei der Xmega-Initialisierung müsste wohl eher eine 1> sein, oder täusche ich mich da?>> Ich versteh' auch nicht ganz, warum du so einen riesigien Prescaler> von 64 nimmst. Der ADE7758 verkraftet doch maximal 10 MHz.>> Wie schon geschrieben: ich würde mir die Signale jetzt auf einem Oszi> oder LA ansehen.
Das mit CPHA=1 CPOL=0, kann sein. Habe es mit der aktuellen Einstellung
getestet und kann div. Register die 8 Bit breit sind Erfolgreicht zurück
lesen.
Den Prescaler hatte ich nur so hoch eingestellt, damit ich was testen
konnte.
Das Erraten, welcher Wert angezeigt, welcher erwartet wird, welche
Spannung überhaupt anliegt, übersteigt meine Fähigkeiten. Ich schaue mir
stattdessen die Eco-Verfilmung an. Einen schönen Abend allerseits.
SPIProgrammierer schrieb:> Ich kann nicht so recht den Sinn erkennen bei einem SPI Master> den Recieve Interrupt zu nutzen.
???
Die dedizierte SPI-Hardware der AVR8 bietet überhaupt nur einen
Interrupt, weder braucht sie mehr noch hat sie mehr. Leider... Das liegt
nämlich schlicht daran, dass sie nicht double-buffered ist. Wie auch
immer: der TO benutzt genau diesen einen überhaupt nur möglichen
Interrupt. Er konnte also diesbezüglich garnichts falsch machen und hat
es demgemäss auch nicht getan.
Allerdings stimmt seine Interrupt*logik* schlicht nicht. Man muss den
SPI-Interrupt im geeigneten Moment erlauben, Bytes mitzählen und den
Interrupt im passenden Moment wieder verbieten.
Üblicherweise liegen solche Fehler daran, dass der Delinquent SPI als
Solches überhaupt nicht verstanden hat. Und/oder nicht die
SPI-Hardware...
Dabei ist das überaus trivial. Ein wenig spannend wird es erst mit den
double-buffer-fähigen UARTs im SPI-Master-Mode. Dann kann man nämlich
tatsächlich zwischen drei potentiell möglichen Interrupts wählen. Und
für den Fall des hier offensichtlich avisierten "Burst-Modell" des
Datenaustauschs ist da der RXC-Interupt sicher nicht die schlechteste
Wahl...
S. Landolt schrieb:> Das Erraten, welcher Wert angezeigt, welcher erwartet wird, welche> Spannung überhaupt anliegt, übersteigt meine Fähigkeiten. Ich schaue mir> stattdessen die Eco-Verfilmung an. Einen schönen Abend allerseits.
Was müsste ich denn ca. für einen A/D Wert bekommen bei einer
Wechselspannung von ~18V?
Jan H. schrieb:> Ich habe eine ~18VAC Spannung am Eingang 3 angelegt (PhaseC)> Mit entsprechenden Widerständen etc.Jan H. schrieb:> Was müsste ich denn ca. für einen A/D Wert bekommen bei einer> Wechselspannung von ~18V?
Das hängt von den „entsprechenden Widerständen“ ab. Sicher von noch
weiteren Faktoren, wenn ich das sehe, dass es ein ganzes Kapitel über
die Kalibrierung gibt.
Das Datenblatt wirst du wohl selbst erstmal verstehen müssen.
Wichtig wäre es doch als erstes, dass bei konstanter angelegter
Wechselspannung ein (einigermaßen) konstanter Wert herauskommt, und
bei einer geringeren Spannung ein kleinerer.
> Was müsste ich denn ca. für einen A/D Wert bekommen bei> einer Wechselspannung von ~18V?
Soll das heißen, dass am ADE7758 18 V~ anliegen? Im Datenblatt lese ich
unter Maximum Ratings: "Analog Input Voltage to AGND: –6 V to +6 V."
Nein. Das ist eine Schaltung die schon fertig ist.
Es liegen maximal 360mV an.
Mir scheint es wirklich so als würde ich die 3 Bytes nicht richtig
bekommen. Ich kann es auch nicht wirklich nachvollziehen.
Jan H. schrieb:> Mir scheint es wirklich so als würde ich die 3 Bytes nicht richtig> bekommen. Ich kann es auch nicht wirklich nachvollziehen.
Dann musst du es nachvollziehen lernen.
Sorry, deine eigene Arbeit können wir dir schlecht abnehmen.
Die Methoden, die ich als nächstes anwenden würde, habe ich dir
ja genannt: LA um zu sehen, dass der eingelesene Wert auch dem
Bitmuster entspricht, und Plausibilitätstest um zu sehen, dass
der gemessene Wert was mit der Eingangsspannung zu tun hat.
Jörg W. schrieb:> Jan H. schrieb:>> Mir scheint es wirklich so als würde ich die 3 Bytes nicht richtig>> bekommen. Ich kann es auch nicht wirklich nachvollziehen.>> Dann musst du es nachvollziehen lernen.>> Sorry, deine eigene Arbeit können wir dir schlecht abnehmen.>> Die Methoden, die ich als nächstes anwenden würde, habe ich dir> ja genannt: LA um zu sehen, dass der eingelesene Wert auch dem> Bitmuster entspricht, und Plausibilitätstest um zu sehen, dass> der gemessene Wert was mit der Eingangsspannung zu tun hat.
Ich habe die Spannung mit einem Stelltrafo geändert und das
entsprechende Register ausgelesen. Synchron dazu das Temperatur
Register. Alles habe ich auf einem LCD dargestellt.
Temperatur passt. Spannung jedoch nicht. Ich zweifel immer noch daran
das ich die 3 bytes richtig auslese.