PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : SPI Lesen/Schreiben von/an ein SPI-Modul



oderlachs
28.10.2018, 12:01
Hallo Freunde !
Ja der Garten hat seine Tore geschlossen, jetzt geht es wieder ans programmieren und Basteln. Nun stehe ich wieder vor einem Problem bei einer SPI Anwendung.
Warscheinlich bin ich in meinem Grunddenken des Ablaufs etwas verkehrt, denn ich verstehe nicht wie dem Slave beigebracht werdenb soll, das er Daten zu Senden hat.
Ich habe auch entsprechender Literatur nicht recht durchgesehen, wie das mit dem Empfang vom Slave im Master(Atmega32) vor sich geht.
Das SPDR wird ja zum Senden beschrieben wie auch beim Empfang dann ausgelesen....Das verwirrt mich ein wenig.

Hier nun mein Source-Code in der Basisform:



/* ================================================== ================ */
/* */
/* Programm interne Definitionen */
/* */
/* ================================================== ================ */
#define DDR_SPI DDRB
#define PORT_SPI PORTB
#define SPI_MOSI 5
#define SPI_MISO 6
#define SPI_SCK 7
#define SPI_SS 4
/* ================================================== ================ */
/* */
/* Funktionen deklarieren */
/* */
/* */
/* ================================================== ================ */
void SPI_Init();
void SPI_Write(uint8_t val);
uint8_t SPI_Read();


/* ================================================== ================ */
/* */
/* SPI Initialisieren */
/* */
/* */
/* ================================================== ================ */

void SPI_Init()
{
DDR_SPI |= (1 << SPI_MOSI);
DDR_SPI |= (1 << SPI_MISO);
DDR_SPI |= (1 << SPI_SCK);
DDR_SPI |= (1 << SPI_SS);
PORT_SPI &= ~(1 << SPI_SS); // CS auf LOW
SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1); // CPU_CLK/64
}

/* ================================================== ================ */
/* */
/* SPI Schreiben an Perepherie */
/* */
/* */
/* ================================================== ================ */

void SPI_Write(uint8_t val)
{

SPDR = val;
while(!(SPSR & (1 << SPIF)));
}

/* ================================================== ================ */
/* */
/* SPI Lesen von Perepherie */
/* */
/* */
/* ================================================== ================ */

uint8_t SPI_Read()
{
while(!(SPSR & (1 << SPIF)));
return SPDR;
}
/*================================================= ===================*/
/* */
/* */
/* */
/* */
/*================================================= ===================*/

Über einen "Anregungs-Tritt", um in die richtige Gedankenspur zu kommen, wäre ich sehr dankbar.

Ich möchte ein SD _Card Modul per SPI am ATmega32/644 betreiben, aber erst mal muss ich da die Grundlagen verstehen wie das mit dem Datenverkehr ist,
bevor ich dann mit dem SD-Spezifischen Sachen weiter mache.
Zum Lernen möchte ich es so halten das ein zweiter Atmega oder auch ein Arduino als Slave die empfangenen daten zurück sendet, die dann vom Master per UART ausgegeben werden.

So nun will ich hoffen das ich gut genug erklärt habe um was es mir geht und wo ich Hilfe, Hinweise benötige.

Gruss und Dank

Gerhard

seite5
28.10.2018, 13:27
DDR_SPI |= (1 << SPI_MISO); MISO als Ausgang?, Zeile einfach weglassen.
mfg
Achim

oderlachs
28.10.2018, 13:38
Danke Achim !
Nun grübel ich aber der MISO-Pin wird doch benötigt und muss meines Erachtens auch dann eine Datenrichtung zu geordnet bekommen.
Na ja ich steck ja bei SPI noch in der "Schultüte".. ;)

Gruss und Dank

Gerhard

Searcher
28.10.2018, 14:07
Hallo,

ich verstehe nicht wie dem Slave beigebracht werdenb soll, das er Daten zu Senden hat.

Im Allgemeinen wird der SS Pin dazu benutzt. Im AVR-Slave ist das ein Input und wird durch den Master-SS auf LOW gezogen. Dadurch wird die SPI HW im AVR-Slave aktiviert und kann Daten empfangen. Damit der Slave auch was Sinnvolles außer einem Nullbyte senden kann, muß ins Senderegister was hineingeschrieben werden, bevor der Master Daten sendet.

Hat der Slave ein Byte vollständig vom Master empfangen, setzt er sein SPIF Flag. Gleichzeitig mit Empfang eines Bytes vom Master hat er sein Byte zum Master geschickt.

Das SPIF kann und wird als Indikator benutzt, daß das emfangene Byte im SPDR (SPI Datenregister) zum Abholen bereit steht und dort ein weiteres Byte zum Senden abgelegt werden kann.

Das SPDR hat eine Doppelfunktion. Liest man es, bekommt man das empfangene Byte. Beschreibt man es, wird das Byte gesendet bzw. auf der Slaveseite zum Senden bereitgestellt, da ja von dort erst mit Empfang des Mastertaktes tatsächlich gesendet wird.



...wie das mit dem Empfang vom Slave im Master(Atmega32) vor sich geht. Das SPDR wird ja zum Senden beschrieben wie auch beim Empfang dann ausgelesen....Das verwirrt mich ein wenig.

Wie oben erwähnt, hat das SPDR eine Doppelfunktion. Wird es im Master beschrieben, wird der Mastertakt gestartet und das Byte gesendet. Der Slave schickt durch den Takt gleichzeitig sein Byte zum Master. Ist das Byte vom Master vollständig rausgeschickt, setzt der Master sein SPIF-Flag. Nun kann der Master das vom Slave empfangene Byte, das ja parallel zum Senden empfangen wurde, im SPDR Register abholen und sofort das nächste Byte zum Senden ins SPDR schreiben.

Eventuell geht sogar erst Schreiben und dann erst das empfangene Byte lesen. Man muß aber aufpassen, daß das empfangene Byte nicht vom nächsten Empfang überschrieben wird (durch Schreiben ins SPDR sendet der Master und gleichzeitig sendet der Slave zurück) Das empfangene Byte muß aus dem SPDR gelesen werden bevor das nächste Byte, das ja seriell eintrudelt, vollständig vom Slave eingetroffen ist.

Gruß
Searcher

oderlachs
28.10.2018, 15:49
Danke Searcher !!
Drei goldene Bienchen zu Dir sende, hast mir sehr geholfen es etwas besser zu verstehen. Nun ich war auch nicht untätig, habe aus nem Arduino-Uno eine "Sklaven" gebastelt und den habe ich ans STK500 angeschlossen.
Wenn auch noch mit Startproblemchen gibt der Arduino das vom Atmega/STK500 gesende Byte seriell aus. Wenigstens etwas was ich so schon hinbekommen habe. Muss mich halt mit der Materie noch weiter befassen.
Ich glaube aber das ich das SD-Projekt aufgebe. Hatte da ein Beispiel von Ulrich Radig ins Auge gefasst, aber da habe ich nur Compiler und Libraries Fehler. Liegt warscheinlich an meine Entwicklungsumgebung mit Geany unter Linux.
Aber die langen Herbst-/Winter-Abende stehen ja bald ins Haus...da kann man wieder Probieren und testen.
Vielen Dank

Gerhard.

P.S. Natürlich bin ich hier weiter für jede(n) Hinweis/Unterstützung dankbar.
Mein Ziel ist Sensor-Klimadaten , Temperatur, Feuchte ....Druck einzulesen und dann in eine csv-datei auf eine SD Card(SPI-Interface) zu schreiben.