5 votos

Cómo utilizar ATmega328 SPI con un registro de desplazamiento de 31 bits

Estoy usando un Allegro 6280 PWM controlador de LED para un proyecto. Esto es un poco fría IC excepto por el hecho de que es un 31 bits de largo registro de entrada. Esto no es ningún problema si yo simplemente bucle a través de mi 31 bits y establecer el pin de los estados de acuerdo, pero estoy queriendo utilizar el atmega a bordo del SPI para acelerar un poco las cosas (el 6280 requiere una fuente de reloj externa para es de 10 bits de largo ciclo PWM).

El 31 de poco largo registro se parece a esto en mi aplicación donde R,G Y B indican el 10 bit PWM valores para el adjunto de LEDs.

0BBBBBBBBBBGGGGGGGGGGRRRRRRRRRR

Estos registros de desplazamiento son encadenable, así que he creado una lista enlazada para que los represente:

struct Pixel {
  uint16_t red;
  uint16_t green;
  uint16_t blue;
  Pixel *next;
};

Así, la idea es poner el pasador de baja, iterar a través de todos los Píxeles y, a continuación, después de enviar el último set el pestillo de alta cerrada de los datos en cada registro. Esto parece fácil, salvo que, debido a la desigual duración del registro tengo que construir desagradable código de aspecto de ser capaz de lazo en torno al principio de nuevo, de modo que nunca se envía a cualquier vacío bits. También, el pestillo puede suceder después de un número arbitrario de bits que se transmiten, no sólo de la última.

¿Alguien tiene alguna idea sobre cómo hacer esto, o estoy simplemente ladrando al árbol equivocado y se quedó con manualmente cambiando el pin de los estados?

Gracias.

5voto

mathewbutler Puntos 479

He sido el seguimiento de esta cuestión, y ya que nadie ha contestado, me voy a tomar una puñalada en ella. Me disculpo de antemano si mi razonamiento termina siendo imperfectos, pero voy a hacer mi mejor esfuerzo.

Creo que la posibilidad de la realización de su proyecto de trabajo depende del número de LEDs RGB que planea utilizar. He estado revisando el Allegro de la hoja de datos, y parece que es necesario vincular un IC con uno de cada color rojo, verde y azul Led (es decir, un píxel RGB). Todos los datos se transmiten por la cadena de 6280s.

Si usted desea tener un solo píxel RGB, o más específicamente, N píxeles mostrar la misma información temporal, entonces creo que usted puede ser capaz de salirse con la suya con SPI. Yo creo que tu lista enlazada idea es el camino correcto a seguir, pero, obviamente, la clave es pestillo de LI en el momento adecuado (cada 31 bits), y no será en 8 bits límites. La única SPI bibliotecas que he usado en micros tomar un byte, el reloj de los datos y la lectura de la respuesta byte. En su caso, usted tendrá que averiguar cómo hacer un SPI de la función que puede desencadenar LI durante un byte de transferencia.

Desde SPI requiere la transferencia de un byte a la vez, usted estará obligado a enviar a 32 bits cuando sólo desea 31. Para la 32 bits será en realidad la primera parte de su segundo conjunto de datos RGB. Deberás establecer LI antes de fichar a cabo la 32 bits. Para la siguiente ronda de los datos, se activará LI antes de fichar a cabo el 31 de bits. Usted podría ser capaz de hacer esto sin necesidad de escribir su propia SPI de la biblioteca, pero no estoy seguro.

Si usted desea apoyar el desplazamiento de datos, entonces las cosas van a ser un poco más complicado. Estoy teniendo un tiempo difícil la formulación de la explicación, pero la sincronización de LI va a ser interesante. LI determina la rapidez con que la pantalla se va a desplazar, ya que se dicta cuando uno 6280 salidas de los datos a la siguiente.

Para el primer conjunto de datos RGB, se activarán LI tan pronto como la velocidad de reloj de 31 bits. Usted también ha sincronizados de 1 bit para el siguiente conjunto de datos. Usted, a continuación, el reloj de otro 3 bytes de datos, más 6 más antes de activar LI. Pero si el tiempo de desplazamiento es lento, no se puede enviar el byte que contiene los últimos 6 bits hasta que usted esté listo para disparar LI, porque no quiero que se desborde el registro de desplazamiento de búfer! Pero una vez que esté listo para disparar LI, te voy a enviar este byte. Ahora 2 bits para el siguiente conjunto de datos ya está en el buffer de serie. Enviar otra de 3 bytes (26 bits en total), y espere hasta que usted necesita para desencadenar LI. Cuando es el momento, enviar el siguiente byte (que tiene el restante 5 bits). Repite esto una y otra vez.

Espero que esto tiene sentido. Como he dicho, yo no tengo experiencia con este chip, pero de lo que he escrito aquí es al menos el primer paso que había que tomar para tratar de resolver este problema mediante SPI.

Buena suerte, y nos mantienen informados!

0voto

w4ik Puntos 841

Al final, la forma de hacerlo es simplemente desbordando el registro de desplazamiento con más bits de los que necesita y asegúrate de que los 31 más importantes sean los ÚLTIMOS. Creo un buffer lo suficientemente largo como para contener 32 bits:

 static uint8_t[BUFFER_SIZE] spiBuffer;
 

Lo lleno cada vez que hay un cambio y uso el SPI impulsado por interrupciones para transmitirlo:

 void transmitSpiBuffer() {
  static uint8_t c = 0;
  SPDR=spiBuffer[c++];
  if (c == (BUFFER_SIZE)) {
    c = 0;
    digitalWrite(LATCH_PIN, HIGH);
    // should I sleep? nah.
    digitalWrite(LATCH_PIN, LOW);
  }
}

void setup() {
   // Enable MOSI and SCK as output, all others input.
   PORTB = (1<<PINB3)|(1<<PINB5);

   ISR(SPI_STC_vect) {
     transmitSpiBuffer();
   }

   // Enable SPI
   SPCR = (1<<SPIE)|(1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);
}
 

Esto funciona increíblemente bien para mí. Problema resuelto.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X