Hallo zusammen,
ich habe nun schon länger vergeblich den MAX157 über SPI mit meinem
Mega8 anzusteueren. Ich weiß leider nicht ob die Receive so
funktioniert, denn damit hatte ich noch nirgends Erfolg.
Ich hab nun in der Funktion SPI_Master_ReceiveInit das geschrieben, was
ich auf Seite 11 im Datenblatt von Maxim finde. Ich hoffe das das so
funktionieren sollte, leider bleibt er aber immer in der while Schleife
von SPI_MasterReceive hängen.
Hier der Code:
Du musst erst etwas auf SPDR ausgeben (zum Beispiel eine 0), bevor
du etwas empfangen kannst. SPI sendet und empfängt immer zugleich,
sodass man etwas senden muss, um etwas zu empfangen.
Ok danke, wie sieht das aber konkret aus?
D.h. ich sende eine null (oder nur SPDR=0 schreiben?) und kann dann
gleich beide bytes auslesen? oder dazwischen dann nochmal was senden?
Warum aber genau ist das so? Das versteh ich noch nicht wirklich...
Gruß Stefan
Stefan Tschiggerl wrote:
> D.h. ich sende eine null (oder nur SPDR=0 schreiben?)
Genau so, SPDR = 0 sendet eine Null.
> und kann dann> gleich beide bytes auslesen?
Nein, das erste.
> oder dazwischen dann nochmal was senden?
Ja, nochmal, vermutlich wieder eine Null.
> Warum aber genau ist das so? Das versteh ich noch nicht wirklich...
Weil das Ganze weiter nichts als ein serielles Schieberegister ist.
Damit du etwas aus dem Schieberegister rausschieben kannst, musst du
auch zugleich was reinschieben. Erst das SPDR = 0 wirft nämlich die
SPI-Maschine überhaupt an, sodass sie beginnt, (acht) Taktimpulse
auszusenden. Der Inhalt der gesendeten Daten wird in diesem Falle
wohl vom SPI-Slave einfach komplett ignoriert.
So das hab ich jetzt gemacht und ich kann auch Daten empfangen, leider
hab ich nur immer 11111111 11111111, was nicht stimmen kann.
ich hab jetzt folgendes:
void SPI_MasterReceive(uint8_t buffer[])
{
PORTB &= ~(1<<CS);
DDRB |= (1<<MOSI);
SPDR=0;
/* Wait for reception complete */
while(!(SPSR & (1<<SPIF)));
buffer[0] = SPDR;
SPDR=0;
/* Wait for reception complete */
while(!(SPSR & (1<<SPIF)));
buffer[1] = SPDR;
PORTB |= (1<<CS);
}
war das so gemeint? Nur funktioniert leider noch nicht...
Gruß Stefan
Im Prinzip ist das OK. Jetzt stolperst du vermutlich über das
,,Kleingedruckte''.
Deine Wahl, PB1 als Chipselect für den Slave zu nehmen, ist recht
ungünstig. Wenn man ihn nicht anders benötigt, ist dafür eigentlich
immer der /SS-Anschluss (beim ATmega8 also PB2) die erste Wahl: im
Masterbetrieb muss dieser Anschluss entweder ein Ausgang sein (dann
hat er keinen Einfluss auf die SPI-Logik), oder falls er ein Eingang
ist, dient er der dynamischen Umschaltung des Masters auf Slave. In
diesem Falle muss PB2 garantiert auf High sein (entweder durch die
externe Beschaltung oder zumindest durch den Pullup, falls keine
externe Beschaltung dran ist), damit es sich um einen SPI-Master
handelt. Wie gesagt, die erste Wahl ist es, diesen Pin einfach als
Ausgang zu beschalten und als Chipselect für den (oder einen, falls es
mehrere davon gibt) SPI-Slave zu nutzen.
Außerdem hat das ständige Herumfummeln an der Datenrichtung des
SPI-Interfaces keinen rechten Sinn. Die Datenrichtung ist ja durch
das SPI-Interface selbst vorgegeben, man legt sie also einmalig bei
der Initialisierung so fest, dass MOSI, CS, und SCK Ausgänge sind und
MISO auf Eingang bleibt. Der einzige Ausgang, an dem man dann noch
manuell ,,fummeln'' muss, ist das CS selbst.
Ich hab' mir das Datenblatt nicht angesehen, wodurch wird eigentlich
die Wandlung im Slave selbst getriggert? Führt der Wandler ständig
Wandlungen durch, deren letztes Ergebnis du zu einem beliebigen
Zeitpunkt einfach abfragen kannst, oder musst du vielleicht erst
einmal ein Kommando schicken, mit dem er das startet?
Btw., die Code-Tags für C heißen [ c ] ... [ /c ], nicht [ c ] ...
[ \c ] (natürlich ohne den Leerzeichen).
Ich hab nun als Chipselect PB2 genommen, trotzdem gleiche Ergebnis.
Man muss normal kein Komando schicken, denn der Wandeler hat auch kein
DIN, nur DOUT...
Die Wandlung startet dann automatisch wenn ich CS auf low lege nach
2.5µs.
Ich hab mich an diesen Punkten orientiert:
1) Use a general-purpose I/O line on the CPU to pull
CS/SHDN low while SCLK is low.
2) Wait for the minimum wake-up time (tWAKE) specified
before activating SCLK.
3) Activate SCLK for a minimum of 16 clock cycles. The
first falling clock edge will generate a serial datastream
of three leading ones, followed by the channel
identification, the MSB of the digitized input
signal, and two sub-bits. DOUT transitions on
SCLK’s falling edge and is available in MSB-first format.
Observe the SCLK to DOUT valid timing characteristic.
Data should be clocked into the μP on
SCLK’s rising edge.
4) Pull CS/SHDN high at or after the 16th falling clock
edge. If CS/SHDN remains low, trailing zeros will be
clocked out after the sub-bits.
Das sollte doch so mit meinem Code übereinstimmen oder?
Hat vielleicht schon jemand diesen Wandler verwendet oder einen
funktionierenden Code?
Gruß Stefan
>void SPI_MasterReceive(uint8_t buffer[])>SPI_MasterReceive(bytes);
Sowas geht?
Irgendwie hab ich im Hinterkopf, dass C Parameter-Übergaben an
Funktionsaufrufe per "call-by-value" realisiert.
>Sowas geht?>Irgendwie hab ich im Hinterkopf, dass C Parameter-Übergaben an>Funktionsaufrufe per "call-by-value" realisiert.
Ja, das geht. Das nennt sich "call-by-reference". Es wird ein Zeiger auf
ein Feld übergeben.
mdg Robert
>Ja, das geht. Das nennt sich "call-by-reference". Es wird ein Zeiger auf>ein Feld übergeben.
Aber nur aufgrund dessen, dass es sich um ein Array handelt, was ja
sowieso durch Pointer beschrieben wird...
Wenn man länger drüber nachdenkt...
Danke Jörg für deine Hilfe!!!
Jetzt funktionierts endlich, ich habe deine Funktion genommen und in der
ReceiveInit nur die Eingänge und Ausgänge für MISO, SCK, CS.. +
Aktivierung SPI
Eines hab ich trotzdem noch: Manchmal - zwar sehr selten - wenn ich
Reset am AVR drücke und eine neue Messung kommt, habe ich nur 11111111
11111111. Und beim Einschalten manchmal nur Nullen. Warum kann das sein?
Ist vielleicht auch das Layaout daran schuld? ich hab den Max157 am
Steckbrett aufgebaut und mit Drahtbrücken mit meinem Experimentierbord
verbunden. Ist das ein möglicher Fehler? Ist ein 10 bit ADC...
Nochmals danke dass das endlich funzt!
Gruß Stefan