SPI Verdrahtung zw. 2 ATMega8

Hallo LotadaC, hallo Mikro23

Vielen Dank für Eure Hilfe :good2:!

Diese while-Schleife in der ISR des Slave - der faux pas hätte mir auffallen müssen :confused: - aber ich habe da irgendwann "den Wald vor lauter Bäumen nicht mehr gesehen" ...
Ich habe - wie vorgeschlagen - aus der while-Schleife eine if-Schleife gemacht (beim Slave) und beim Master den Takt geändert (dieser war zu hoch, dies führte wiederum zu falschen Ergebnissen beim Slave)...
Jetzt funktioniert das Senden der Daten vom Master => Slave :).
Es fehlt nun der Datenaustausch Master <=> Slave ....

mfg

Hero_123
 
Zuletzt bearbeitet:
Heros Code ist Slave-Code.
Ich hatte mir wie gesagt nur die von Dir zitierte ISR angesehen (zu mehr hatte ich noch keine Zeit)…
Innerhalb der ISR sind IRQs grundsätzlich über das I in SREG unterdrückt
Bevor die ISR beendet ist, kann sich der Controller nur einen neuen Interrupt merken. Alle weiteren gehen dann verloren.

Bei den Xmegas (und den neuen tinies und megas) wird das I-Flag nicht verändert (Edit sagt, hast Du ja schon erwähnt). Da die alle zwei oder drei Prioritätsebenen haben, werden nur Interrupts niedrigerer Priorität gesperrt.
aus der while-Schleife eine if-Schleife gemacht
Aua! ;) If ist eine Bedingung bzw. Verzweigung. Hat nichts, aber auch garnichts mit Schleifen zu tun.
 
Bevor die ISR beendet ist, kann sich der Controller nur einen neuen Interrupt merken. Alle weiteren gehen dann verloren.
Wie gesagt kann(!) man auch sofort "in der ISR" "I" wieder setzen - man muß dann(!) natürlich einschätzen können, was daraus folgen kann...
Mit "nur einen Interrupt" meinst Du für jede Interruptquelle einzeln einmal - klar, aber sicherheitshalber nochmal erwähnt. Jedes Interrupt-Fähnchen kann nur einmal hochgezogen werden, dann ist es oben. Solange man es nicht runterzieht, sieht man nicht wie oft es zwischendurch neu hätte hochgezogen werden sollen. Eben deswegen sollten ISRs ja kurz sein, aber eben auch so lang wie nötig. Man muß eben abschätzen wieviel Zeit/Takte man hat und braucht, wenn's eng werden könnte.
If ist eine Bedingung bzw. Verzweigung. Hat nichts, aber auch garnichts mit Schleifen zu tun.
Hochsprachenkram...:stupid::p (Aber da haste dann natürlich(!) recht...)
Schleifen bestehen doch auch nur aus (mindestens) einem Sprung (zurück). Entweder ohne Bedingung (Endlosschleife, Goto, Jmp), oder mit einer Bedingung, die eigentlich nichts anderes als ein "If" ist (If Bedingung then Springe... Oder maschinennäher: Operation mit Statusbit-Manipulation -> Branch if Bit in Statusregister is Set/Cleared). Kommt nur darauf an das richtig anzuwenden.
 
:offtopic:
Wenn Du Dich mal mit strukturierter Programmierung beschäftigt hast, weißt Du, daß es nur drei grundlegende Strukturelemente gibt: Anweisung, Verzweigung und Schleife.

Jedes beliebige Programm läßt sich aus diesen drei Elementen aufbauen und mit Leichtigkeit in jede beliebigen Programmiersprache (auch Assembler) übertragen.

Assembler ist übrigens auch schon eine höhere Sprache. :D Wenn Du wirklich an die Wurzeln gehen willst mußt Du in Maschinensprache, d.h. in Nullen und Einsen programmieren. :p

