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
Sylvia H. schrieb: > gehen regelmäßig Bytes verloren. Was meinst Du? Werden sie nicht gesendet oder werden sie nicht korrekt empfangen?
laut meinem "Spion" (der Protokol Analysator) werden sie nicht gesendet, sie tauchen überhaupt nicht auf dem Bus auf
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.
ok, Fcpu/2 ist in meinem Fall 16 Mhz warum kann nun der ATXMEGA aber wenn ich höher als 2 Mhz sende mit den Datenpaketen auf SPI nicht mehr mithalten?
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
@ Jan-Henrik Bathelt (vedaykin) > IMG_0294.JPG > 2,2 MB, 13 Downloads >jetzt aber... Eben, lies mal was über Bildformate!
Ich hab's verkleinert. Der Fokuspunkt ist zu nah gewählt, man kann das Gesicht des Fotografen nicht erkennen. ;-)
Daraus ein biometrisches Passfoto zu berechnen ist wahrscheinlich einfacher, als die Pausen wegzukriegen ;). Sorry für die 2MB.
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
1 | /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
2 | Variablendeklaration
|
3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
4 | |
5 | uint16_t gintI; //Testvariable |
6 | |
7 | /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
8 | ADC-Auslesen
|
9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
10 | |
11 | uint16_t read_MCP3204(void) |
12 | {
|
13 | uint8_t lintISPConfByte = 0b00000110;; |
14 | uint8_t lintByte_high; |
15 | uint8_t lintByte_low; |
16 | uint8_t lintChannel = 0; |
17 | |
18 | PORTC.OUTCLR = PIN4_bm; //Übertragung starten, SS auf high |
19 | |
20 | SPIC_DATA = lintISPConfByte; //ADC-Initialisieren, Byte 1, siehe Datenblatt |
21 | while(!(SPIC.STATUS & (1<<SPI_IF_bp))) |
22 | |
23 | lintISPConfByte =lintChannel<<6; |
24 | |
25 | SPIC_DATA = lintISPConfByte; //ADC-Initialisieren, Byte 2, siehe Datenblatt |
26 | while(!(SPIC.STATUS & (1<<SPI_IF_bp))) |
27 | |
28 | lintByte_high = SPIC_DATA; //ADC-Auslesen |
29 | lintByte_high &= 0b00001111; // Nur die ersten 4 Bit in Byte 2 sind interessant bei einem 12Bit-Wandler |
30 | |
31 | SPIC_DATA = 0x00; //Ein Dummy-Byte durchschieben |
32 | while(!(SPIC.STATUS & (1<<SPI_IF_bp))) |
33 | |
34 | lintByte_low = SPIC_DATA; // Byte 3 ist ein reines Datenbyte des ADCs |
35 | |
36 | PORTC.OUTSET = PIN4_bm; //Übertragung stoppen, SS auf high |
37 | |
38 | return ((lintByte_high<<8)|lintByte_low); //Zusammenbau des 12Bit Messwertes und Rückgabe |
39 | }
|
40 | |
41 | /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
42 | Hauptprogramm/Main
|
43 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
44 | |
45 | int main( void ){ |
46 | |
47 | ClockSystemIni(); |
48 | SPIInit(); |
49 | sei(); |
50 | |
51 | while (true) |
52 | {
|
53 | gintI = read_MCP3204(); |
54 | }
|
55 | }
|
56 | |
57 | /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
58 | Initialisierungsfunktionen
|
59 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
60 | |
61 | //Configure XMega Clock, clock system @ 32Mhz , PERCLK is 16 Mhz
|
62 | void ClockSystemIni( void ) |
63 | {
|
64 | OSC.CTRL = OSC_RC32MEN_bm; //Start internal 32MHz RC oscillator |
65 | do { |
66 | } while ( ( OSC.STATUS & OSC_RC2MRDY_bm ) == 0 ); //Wait while oscillator stabilizes |
67 | CCP = CCP_IOREG_gc; |
68 | CLK.PSCTRL = (CLK_PSADIV_1_gc | CLK_PSBCDIV_1_1_gc); //Enable prescaler A div by 1 and B and C to div by 2 |
69 | CCP = CCP_IOREG_gc; |
70 | CLK.CTRL = CLK_SCLKSEL_RC32M_gc; //Select 32 MHz as master clock |
71 | }
|
72 | //Configure SPI-BUS
|
73 | void SPIInit() |
74 | {
|
75 | SPICPort_Init(); //max Spi-Takt F_CPU/2 = 16 Mhz. Pinkonfiguration für SPI-Master |
76 | SPIC.CTRL = SPI_MODE_0_gc | SPI_PRESCALER_DIV4_gc | (1<< SPI_CLK2X_bp) | (1<< SPI_ENABLE_bp) | (1<< SPI_MASTER_bp); |
77 | SPIC.STATUS = 0; |
78 | SPIC.INTCTRL = SPI_INTLVL_MED_gc; |
79 | }
|
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.