XMega SPI über USART

OP #1394813
Lesenswert?
• ▲
▼
Ich nutze erfolgreich den SPI Bus, um Daten auf eine SD-Karte zu loggen. 
Nun möchte ich die DMA Funktionalität des XMega128A1 nutzen, um den 
Prozessor beim Schreiben der FAT Sektoren zu entlasten. DMA funktioniert 
aber nur, wenn man SPI über USART nutzt.

Nun habe ich zum SPI Mastermode des USART Fragen, da es bei mir noch 
nicht funktionieren will. Hier erstmal die Initialisierung:
1
#define SCK 5   // USART XCK 
2
#define MISO 6  // USART RxD
3
#define MOSI 7  // USART TxD
4
#define SS 4    // just an output pin
5

6
// set the TxD pin value high, and optionally the XCK pin low
7
PORTD.OUTSET = (1 << MOSI);
8
PORTD.OUTCLR = (1 << SCK);            
9

10
// set the TxD and optionally the XCK pin as output
11
// and chip select as output
12
PORTD.DIRSET = (1 << MOSI) | (1 << SCK) | (1 << SS);
13

14
// MISO is input
15
PORTD.DIRCLR = (1 << MISO); 
16

17
// max 400 kHz allowed during initialization
18
// 29.4912 MHz / (2 * (39 + 1)) = 368.64 kHz
19
USARTD1.BAUDCTRLA = 39;
20
USARTD1.BAUDCTRLB = 0; 
21
    
22
// set spi mode and bitsize
23
USARTD1.CTRLC = USART_CMODE_MSPI_gc | USART_CHSIZE_8BIT_gc;
24

25
// interrupt
26
USARTD1.CTRLA = USART_RXCINTLVL_LO_gc;
27

28
// enable RX and TX
29
USARTD1.CTRLB = USART_RXEN_bm | USART_TXEN_bm;

Danach schalte ich die Interrupts ein, setze Chipselect und sende über 
USARTD1.DATA.
Ist es nun richtig, den Receive Complete Interrupt (USARTD1_RXC_vect) zu 
nutzen? Er wird bei mir aufgerufen, aber das Empfangene Byte ist immer 
0. Beim "normalen" SPI kommt hier 0xFF von der SD-Karte. Vorher habe ich 
den Data Register Empty Interrupt genutzt, aber durch die Bufferung im 
USART macht das glaube ich beim USART keinen Sinn.

Also wie nutze ich SPI über USART richtig? Hat das schonmal jemand von 
euch hinbekommen?
OP #1395121
Lesenswert?
• ▲
▼
Habe den Fehler entdeckt:
1
// set spi mode and bitsize
2
USARTD1.CTRLC = USART_CMODE_MSPI_gc | USART_CHSIZE_8BIT_gc;

Bitsize gibt es im SPI Modus nicht und die enstprechenden Bits im CTRL 
Register haben daher eine andere Funktion (UDORD und UCPHA). Durch meine 
Zuweisung werden daher UDORD und UCPHA falsch gesetzt, sie mussten auf 0 
stehen. Richtig ist daher
1
// set spi mode 
2
USARTD1.CTRLC = USART_CMODE_MSPI_gc;

Offensichtlich gibt es den USART SPI Modus nicht erst beim XMega. Hier 
habe ich eine Application Note zum Thema gefunden:
http://www.atmel.com/dyn/resources/prod_documents/doc2577.pdf

Zum Thema Interrupts:
- Will man nur senden, dann kann man den Data Register Empty Interrupt 
nutzen um ein neues Byte zu schreiben. Durch die Pufferung des 
Senderegisters kriegt man dadurch die Bytes schneller raus als beim 
normalen SPI.

- Zum Empfangen sendet man wie immer erst ein Byte und wartet dann auf 
den Receive Complete Interrupt.

Ich werde jetzt DMA ausprobieren, aber dieser Thread ist wohl hiermit 
erledigt.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.