Von der CPU aus gesehen, mag Assembler bzw. Maschinensprache grundlegender aussehen, vom Programm aus gesehen, sind Struktogramme (Nassi-Shneiderman-Diagramme) grundlegender.
 
Hallo Mikro23

Aua! ;) If ist eine Bedingung bzw. Verzweigung. Hat nichts, aber auch garnichts mit Schleifen zu tun.

Das ist mir klar; wenn man Begrifflichkeiten verwendet, dann im korrekten Kontext.
Aber ein Verschreiben kann immer mal vorkommen ;)
:offtopic:
Auch wenn ich kein C - oder Mikrocontroller - Adept bin, so kenne ich dennoch den theoretischen Unterschied zwischen einer abweisenden und nicht-abweisenden Schleife, einer Verzweigung und einem bedingten Sprung - und deren praktischen Auswirkungen im Programm ;)

mfg

Hero_123
 
  • Like
Reaktionen: Mikro23
Verschreiben kann immer mal vorkommen
Bei Leuten, die man nicht persönlich kennt (grade im web soll sowas häufig vorkommen ;)),
weiß man nicht, welche Vorkenntnisse man voraussetzen kann.

Da gibt es beispielsweise Softwarecracks, die Null Ahnung von Hardware haben
oder Hardwarespezialisten, die noch nie ein Programm gesehen haben...
 
Hallo Mikro23

:good3:

mfg

Hero_123
 
  • Like
Reaktionen: Mikro23
Strukturelemente mußt Du programmieren (lassen). Bedingte Verzweigungen gibt's beim AVR in rudimentärer Form, Schleifen nicht; die mußt Du Dir aus (rudimentären Verzweigungen) zusammenbauen (lassen)…
Hier (und in einigen folgenden Beiträgen) hatte ich alle Instruktionen (Ja, Assembler - aber ich hätte da ebenso die Maschinen-Opcodes hinschreiben können) zusammengestellt - Schleifen sind nicht dabei...
Wenn Du wirklich an die Wurzeln gehen willst mußt Du in Maschinensprache, d.h. in Nullen und Einsen programmieren. :p
Hab ich spaßenshalber auch schon mal gemacht;)
(zumindest das bis zum Hexfile - das flashen hab ich dann das Studio machen lassen.) Dauert natürlich etwas länger.
Es geht aber auch ganz extrem, nur mit zwei Tastern (und Widerständen) am SPI - den Link hab ich leider nicht mehr im Kopf
Edit: Nachreich

Aber genug OT...
 
Strukturelemente mußt Du programmieren ... Schleifen sind nicht dabei...
Aus Sicht des Programms ist die Herangehensweise völlig anders. Ich habe versucht zwei völlig konträre Sichtweisen zu beschreiben. Die meisten Leute, die Controller bzw. Mikroprozessoren programmieren, kommen von der Hardwareseite (inzwischen mag sich das (seit Arduino und Konsorten) geändert haben) und sehen als erstes nur Nullen und Einsen, also Maschinensprache bzw. Assembler und dann erst höhere Sprachen.

Von der Softwareseite, also für Programmierer, die nicht mal mehr das Wort Hardware kennen, sieht das ganze ein bißchen anders aus. Bevor man auch nur eine einzige Zeile in irgendeiner Programmiersprache schreibt, wird (in vielen Fällen muß man allerdings sagen: sollte) das gesamte Programm aus den drei Strukturelementen auf Papier entworfen.
Wie die Strukturelemente später in einer beliebigen Programmiersprache umgesetzt werden, spielt erstmal überhaupt keine Rolle. Höhere Programmiersprachen bieten bloß etwas einfachere Möglichkeiten die Kontrollstrukturen umzusetzen als Assembler. Und C sehe ich immer noch als einen besseren Makroassembler, der mir die überflüssige Arbeit abnimmt, alles zu Fuß zu programmieren. Die Maschinennähe ist ähnlich wie bei Assembler.

