Pregunta:
Sincronizar / tomar reloj externo para SPI en Arduino Due
wallenut
2016-05-27 01:00:51 UTC
view on stackexchange narkive permalink

Tengo un Arduino Due con un chip SAM3X8E y estoy tratando de leer datos SPI de una fuente externa que se comunica en SPI. Pude obtener datos identificando bytes específicos que son identificadores, pero me di cuenta de que el reloj de mi placa no está sincronizado con la fuente que ingresa. Imprimo los bytes en formato hexadecimal (08 00 FF AB, etc.) y cada mensaje es 128 bytes de longitud.

Para ser claros, la fuente es un maestro SPI que está enviando datos en su propia línea MOSI, pero actualmente estoy tratando a mi placa como un maestro ya que no sé cómo hacer el modo esclavo en el vencimiento. Conecto la línea Slaves MOSI a la línea MISO de mi placa, y simplemente transfiero datos y leo 128 bytes, pero parece que no obtengo los mismos datos. ¿Hay alguna forma de que pueda ver el reloj del reloj externo y sincronizar mi placa con ese reloj para asegurarme? Mi código fuente está a continuación. Los únicos métodos en los que puedo pensar son averiguar cómo implementar la placa en modo esclavo (no estoy lo suficientemente familiarizado con los registros y cómo cambiar esto, o leer datos en modo esclavo) o sincronizar los relojes para que mi placa está leyendo y muestreando los datos de origen correctamente.

¿Podría alguien comprobar si mi pensamiento es correcto o no necesito hacer ningún cambio ya que los datos están en un registro de desplazamiento?

Gracias


  void setup () {Serial.begin (9600); SPI.begin (); SPISettings settings (50000000, LSBFIRST, SPI_MODE1); // Tasa de muestreo 50Mhz, velocidad máxima de la fuente SPI.beginTransaction (configuración);} void loop () {int i = 0; valor uint8_t; valor = SPI.transfer (0x00); while (value! = 8) {// buscando el identificador 0x08 value = SPI.transfer (0x00); } SPI.transfer (búfer, 127); // obtiene el resto de 127 bytes Serial.print (valor, HEX); Serial.print (""); for (i = 0; i < 127; i ++) {if (buffer [i] == 0) {Serial.print (buffer [i], HEX); Serial.print (0, HEX); } else {Serial.print (buffer [i], HEX); } Serial.print (""); } Serial.println ("\ n");}
 
One responder:
SoreDakeNoKoto
2016-05-27 02:00:45 UTC
view on stackexchange narkive permalink

Para que su fuente externa sea un maestro de bus SPI, debe ser la única que genere la señal de reloj. Sin embargo, llamar a SPI.transfer () también genera una señal de reloj desde Arduino ; ambos dispositivos están intentando controlar la línea de reloj simultáneamente, de ahí sus problemas.

Tiene que hacer un bit-bang o manipular los registros SAM usted mismo para configurarlo como esclavo; la biblioteca SPI no admite el modo esclavo.Para bit-bang, tendrá que definir sus propios pines MOSI, SCK, SS (y MISO, si va a escribir en el maestro) y hacer todo el muestreo usted mismo con digitalRead () ; no hay registros para leer ya que no está utilizando el periférico SPI de SAM.

Dado que su modo SPI es el MODO 1, significa que la polaridad inactiva del reloj es BAJA y que los datos se muestrean en el flanco descendente. Para hacer bit-bang con digitalRead () , es necesario que la frecuencia SCK esté por debajo de 50 kHz ( digitalRead () tarda alrededor de 4us), teniendo en cuenta los gastos generales. Debe utilizar la manipulación directa del puerto, si necesita una frecuencia más alta. Si estará bloqueando hasta que haya leído los datos y asumiendo que la fuente externa siempre envía datos en unidades de bytes, entonces un algoritmo básico:

  1. Cree un byte código > matriz para contener todos los bytes esperados
  2. Defina una variable byte ( curr_byte , tal vez) para contener cada byte recibido
  3. Espere hasta que el pin SS pase a BAJO
  4. Borre curr_byte a cero
  5. Espere hasta que SCK pase a ALTO
  6. Espere hasta que SCK pase a BAJO
  7. Lea el bit en la línea MOSI y cámbielo a curr_byte
  8. Si ha recibido hasta 8 bits hasta ahora, guarde curr_byte al arreglo byte ; si SS todavía es BAJO, vaya al paso 4, de lo contrario salga de este ciclo. Pero si aún no ha recibido un byte completo, vaya al paso 5.

Después de salir del bucle, puede confirmar los bytes que recibió con Serial. Si el dispositivo externo puede enviar datos con cualquier número de bits, entonces siempre debe verificar la línea SS después de cambiar un bit, para determinar si el Due ha sido deseleccionado o no, es decir, si hay más bits entrantes.

Gracias, eso parece tener sentido. Creo que entiendo el bit-banging, pero estoy confundido sobre cómo debo muestrear en consecuencia, ya que no puedo llamar a SPI.transfer (). ¿Está leyendo de SPDR o del registro de datos? Porque en Arduinho Due, no creo que reconozca SPDR, pero el objetivo debería ser esperar hasta que SCK sea alto y luego leer desde el registro de datos respectivo. Simplemente no estoy seguro de cómo o qué registro se encontrarán los datos MOSI externos entrantes.
@wallenut He editado mi respuesta.
Eso lo aclara mucho. Gracias, solo tengo que ocuparme de localizar dónde se transfieren los datos MOSI a los registros y leerlos, y debería estar bien.
Tu ayuda responde a mi pregunta. Simplemente no creo que funcione para la alta velocidad de reloj a la que envía datos (50 Mhz). Voy a perder el tiempo e intentar cambiar los registros y operarlo en modo esclavo, pero no hay mucha documentación debida de Arduino para el modo esclavo. ¿Algún consejo sobre cómo utilizar la hoja de datos de Atmel? Este es mi primer proyecto real de Arduino.
@wallenut No podrá alcanzar los 50 MHz; el Due tiene un reloj de 84 MHz y el prescaler SPI más bajo es 2, lo que le da una frecuencia SCK máxima de 42 MHz. ¿Es posible que el maestro envíe datos a velocidades más bajas? Para ver una muestra de un boceto esclavo Due, mira esto: https://github.com/manitou48/DUEZoo/blob/master/spislave.ino. Tendrá que cambiar el modo SPI a MODE1 en el esquema, configurar la velocidad del reloj con `SPI.setClckDivider (SPI_CLOCK_DIV2)` y adaptar el `loop ()` para sus propósitos. Sin embargo, no he usado un Due antes, por lo que puede que no sea de mucha ayuda.


Esta pregunta y respuesta fue traducida automáticamente del idioma inglés.El contenido original está disponible en stackexchange, a quien agradecemos la licencia cc by-sa 3.0 bajo la que se distribuye.
Loading...