Forum: Mikrocontroller und Digitale Elektronik XMega SPI über USART


von Tobias K. (tobi123)


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?

von Tobias K. (tobi123)


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.

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
Noch kein Account? Hier anmelden.