Bevor ich den AVR-Befehlssatz kennenlernte (als ich mit AVR anfing, war das Erste, den Befehlssatz anzusehen), habe ich 6802, IBM 360, 6502, 8080, 6809, Z8, 68000 und 6805 (in der Reihenfolge ihres Auftretens) programmiert, zuerst in Maschinensprache, dann Assembler, Fortran IV, Basic, Pascal, Modula II, Forth und dann erst in C (abermals in der o.g. Reihenfolge).
Hab ich spaßenshalber auch schon mal gemacht;)
Ich hab mit dem Eurocom 1 angefangen.
Eurocom1.jpg
Acht Siebensegment-Anzeigen, Hexadezimaltastatur.
Das »Betriebssystem« war im 2716, 2 kB EPROM. Das Programm wurde hexadezimal ins RAM eingegeben. Nach Ausschalten des Stroms war alles weg.

EO OT ;)
 
Hallo

Ich habe es jetzt hinbekommen, dass Master <=> Slave Daten austauschen (8 Byte), musste aber beim Master in der Sende/Empfangsroutine ("void SPI_write( uint8_t *sen_buf, uint8_t *empf_buf, uint8_t buf_size )") ein _delay_us(50) (also 50us delay) einfügen, damit die Empfangsdaten korrekt in den Empfangsbuffer "empf_buf" beim Master geschrieben werden; die SCK Frequenzy = f/16 (3686400/16).

Ich verstehe das _delay_us(50) nicht - würde ich nur 1 Byte senden/empfangen, wäre es nicht nötig..
So wie es scheint, gibt es Probleme beim Schreiben der Empfangsdaten beim Master und dies kann ich nur durch ein delay (die schlechteste aller Möglichkeiten) in Griff bekommen...wenn ich dieses delay nicht habe (sende/empfange 8 Bytes) stehen im Empfangsbuffer des Masters teilweise die Werte des Sendebuffers des Masters - komisch ...

