Servus ;)
Habe zu dem Thema zwar einige andere Beiträge gefunden, die haben mir
allerdings relativ wenig weitergeholfen.
Ich benutze den ATmega1284P und möchte aus dem SPDR Register Daten eines
Funkmoduls auslesen, glaube ich habe da einen Denkfehler in der
Read-Routine, vielleicht kann mir ja jemand weiterhelfen.
Den Transmitter habe ich bereits in Betrieb genommen und der
funktioniert einwandtfrei, also daran kann es nicht liegen.
Hier mal der Code-Abschnitt:
1
voidrx_fifo(){
2
uint8_ti;
3
uint8_ta[64];
4
uint8_tb;
5
PORTB&=~(1<<SCS);
6
SPDR|=0x45;
7
while(!(SPSR&(1<<SPIF)));
8
for(i=0;i<64;i++){
9
a[i]=SPDR;
10
}
11
PORTB|=(1<<SCS);
12
b=a[5];
13
if(b==166){
14
PORTD&=~(1<<LEDGELB);
15
PORTA|=(1<<LEDGRUEN);
16
}
17
else{
18
PORTD|=(1<<LEDGELB);
19
PORTA&=~(1<<LEDGRUEN);
20
}
21
}
Habe zusätzlich LED's eingebaut, um anzuzeigen, welcher Wert nun
ankommt, da ich kein Display habe (hab einfach irgendeinen Wert
verwendet, in diesem Fall A6 = 166). Jedoch erhalte ich immer 0 oder
255...
Meine Funktion zum Auslesen von Registern funktioniert allerdings
genauso wenig, also geh ich mal von nem Verständnisfehler meinerseits
aus :'D
Hi
> for(i=0; i<64; i++){> a[i]=SPDR;
So funktioniert das nicht. Der Takt zum Lesen muss vom Master erzeugt
werden. Und das geschieht durch Senden eines Dummybytes.
MfG Spess
spess53 schrieb:> So funktioniert das nicht. Der Takt zum Lesen muss vom Master erzeugt> werden. Und das geschieht durch Senden eines Dummybytes.
Hmmm, hab ich eigentlich schon ausprobiert, das wollte aber auch nicht
so recht funktionieren :/ Kannst du mir evtl. mal ein Codebeispiel dafür
geben?
danke :)
T.K. schrieb:> spess53 schrieb:>> So funktioniert das nicht. Der Takt zum Lesen muss vom Master erzeugt>> werden. Und das geschieht durch Senden eines Dummybytes.>> Hmmm, hab ich eigentlich schon ausprobiert, das wollte aber auch nicht> so recht funktionieren :
Das mag schon sein, dass da noch mehr im Argen liegt.
Daaaas ist allerdings mit Sicherheit eines deiner Probleme.
> Kannst du mir evtl. mal ein Codebeispiel dafür> geben?
Ist doch simpel.
Der Slave kann nur senden, wenn ihm der Master einen Takt generiert.
Damit der Master den Takt generiert, muss er selber was senden.
Ergo
1
for(i=0;i<64;i++){
2
SPDR=0x00;// wenn es nur darauf ankommt, dass der Slave 1 Byte loswerden kann
3
// ist es normalerweise wurscht, was der Master sendet
4
while(!(SPSR&(1<<SPIF)))
5
;
6
a[i]=SPDR;
7
}
Das größte MIssverständnis bei SPI schein es zu sein, dass es da sowas
wie senden und empfangen getrennt gäbe. Tatsächlich ist es so, dass es
eigentlich nur einen Byteaustausch gibt. Der Master übergibt 1 Byte an
den Slave und zur gleichen Zeit übergibt der Slave 1 Byte an den Master.
Die beiden Dinge sind unterennbar miteinander verbunden, wobei der
Master zu jeder Zeit die Kontrolle hat. D.h. der Slave kann von sich aus
überhaupt nichts tun, der Master muss alles anleiern.
Sinnigerweise steckt man den 'Baustein'
spess53 schrieb:> Hi>> Da dir Assembler wahrscheinlich nichts nutzt, hier eine Routine aus> einer Atmel Appnote:> char spi_transfer(volatile char data)> {> SPDR = data; // Start the transmission> while (!(SPSR & (1<<SPIF))) // Wait the end of the transmission> {};> return SPDR; // return the received byte> }>> Zum Lesen ist der Inhalt von data irrelenant.>> MfG Spess
Ok danke ich werd damit mal etwas rumprobieren ;)
Da scheint wohl irgendwo anders noch ein Fehler zu sein, denn ich kann
nichtmal richtig Register auslesen (bekomme im Debugger an betreffender
Stelle immer 0 angezeigt), obwohl sie richtig beschrieben sein müssen,
da es auf der Transmitter-Seite funktioniert :o
T.K. schrieb:> Da scheint wohl irgendwo anders noch ein Fehler zu sein, denn ich kann> nichtmal richtig Register auslesen (bekomme im Debugger an betreffender> Stelle immer 0 angezeigt), obwohl sie richtig beschrieben sein müssen,> da es auf der Transmitter-Seite funktioniert :o
Na ja.
überleg mal.
Wie soll denn der Slave den Registerinhalt zur Datenübertragung bereit
stellen, wenn ee noch gar nicht weiß, welches Register du haben willst?
SPI ist ein Byteaustausch!
mit dem ersten Austausch, teilst du dem Slave mit, was du von ihm
willst. Mit dem zweiten Austausch hat der Slave dann die Gelegenheit das
gewünschte zu liefern.
Das hier
1
uint8_tRegister_read(uint8_taddr){
2
uint8_ttmp;
3
PORTB&=~(1<<SCS);
4
SPDR|=(addr|0x40);
5
while(!(SPSR&(1<<SPIF)));
6
tmp=SPDR;
7
PORTB|=(1<<SCS);
8
returntmp;
9
}
kann nicht funktionieren. Denn dazu müsste der Slave schon Hellseher
sein um zu wissen, was er übertragen soll, noch ehe er vom Master die
Anforderung vollständig 'in der Hand hat'.
SPI ist ein Austausch von Informationen.
So wie du und dein Kumpel, die ihr euch am Tisch gegenüber sitzt. Jeder
hat einen Zettel in der rechten Hand auf den jeder was schreiben kann.
Gleichzeitig streckt jeder die rechte Hand aus und schiebt den Zettel
zum Gegenüber hinüber, den der dann mit der linken Hand nimmt. Ihr
tauschr IMMER die Zettel aus. Es gibt nicht den Fall, dass du den Zettel
rüberschiebst und dein Kumpel tut nichts.Es ist IMMER ein Austausch.
D.h. du kannst auf deinen Zettel dfraufschreiben: Gib mir deine
Kontonummer.
Dann tauscht ihr die Zettel aus. Dein Kumpel kann jetzt deine
Anforderung lesen und seinerseits die Info auf den Zettel schreiben, den
er jetzt hat.
Damit die Information zu dir kommt, müsst ihr nochmal die Zettel
austauschen.
Und wahrscheinlich ist es auch eine gute Idee, wenn du deinem Kumpel ein
wenig Zeit gibst die angeorderte Information auch bereit zu stellen.
Denn der braucht ja auch ein bischen Zeit, um die Kontonummer von der
EC-Karte auf den Zettel abzumalen. Wenn du also sofort nach dem ersten
Austausch den zweiten anleierst, dann wird der noch nicht fertig sein,
und der Zettel den er dir im Austausch rüberschieben muss, wird noch
leer sein, weil er ganz einfach in der Zeit nicht fertig geworden ist.
So funktioniert SPI.
Karl Heinz schrieb:> kommt mir allerdings schon sehr seltsam vor.> Wozu soll man da eine 0x45 in den unbekannten Inhalt von SPDR rein> odern?
0x40 ist der Befehl zum Auslesen und verodert mit 0x05, dem Register,
indem die FIFO-Daten sind.
Karl Heinz schrieb:> kann nicht funktionieren. Denn dazu müsste der Slave schon Hellseher> sein um zu wissen, was er übertragen soll, noch ehe er vom Master die> Anforderung vollständig 'in der Hand hat'.
Ja genau das versteh ich nicht. Eigentlich bekommt er doch den Befehl,
dass er jetzt die Daten aus dem FIFO senden soll, also müsste ich sie
doch im nächsten Zug über SPDR Stück für Stück auslesen können oder etwa
nicht? :o
Karl Heinz schrieb:> So wie du und dein Kumpel, die ihr euch am Tisch gegenüber sitzt. Jeder> hat einen Zettel in der rechten Hand auf den jeder was schreiben kann.> Gleichzeitig streckt jeder die rechte Hand aus und schiebt den Zettel> zum Gegenüber hinüber, den der dann mit der linken Hand nimmt. Ihr> tauschr IMMER die Zettel aus. Es gibt nicht den Fall, dass du den Zettel> rüberschiebst und dein Kumpel tut nichts.Es ist IMMER ein Austausch.> D.h. du kannst auf deinen Zettel dfraufschreiben: Gib mir deine> Kontonummer.> Dann tauscht ihr die Zettel aus. Dein Kumpel kann jetzt deine> Anforderung lesen und seinerseits die Info auf den Zettel schreiben, den> er jetzt hat.> Damit die Information zu dir kommt, müsst ihr nochmal die Zettel> austauschen.> Und wahrscheinlich ist es auch eine gute Idee, wenn du deinem Kumpel ein> wenig Zeit gibst die angeorderte Information auch bereit zu stellen.
Die Erklärung ist TOP ;) aber was meinst du mit "Zeit geben"? reichen
die while-Schleifen aus, oder muss beim Einlesen auch auf etwas gewartet
werden?
T.K. schrieb:> Karl Heinz schrieb:>> kommt mir allerdings schon sehr seltsam vor.>> Wozu soll man da eine 0x45 in den unbekannten Inhalt von SPDR rein>> odern?>> 0x40 ist der Befehl zum Auslesen und verodert mit 0x05, dem Register,> indem die FIFO-Daten sind.
Schon. Und das ganze verodert mit dem momentanten INhalt von SPDR, den
du nicht kennst.
Wozu verodern?
Wenn du 0x45 rüberschieben musst, dann doch ganz einfach
T.K. schrieb:> Die Erklärung ist TOP ;) aber was meinst du mit "Zeit geben"?
Na Zeit geben. Zwischen 'Ich will das und das von dir' und 'rück mal mit
der Info rüber', muss dein Gegenüber Zeit haben, die Info zu besorgen.
> reichen> die while-Schleifen aus
die while Schleife behandelt nur den Fall, dass das Hand ausstrecken und
Zettel rüberschieben ja auch Zeit braucht. Mit
1
SPDR=....
beginnt das Ausstrecken der rechten Hand.
Von diesem Zeitpunkt an dauert es aber eine gewisse Zeit, bis du dann in
der linken Hand den Zettel vom Gegenüber tatsächlich verfügbar hast.
Diese Zeit ist rein nur die Zeit, die der Datenaustausch an sich
braucht.
1
uint8_tRegister_read(uint8_taddr)
2
{
3
uint8_ttmp;
4
5
PORTB&=~(1<<SCS);
6
7
spi_transfer(addr|0x40);// Anforderung schicken
8
9
_delay_us(.....);// hängt vom Slave und/oder vom konkreten 'Befehl' ab
10
// die zeit muss ich dem Slave geben, damit der die gewünschte
T.K. schrieb:> Ja genau das versteh ich nicht.
Da sich die Posts überschnitten haben:
Hast du es jetzt? Verstehst du, wo in deinem Code das Problem ist?
> doch im nächsten Zug über SPDR Stück für Stück auslesen können oder etwa> nicht? :o
Schon.
Aber jedes 'Stück' beinhaltet, dass der Master seinerseits etwas
rüberschiecken muss. Denn von sich aus kann der Slave nichts tun.
Oder beim Beispiel:
Dein Kumpel kann nicht von sich aus den rechten Arm ausstrecken und
einen Zettel rüberschieben. Die Aktion geht IMMER von dir aus. Aber wenn
du den Arm ausstreckst, dann muss das dein Kumpel auch tun. Er hat keine
andere Wahl. Egal ob er den Zettel schon mit der angeforderten
Information schon beschrieben hat oder nicht. Du hingegen hast rein vom
Mechanismus her keine Möglichkeit festzustellen, ob er mit der
Informationsbeschaffung schon fertig ist oder nicht. Du kannst ihm
lediglich deiner Ansicht nach genügend Zeit geben (bzw. im Handbuch
nachsehen, ob da was steht, wie lange du warten musst)
Karl Heinz schrieb:> Da sich die Posts überschnitten haben:> Hast du es jetzt? Verstehst du, wo in deinem Code das Problem ist?
Ahhh ok. Ja glaube schon, das macht Sinn ;D
Habe nach wie vor ein Problem mit dem Auslesen der Register es kommt
immernoch tmp=0, aber bin denk ich schon ein großes Stück vorwärts
gekommen vor allem vom Verständnis her ;)
Danke :)