¿Cómo puedo recibir varios bytes en SPI con CS bajo?

2

Tengo un FPGA que envía un flujo de bits a través de SPI que se comunican a 3 AD8403 conectados en cadena. El FPGA mantiene el CS bajo, hasta que se hayan transmitido 30 bits (2 bits de dirección, 8 bits de datos x 3), y luego el CS alto.

La forma en que se configuran los AD8403 es que a medida que entran los bits, se desplazan al siguiente chip si el registro de desplazamiento interno está lleno . Los primeros 10 bits transmitidos se convierten en los datos del último AD8403 y los 10 bits siguientes se convierten en los datos del segundo AD8403 y, finalmente, los últimos 10 bits transmitidos se convierten en los datos del primer AD8403.

Necesitopoderleerestosdatostambién.EstoypensandoensimplementeaprovecharelSDI(MOSI)delprimerchip.NoheusadoSPIenmodoesclavoenunmicrocontroladorantes,asíqueestoyunpocoperdidoencuantoacómofuncionalarecepción.

Estoyconsiderandoelusode AT32UC3C2256C (AVR32) para esta tarea. Puede transmitir 8/16 bytes y asumo que puede recibir lo mismo, pero ¿puede recibir un número arbitrario de bits? El FIFO tiene 4 capas de profundidad, por lo que tendría que leer los datos y almacenarlos en otro lugar.

Pregunta: ¿Cómo puedo recibir un número arbitrario de bits (múltiplos de 10) correctamente?

    
pregunta efox29

2 respuestas

2

Hice lo mismo en un AT32UC3C0512 (sin embargo, fui el maestro que probablemente lo hizo un poco más fácil).

La idea es probablemente la siguiente (si está utilizando el marco ASF, también debería funcionar en modo esclavo):

  • Call spi_get (SPI)
  • Bucle hasta spi_is_rx_ready (SPI) o hasta que se agote el tiempo de espera
  • Llame a spi_get (SPI) para el siguiente byte (o 10 bytes o lo que sea que establezca para que sea el tamaño del registro spi_rx)
  • Haga esto varias veces hasta que reciba todos los bytes

Aquí hay algo de código como punto de partida, espero que ayude un poco:

volatile avr32_spi_t *spi = device->spi;
unsigned int timeout = SPI_TIMEOUT;    

timeout = SPI_TIMEOUT;
while (!spi_is_rx_ready(spi)) {
    if (!timeout--) {
        tmc260_deselect_device(device);
        return ERR_TIMEOUT;
    }
}
// Store the received data
rx_msb = spi_get(spi);

No estoy muy seguro de lo que se debe hacer para restablecer el indicador que se establece una vez que se recibió un byte. Supongo que simplemente leyendo el registro rx debería hacer el truco.

También debería ser posible portar este código para usar interrupciones (llame al ISR siempre que se reciba un byte / el registro de RX esté lleno).

De la hoja de datos AT32UC3C0512:

El SPI espera a que NSS se active antes de recibir el reloj serial de un maestro externo. Cuando NSS cae, el reloj se valida en el serializador, que procesa el número de bits definido por el campo Bits por transferencia del Registro de selección de chip 0 (CSR0.BITS). Estos bits son procesados siguiendo una fase y una polaridad definidas respectivamente por la CSR0.NCPHA y CSR0.CPOL bits. Tenga en cuenta que los bits BITS, CPOL y NCPHA de los otros registros de selección de chip no tiene ningún efecto cuando el SPI está configurado en modo esclavo. Los bits se desplazan en la línea MISO y se muestrean en la línea MOSI. Cuando se procesan todos los bits, los datos recibidos se transfieren en el Registro de datos de recepción y el bit SR.RDRF aumenta. Si el registro RDR no se ha leído antes de recibir nuevos datos, Se establece el bit SR.OVRES. Los datos se cargan en RDR incluso si este indicador está establecido. El usuario tiene que leer el Registro SR para borrar el bit SR.OVRES.

Por lo que yo entiendo, se establecerá una bandera después de 8 a 10 bases de datos. Para un primer intento, deberás leer los datos y ver si la bandera se levanta una segunda vez, incluso si CS no se afirma por segunda vez.

Una solución alternativa

También puede usar una interrupción en la línea SCK (dependiendo del modo en el flanco ascendente o descendente) y muestrear los datos "manualmente". Una vez que descubre una condición en la que SCK aumenta (o disminuye) y CS es alta, está fuera de la transferencia de datos "normal" y comienza una nueva recepción.

    
respondido por el Tom L.
1

Podría conectar en cadena 4x 74xx164 registros de desplazamiento en paralelo de entrada en serie, más algo de logica del pegamento; o podría usar un CPLD o un FPGA pequeño e implementar una lógica similar en eso. Todavía necesitaría conectar los 30 bits resultantes (32, 32, en realidad, pero puede ignorar 2) de salida paralela a algo para leerlos, probablemente su AVR32. Si eso es demasiada E / S, simplemente configúrelos como un bus de memoria: 2 bits de dirección, 8 bits de datos, solo lectura.

Mi recomendación sería un CPLD, porque generalmente almacenan su configuración en la memoria NV interna ("fusibles"), mientras que los FPGA generalmente requieren un dispositivo de memoria externo (aunque se pueden cargar desde una MCU).

    
respondido por el markt

Lea otras preguntas en las etiquetas