Ich nehme an (hab's nicht getestet) dass ich die Verzögerung noch größer machen müsste, wenn ich mehr Werte als nur 8 Bytes übertragen würde ...

Ich hatte natürlich vor Einfügen des delays mit verschiedenen SCK Werten getestet (f/128 als minimalster Wert), hatte aber dennoch falsche Werte im Empfangsbuffer (nämlich Sendewerte...)

Der Master pollt SPI, der Slave macht es durch eine ISR.

In der SPI Verdrahtung habe ich je Line einen Serienwiderstand von 1kOhm

Auch verstehe ich nicht, dass ich nach einem Flashen des Masters den Slave auch flashen muss, obwohl beim Slave programmmäßig nichts geändert wurde ...

mfg

Hero_123
 

Anhänge

  • master_spi_05.c
    5,4 KB · Aufrufe: 4
  • slave_spi_int_05.c
    7,9 KB · Aufrufe: 1
Zuletzt bearbeitet:
Es sollte prinzipiell möglich sein, alle seriellen Schnittstellen zu benutzen ohne ein Delay zu benötigen. Wenn es nicht ohne geht, liegt das vermutlich ein einer ungünstigen Programmstruktur.

Hast Du schon mal ein externes Peripheriegerät, wie z.B. ein EEPROM mit SPI-Schnittstelle benutzt? Falls nicht, versuchst Du den zweiten Schritt vor dem ersten...
 
Hallo Mikro23

Vielen Dank für Deine Antwort.

Es sollte prinzipiell möglich sein, alle seriellen Schnittstellen zu benutzen ohne ein Delay zu benötigen.

Der Meinung bin ich auch ...

Wenn es nicht ohne geht, liegt das vermutlich ein einer ungünstigen Programmstruktur.

Das kann ohne weiteres sein ...

Hast Du schon mal ein externes Peripheriegerät, wie z.B. ein EEPROM mit SPI-Schnittstelle benutzt?

Nein, habe ich nicht. Ich habe zwei ATMega8 Boards.

Falls nicht, versuchst Du den zweiten Schritt vor dem ersten...

Wieso das denn?


mfg

Hero_123
 
Ganz einfach: Wenn Du ein externes SPI-Peripheriegerät benutzt, kannst Du zu hundert Prozent sicher sein, daß Du einen funktionierenden Slave hast und kannst Dich voll darauf konzentrieren den Master zu programmieren.

Du versuchst Master und Slave gleichzeitig zu programmieren und weißt damit nie in welchem Programmteil Du den nächsten Fehler suchen mußt.
 
Hallo Mikro23

Bei allem gebührlichem Respekt - aber Deine letzten Beiträge haben mir bei meinem Problem nicht geholfen.

Ein EEPROM anstatt des SLAVE ATMega8 - welche Erfahrung gewinne ich damit? Soweit mir bekannt, kann ich in ein EEPROM Bytes schreiben und diese - unverändert - wieder auslesen => wäre ein EEPROM der Slave, würde der Master genau das zurücklesen, was er geschrieben (=gesendet) hat.
Außerdem könnte ich mit einem EEPROM als Slave eine zweite Baustelle aufmachen, wenn ich das Senden und Empfangen nicht "zum Laufen" bekomme.
Und sollte das Senden/Empfangen beim Master problemlos funktionieren - dann kann ich zwar sagen "Ja, das mit dem EEPROM funktioniert", aber das ursprüngliche Problem habe ich damit nicht gelöst.


mfg
Hero_123
 
Es sollte prinzipiell möglich sein, alle seriellen Schnittstellen zu benutzen ohne ein Delay zu benötigen.
Hmm...
Um mal bei den von Dir eingeworfenen seriell angebundenen Speichern zu bleiben:
Der Master-AVR soll also ein Byte von Adresse X lesen. Vereinfacht angenommen also folgendes Protokoll:
  • CS aktivieren
  • X senden (empfangenes Byte enthält entweder Status oder Müll)
  • irgendwas senden (empfangenes Byte ist Inhalt von Adresse X)
  • CS deaktivieren
Ok, wenn jetzt ein AVR die Rolle des Slave übernehmen soll, brauchst Du zwingend 'ne Pause (ob nun delay-basiert, durch irgendwelchen nebenbei laufenden sinnigen Code, oder durch einen hinreichend groß gewählten SPI-Prescaler) zwischen dem letzten Bit von "X senden" und dem ersten Bit von "irgendwas senden".
Der Slave muß ja Zeit zum reagieren haben - bei Verwendung von IRQs verstreichen erstmal vier Takte bis zur IVT, zwei weitere für den Sprung zur ISR. Dort wird dann sicherlich das SREG und vorher ein Rechenregister gerettet (mindestens), fünf weitere Takte. jetzt wäre das SPDR zu laden (1 Takt), das adressierte Byte zu laden (2 Takte) und nach SPDR zu schreiben (1 Takt).
Also mindestens 15 Takte.
Bei einem möglichen SCK-Vorteiler von vier wären da bereits gut drei Bits des nächsten Bytes im Transfer unterwegs.

Meinem Verständnis nach sollte bereits beim Beschreiben von SPDR nach der ersten SCK-Flanke (des neuen Bytes) 'ne Write Collision kommen.
Aus dem Datenblatt geht nicht genau hervor, ob SPDR während eines Transfers (nach der ersten SCK-Flanke) "gelockt" ist, aber "single buffered in the transmit direction" könnte man zumindest so interpretieren...
So wie es scheint, gibt es Probleme beim Schreiben der Empfangsdaten beim Master und dies kann ich nur durch ein delay (die schlechteste aller Möglichkeiten) in Griff bekommen...wenn ich dieses delay nicht habe (sende/empfange 8 Bytes) stehen im Empfangsbuffer des Masters teilweise die Werte des Sendebuffers des Masters - komisch ...
Das (Probleme beim Schreiben) glaube ich nicht. Wenn Du ein Byte ins SPDR schreiben läßt, wird das Byte ins Schieberegister geschrieben (sofern kein Transfer läuft). Bei gesetztem MSTR-Bit (=Master), wird dadurch auch ein Transfer angestoßen.
Nach dem achten Bit wird der Inhalt des Schieberegisters in den "Shift Register Read Buffer" kopiert.
Jedesmal wenn Du SPDR lesen läßt, wird in Wirklichkeit dieser Read-Buffer ausgelesen - das eigentliche Schieberegister kannst Du gar nicht (zurück-) lesen.

Wahrscheinlicher ist (meiner Meinung nach) eher, daß der Master (ohne Pause) den Transfer des zweiten Bytes bereits angestoßen hat, bevor der Slave das entsprechende Byte in sein SPDR legen konnte. Dort befand sich also bei Transfer-Begin noch das, vom Master empfangene Byte, welches jetzt zurück getaktet wird. Kannst ja testweise mal MISO unterbrechen, und beim Master fest auf Vcc oder Gnd legen - dann solltest Du immer 0xFF oder 0x00 empfangen, ega was Du sendest...

Aber das ist nur meine Vermutung (als nicht-studierter Hobby-Mikrocontroller-Amateur)...
 
Zuletzt bearbeitet:
Hallo Hero_123,

Ich weiß nicht, welche Vorkenntnisse Du hast. Für mich sieht es so aus, als hättest Du kaum Erfahrungen mit SPI und dann ist Dein Vorhaben so, als wolltest Du Wurzelziehen, bevor Du die Grundrechenarten beherrschst.

Aber wenn Du weißt, wie SPI funktioniert, wirst Du leicht selbst herausfinden können, ob @LotadaC s Vermutungen im letzten Beitrag stimmen.

µ
 
HalloLotadaC

Vielen Dank für Deine Hilfe :good2:!

Der Hinweis, dass der Slave mindestens diese 15Takte benötigt, waren die Lösung - ich lasse den Master erstmal 'ne Zeit warten (mit "__asm volatile("nop")"); das _delay_us() ist somit obsolet.

Das andere hab' ich auch mal probiert; habe 255 = 0xFF empfangen.

mfg

Hero_123
 
Hallo Mikro23

Hallo Hero_123,

Ich weiß nicht, welche Vorkenntnisse Du hast. Für mich sieht es so aus, als hättest Du kaum Erfahrungen mit SPI und dann ist Dein Vorhaben so, als wolltest Du Wurzelziehen, bevor Du die Grundrechenarten beherrschst.

Bei allem gebührlichem Respekt - diese Bemerkung von Dir ist weder motivierend noch zweckdienlich. Man lernt nur durch Erfahrung und die bekommt man nur, wenn man sich an etwas Unbekanntes wagt.
Vorkenntnisse - siehe Beitrag #65

Auch wenn ich zu Beginn keine Erfahrung mit SPI hatte (siehe meinen Post #1) - JETZT habe ich welche. Und hätte ich welche gehabt, hätte ich hier nicht meine Fragen gestellt.
"Erfahrung ist etwas, das man hat, nachdem man es gebraucht hätte"

mfg
Hero_123
 
Natürlich vergeht zwischen Start und Ende der Übertragung Zeit.
brauchst Du zwingend 'ne Pause (ob nun delay-basiert, durch irgendwelchen nebenbei laufenden sinnigen Code, oder durch einen hinreichend groß gewählten SPI-Prescaler) zwischen dem letzten Bit von "X senden" und dem ersten Bit von "irgendwas senden".
Der Slave braucht die Zeit zum reagieren - was der Master in der Zeit macht ist irrelevant (Däumchendrehen, hundert Schachzüge vorrausberechnen, Youtube-Videos ansehen) - er darf eben nur nicht zu schnell das nächste Byte takten.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)