Bei AVR ATmega-Geräten kann der USART im SPI-Modus arbeiten (dh synchron ohne Start- oder Stoppbits). Der Hauptbetriebsunterschied besteht darin, dass die TX-Leitung (dh MOSI) einen Puffer hat, während das SPI-Hardware-MOSI keinen Puffer hat. Laut dieser Atmel Application Note ( http://www.atmel.com/Images/doc2577.pdf ) ermöglicht dieser Puffer die kontinuierliche Übertragung von Daten. Dies steht im Gegensatz zur SPI-Hardware, wo SCK angehalten werden muss, während ein neues Byte in SPDR geladen wird.
Welches der folgenden Programme zum Übertragen von 200 Bytes aus einem Puffer buf[200]
würde vor diesem Hintergrund in kürzester Zeit abgeschlossen werden? (Nehmen Sie an, dass alle unter konfiguriert sind fosc / 2
.)
Abgefragter SPI:
for(int B = 0; B < 200; ++B)
{
SPDR = buf[B]; // Load next byte into SPDR
while(!(SPSR & (1 << SPIF))); // Wait for SPIF to be set
(int)SPDR; // Read SPDR to clear SPIF
}
Interrupt-gesteuertes SPI:
ISR(SPI_STC_vect)
{
if(B < 200)
{
SPDR = buf[B]; // Load next byte into SPDR
++B;
}
else
{
SPCR &= ~(1 << SPIE); // Disable SPI interrupts
}
return;
}
Polled USART im SPI-Modus:
for(int B = 0; B < 200; ++B)
{
UDR0 = buf[B]; // Load next byte into UDR
while(!(UCSR0A & (1 << UDRE))); // Wait for UDR empty
}
Interrupt-gesteuerter USART im SPI-Modus:
ISR(USART0_UDRE_vect)
{
if(B < 200)
{
UDR0 = buf[B]; // Load next byte into SPDR
++B;
}
else
{
UCSR0B &= ~(1 << UDRIE); // Disable UDRE interrupt
}
return;
}
Sofern nicht viele konkurrierende Interrupts vorhanden sind, wäre das Polling-USART-Verfahren am schnellsten.
Für schnelle SPI-Übertragungen (mit fosc/2
) wäre der Interrupt-Ein- und Ausgang zu lang, und die SPI-Methoden haben die in der Frage erwähnten Lücken.