Hi,
ich möchte mit meinem ATXMEGA 256 D3 so schnell wie möglich Datenpakete
über SPI schicken. Dazu habe ich ihn wie folgt konfiguriert:
Interner Oszillator auf 32 Mhz hoch multipliziert,
SS als Ausgang mit wired And pullups,
SPI Mode 0,
Interrupts aus.
Ich schicke ein Datenarray mit 8 Bytes Inhalt zu meinem Slave.
Nun kommt mein Problem:
Wenn ich die SPI Geschwindigkeit so konfiguriere, das es schneller geht
als 2 Mhz gehen regelmäßig Bytes verloren.
Dies beobachte ich mit Hilfe des AARDVARK(Beagle) SPI/I2C Protocol
Analyzer von Totalphase.com .
Hat jemand eine Idee, wie ich SPI Datenpakete schneller als 2 Mhz
verschicken kann, ohne das Bytes verloren gehen?
Ich würde gerne mit 8 oder mehr Mhz senden können.
Vielen Dank
Das ist ein programmtechnisches Problem. Der XMega kann SPI-Daten mit
Fcpu/2 als SPI-Clock versenden. Allerdings ist die Nettorate etwas
niedriger, da der XMega jedes Byte nachladen muss. Oder Du nimmst DMA,
dann geht´s schneller.
Sylvia H. schrieb:> warum kann nun der ATXMEGA aber wenn ich höher als 2 Mhz sende mit den> Datenpaketen auf SPI nicht mehr mithalten?
Der XMega kann, glaub mir. Wartest Du auf das Interrupt-Flag des SPI und
löschst Du dieses auch (oder Deine ISR)? Wenn nicht, überscheibst Du
vielleicht das Datenregister, während noch gesendet wird?
ich benutze den von ATMEL zur verfügung gestellten spi_driver
mein code ist:
for(uint8_t i = 0; i < =8; i++) {
/* Transmit data from master to slave. */
SPI_MasterTransceiveByte(&spiMasterC, masterSendData[i]);
}
damit sende ich 8 Byte
die Methode SPI_MasterTransceiveByte(bla)
sieht fogendermaßen aus:
uint8_t SPI_MasterTransceiveByte(SPI_Master_t *spi, uint8_t TXdata)
{
/* Send pattern. */
spi->module->DATA = TXdata;
/* Wait for transmission complete. */
while(!(spi->module->STATUS & SPI_IF_bm)) {
}
/* Read received data. */
uint8_t result = spi->module->DATA;
return(result);
}
Dort müsste meiner Meinung nach alles stimmen
ich habe mal versucht alle Leitungen zu kürzen,
(SPI möchte ja keine langen Leitungen)
und trotzdem:
bei 2Mhz werden alle 8 Byte ordendlich verschickt,
bei 4Mhz werden die letzten 2 Byte "verschluckt" und erscheinen erst gar
nicht auf dem Bus......
Ich kenne mich (noch ;-) ) mit den ATXMEGAs nicht so gut aus, aber muss
man das Interrupt-Flag nicht explizit löschen, wenn man keine
ISR-Routine ausführt?
update: Hm. Laut AVR1309 muss man das offenbar nicht. Mein Irrtum.
Mit welcher maximalen Rate habt ihr die 8 Byte übertragen können? Also
gemessen von SS/CS auf Null bis SS/Cs auf High. Ich komme bei einer
Übertragung von 3 Byte mit den oben aufgeführten Befehlen auf ca. 7kHz
und würde gerne wissen, ob das schon am Limit ist, bzw. ob Ihr da
wesentlich schneller seit.
@ Jan-Henrik Bathelt (vedaykin)
>Mit welcher maximalen Rate habt ihr die 8 Byte übertragen können?
Lesen? F_CPU/2, hier also 16 MHz.
>Also>gemessen von SS/CS auf Null bis SS/Cs auf High. Ich komme bei einer>Übertragung von 3 Byte mit den oben aufgeführten Befehlen auf ca. 7kHz
Rechnen?
8 byte x 8 Bit x 1/16 Mhz = 4µs.
Mit ner Handvoll Takte für CS LOW/High vielleicht 5µs, macht 200kHz.
Wenn man diese maximale Geschwindigkeit erreichen will, muss man aber
das alles in EINER Funktion zusammenfassen oder SPI_MasterTransceiveByte
als inline deklarieren. Sonst wird sinnlos zeit mit Funktionsaufrufen
verplempert.
Hallo,
Sylvia H. schrieb:> Ich würde gerne mit 8 oder mehr Mhz senden können.
teste es mal mit einen herkömmlichen Spi-Treiber.
Der ist zwar jetzt auf SPID eingestellt, läßt sich aber leicht auf SPIC
usw. umstellen. Interrupt wäre auch möglich.
spidTransferByte(xx) oder spidTransferWord(xxxx)
Gruß G.G.
Hallo,
@Frank Brunner: Genau das mit den einzelnen Funktionsaufrufen ist auch
mein aktuelles Problem, da ich mit dem ATXMega bisher immer nur 1 Byte
übertragen kann. Zwischen den Aufrufen vergeht unglaublich viel Zeit,
nicht ganz unverständlich mit den ganzen Fehlerroutinen, aber noch nicht
völlig verstanden auf meiner Seite. Ich habe es noch nicht
geschafft/angefangen alles in EINER Funktion zu verpacken. Danke für die
Abschätzung was möglich wäre, wenn nicht auf die vordefinierten
Funktionen zurückgegriffen würde.
@G.G.: Danke für den Beispiel-Code.
Grüße,
Jan
Hallo,
@ G.G.: Also die Übertragung der Bytes funktioniert noch einen Tick
schneller, jedoch wird 80% der Zeit bei mir mit Pausen verschwendet. Du
überträgst 2 x 1 Byte in der Funktion spidTransferWord(xxxx) unter
verwendung der Funktion spidTransferByte(xx). Es dauert die Übertragung
der 3 Bytes aufsummiert ca. 30us, topp!! ;). Allerdings habe ich
insgesamt über 100us Pausen zwischendrin. Also eine Pause zwischen der
Übertragung zweier Bytes ist größer, als die Übertragung des
eigentlichen.
Ich habe das Problem bzw. werde gezwungen, dass ich Daten in SPIC_DATA
schreiben muss. Was in der iox256a3.h als "#define SPIC_DATA
_SFR_MEM8(0x08C3)" steht. Hier kann ich ja nur ein Byte reinschreiben.
Also ist mir die Übertragung von z.B. einem Wort in einem Schritt mit
dem Hardware SPI nicht möglich?
Im Anhang ein Screenshot. Gelb: Die 3 Bytes, Lila: CS-Kanal.
Grüße,
Jan
So, laut Oszi läuft das ganze korrekt mit 20kHz, jedoch scheint es, als
ob die Daten noch nicht in "SPIC_DATA" abholbereit sind. Die Werte die
ich jetzt auslese haben nichts mit der anliegenden analogen Spannung am
ADC zu tun. Wenn ich den Prescaler von 4 auf 16 hochsetze, dann werden
wieder die korrekten analogen Werte gelesen. Ich warte doch schon auf
die Statusmeldung des SPI, ob auch alle Daten übertragen worden sind.
Hat jemand eine Ahnung, warum die Daten anscheinend doch noch nicht
richtig in "SPIC_DATA" angekommen sind, bzw. mache ich einen Fehler beim
Auslesen?
An MISO liegt ein richtiges Signal an. Der ADC wandelt korrekt. Alle
Signale sind sauber.
Grüße,
Jan
Eine eigene Frage?
Dieser Thread ist über 15 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.