Hallo an alle, ich habe ein kleines Problem. Ich schreibe gerade einen Linux Treiber auf der anderen Seite ist ein Atmega128rf1a. Die Linuxkiste sendet eine SPI Message (0xac) daraufhin soll der Atmega etwas zurücksenden. Die Linuxkiste ist der Master. Weiterhin wird der CS zwischen den 8 Bit Packeten nicht getriggert bleibt also immer low während der Übertragung. Beispielcode: static int ui8Frame_Counter; static u8 ui8Message_Buffer[250]; ISR (SPI_STC_vect) { if (SPDR == 0xac){ status = 1; ui8Frame_Counter=0; } if (status== 1){ ui8Frame_Counter++; while(!(SPSR & (1<<SPIF))); get(); } } uint8_t get(){ SPDR = ui8Message_Buffer[ui8Frame_Counter]; } Wenn die SPI ISR das magische Kommando 0xac bekommt sollen die Daten die im Buffer ui8Message_Buffer stehen gesendet werden. Die Funktion get besorgt sicht einfach das nächte Byte aus dem Buffer und schreibt es in das Register. Nun kommt aber folgendes an meiner Linuxmaschine an: 0x05 0xac 0x06 0xac rauskommen sollte aber: 0x05 0x06 0x07 0x08 ... Merkwürdiger weise wird die ISR nicht immer aufgerufen! Nur jedes zweite Packet kommt richtig an. Ich weiß einfach nicht warum. WEitere Infos: AUf dem Atmega läuft der AMTEL MAC Stack. Ich habe mal die Zeit zwischen zwei Packeten holen vergrößert -> Ergebnis war das gleiche. Weiß jemand woran das liegen kann? Wenn mehr infos benötigt werden liefer ich die gerne nach. LG MOE
1 | while(!(SPSR & (1<<SPIF))); |
in einer ISR auf das AUftreten eines Interrupt Flags zu warten, muss einem immer seltsam vorkommen. Die ISR ist aufgerufen worden, #WEIL# vom Master ein Byte angekommen ist. Du brauchst da nicht noch zusätzlich warten. Das Byte ist schon da! Mit Sicherheit. Sonst wäre die ISR nicht aufgerufen worden. Ganz im Gegenteil. MIt dem Betreten der ISR ist dieses Flag gelöscht worden, so dass du hier effektiv bereits auf das eintreffen des jeweils nächsten Bytes wartest. (Und ich denke genau das ist der Grund, warum du nur jeden 2.ten Interrupt siehst.)
Karl Heinz Buchegger schrieb: >
1 | > while(!(SPSR & (1<<SPIF))); |
2 | >
|
> > in einer ISR auf das AUftreten eines Interrupt Flags zu warten, muss > einem immer seltsam vorkommen. > > Die ISR ist aufgerufen worden, #WEIL# vom Master ein Byte angekommen > ist. Du brauchst da nicht noch zusätzlich warten. Das Byte ist schon da! > Mit Sicherheit. Sonst wäre die ISR nicht aufgerufen worden. > Ganz im Gegenteil. MIt dem Betreten der ISR ist dieses Flag gelöscht > worden, so dass du hier effektiv bereits auf das eintreffen des jeweils > nächsten Bytes wartest. > > (Und ich denke genau das ist der Grund, warum du nur jeden 2.ten > Interrupt siehst.) Ach Kopfschüttel. Alles klar! Vielen Dank
ICh muss nochmal stören ^^. Nun werden die Daten einfach nicht in das SPDR Register eingetragen ... Ergebnis ist: 0xac richtig 0xac falsch ... 0 0 0 0 0 Darf ich den in der ISR keine Funktion aufrufen, die das SPDR Register setzt? LG MOE
Ivo Kunadt schrieb: > Darf ich den in der ISR keine Funktion aufrufen, die das SPDR Register > setzt? Der Satz aus dem Datasheet zb des Mega8 macht mir Sorgen
1 | The system is single buffered in the transmit direction and double |
2 | buffered in the receive direction. |
3 | This means that bytes to be transmitted cannot be written to the SPI Data |
4 | Register before the entire shift cycle is completed. |
Mir ist nicht ganz klar, ob mit 'cannot be written ... before completed' eine aktive Verriegelung des Shift-Registers gemeint ist oder nicht. Das würde IMHO Bedeuten, dass der Master nach jedem Byte sinnvollerweise eine kleine Pause einlegen sollte, um so dem Slave die Zeit zu geben, das jeweils nächste Byte bereitzustellen, welches er sich mit der nächsten Übertragung des nächsten Bytes dann abholt. Ich würde das probehalber auf Linux-Seite mal so machen. Ansonsten gilt wie immer: aktueller Code muss her.
Karl Heinz Buchegger schrieb: > Das würde IMHO Bedeuten, dass der Master nach jedem Byte sinnvollerweise > eine kleine Pause einlegen sollte, um so dem Slave die Zeit zu geben, > das jeweils nächste Byte bereitzustellen, welches er sich mit der > nächsten Übertragung des nächsten Bytes dann abholt. Ja, das geht letztlich nur so. Microcontroller sind miserable SPI-Slaves, da beim SPI der Master komplett das Timing vorgibt und der Slave keine Chance hat, die weiße Flagge zu hissen und keuchend zu röcheln: "Ich kann gar nicht so schnell!" Braucbare SPI-Slaves muss man in Hardware implementieren, denn es ist weiter nichts als ein Schieberegister. Für Microcontroller und Software eignet sich I²C viel besser als Protokoll, denn dort kann der Slave (durch Festklemmen der SCL- Leitung) den Bus blockieren, bis er fertig ist.
HEHE ja wir wollten schon I2C nehmen aber SPI war schon im Kerneln von Linux für unser Board ... So nun mit ein wenig Delay funktionierts .... Sch ... DING! Vielen Dank für die ausführlich Hilfe!!!!! LG MOE
Das ist wie bei anderen Bussystemen auch. Der Master muss/sollte das (WorstCase) Timing der angeschl. Teilnehmer kennen, und danach handeln. (synchr) Optional kann (asynchr) der Slave ein Wait o.ä. zum Master schicken. IIC ist nur was für Stricknadel-Frequenzen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.