Preguntas Atmega16 SPI

0

Tengo un problema para entender la función de transmisión de SPI en atmega16 la función que no entiendo es

void SPI_SendByte (s8_t data){             
SPDR = data;

/* check if operation of transmit or receive is running */
while (bit_is_clear(SPSR,SPIF));

}

Creo que debería reemplazar las dos líneas como esta aquí

void SPI_SendByte (s8_t data){             

/* check if operation of transmit or receive is running */
while (bit_is_clear(SPSR,SPIF));

SPDR = data;

}

¿no se supone que debemos comprobar si está ocupado primero y luego escribir los datos? ¿Por qué hicimos lo contrario? En otro protocolo de comunicación como UART, por ejemplo, primero comprobamos si está ocupado y luego escribimos para registrarnos, ¿por qué no es lo mismo en SPI?

    
pregunta Mustafa Bahaa

3 respuestas

2

Supone que SPIF es inicialmente 1, lo que indicaría que SPDR puede estar escrito de forma segura; en otras palabras, espera que SPIF sea un indicador de disponibilidad / ocupado . Sin embargo, esto no es coherente con la definición real de que SPIF es un indicador de operación finalizada ( S erial P eripheral I nterface F inished).

De acuerdo con Hoja de datos de ATmega16 , SPSR - SPI Status Register bit El valor inicial de SPIF es en realidad 0, no 1. En su segundo ejemplo de código, la declaración

while (bit_is_clear(SPSR,SPIF));

es un bucle infinito si SPIF inicialmente es 0 y no se han escrito datos en SPDR.

Una operación no puede terminar antes de que comience. SPIF nunca será 1 hasta que el primer byte de datos se escriba en SPDR y los datos se transmitan posteriormente por SPI.

    
respondido por el MarkU
3

De la hoja de datos:

  

... al escribir un byte en el registro de datos SPI, se inicia el generador de reloj SPI y el hardware cambia los ocho bits al esclavo. Después de cambiar un byte, el generador de reloj SPI se detiene y establece el final del indicador de transmisión (SPIF).

Escribir el byte es lo que inicia la transferencia SPI. Si no escribe el byte, la transferencia no se iniciará y, por lo tanto, nunca podrá terminar.

    
respondido por el Ignacio Vazquez-Abrams
2

No considero que ninguno de los dos enfoques sea "bueno", ya que ambos representan un método de espera ocupada . Utilizo diferentes enfoques, a menos que todo lo que esté haciendo sea una prueba de algún tipo y no se use de forma regular (o no tengo otra opción).

Sin embargo, los dos enfoques son equivalentes.

En el primer caso, la rutina siempre supone que el búfer de datos está disponible para escritura. Así que simplemente escribe el valor, sin demora. Luego, después, espera. De esta manera, la rutina nunca se va hasta que pueda garantizar que los datos ya se han enviado y que el búfer está nuevamente listo para aceptar datos. La próxima vez, siempre que esta suposición siga siendo válida, debería funcionar.

En el segundo caso, la rutina no asume que el búfer de datos está listo. Así que espera. Luego escribe los datos y se va de inmediato, donde es casi seguro que aún no se transmiten. Por lo tanto, esta rutina debe, por supuesto, verificar si se envió al comienzo del código.

Son solo dos formas de hacer lo mismo. Sin embargo, las dos rutinas NO son compatibles. Usted utiliza uno. O usas el otro. Pero no ambos.

    
respondido por el jonk

Lea otras preguntas en las etiquetas