Paso 5: código
El código de pantalla es interrupción conducido y utiliza la biblioteca de Timer1 . Timer1 no está incluido en la instalación del software de Arduino. Por lo tanto, para instalarlo, debe TimerOne.zip de descargar y descomprimir su contenido en su sketchbook/bibliotecas/TimerOne.
Un marco es un hay de datos. Una forma muy sencilla y común de almacenar los datos sería utilizar un byte para cada LED. Este usaría 25 bytes por fotograma. Para ahorrar memoria, la definimos como un conjunto de 5 bytes. Cada byte representa una fila completa de nuestra pantalla. Puesto que un byte se compone de 8 bits, y sólo tenemos 5 LED por fila, sólo utilizamos la parte inferior 5 pedacitos, y el superior 3 bits se ignoran. Hay 5 bytes porque tenemos 5 filas. Podríamos ahorrar otro byte de embalaje 25 bits en 4 bytes, pero que complica innecesariamente el código y hace imposible ver gráficamente las declaraciones de marco de frames.h.
#define 5 DIM / / x / y dimensión - matriz de 5 x 5
typedef byte Frame [DIM];
Los pernos de columna LED están definidos en la matriz de cols .
int cols [DIM] = {12,11,10,9,8};
Los pernos de LED de la fila se definen en la matriz de filas .
int filas [DIM] = {7,6,5,4,3};
Para encender un LED especial, establecemos su pin de cols alta y sus filas pin bajo. Esto causa actual para fluir a través del LED seleccionado. La forma más directa para hacer esto sería utilizar la función digitalWrite() en cada LED en secuencia. Así que para encender el LED izquierdo superior, podríamos utilizar
digitalWrite(cols[0],HIGH);
digitalWrite(rows[0],LOW);
y hacer para cada LED. Sin embargo, no es muy eficiente. En su lugar usamos manipulación puerto directo para encender las columnas. El registro PORTB corresponde a los pines digitales 8 a 13.
Tenga en cuenta el orden que utilizamos en nuestra declaración de la matriz de cols arriba: 12,11,10,9,8. Esta manera, bit0 de PORTB corresponde a la columna derecha, albañilería1 corresponde a la siguiente columna a la izquierda, hasta bit4, que corresponde a la columna de la izquierda. Si establece un poco particular en 1, es el mismo como llamada digitalWrite() con alta y ajuste un poco a 0 es equivalente a llamar digitalWrite() con baja. Por lo tanto, podríamos teóricamente reemplazamos digitalWrite() llamando 5 veces para configurar todas las columnas de 5 con una escritura a PORTB. Pero ya que nos permite encender sólo a lo más 2 LED a la vez, tenemos a lazo 3 veces para cada columna, análisis 2 bits a la vez.
Interrumpir la rutina
se llama display() de cada tiempo, se apaga la fila anterior
y en la siguiente fila
máscara de bits bytes = B00000011;
void display() {}
digitalWrite (filas [fila], HIGH); Desactivar la fila entera anterior
Si (máscara de bits == B00010000) {}
máscara de bits = B00000011; columnas de luz de la razón 2 (pines 9,8)
incremento de fila y abrigo si fuera necesario
Si (++ fila == DIM) {}
fila = 0;
}
}
else if (máscara de bits == B00000011) {}
máscara de bits = B00001100; luz el medianas 2 columnas (pins 11,10)
}
Else {/ / bitMaskIdx == B00001100
máscara de bits = B00010000; luz de la columna de la izquierda (pin 12)
}
manipulación de Puerto directo.
PORTB es una variable de pseudo para pernos de digitales 8 a 13 los dos bits altos (6 y 7) no son utilizables y mapa a los pines del cristal
la parte inferior 5 pedacitos son nuestras columnas. No queremos cambiar los bits
así que primero la máscara de los bits de ignorar y luego establecer los bits que queremos a la luz
PORTB & = B11100000;
PORTB | = curFrame [fila] y máscara;
digitalWrite (filas [fila], LOW); Gire en la fila
}
Tenga en cuenta que nuestro comentario anterior dice que display() es una rutina de interrupción. Esto es porque en lugar de la exploración en la función loop(), lo llamamos en el fondo a través de la biblioteca de Timer1.
intervalo de interrupción en uSec
determina cuánto tiempo mantener cada fila activada
así si tenemos 5 filas, redibujar toda la pantalla
una vez cada 5 filas * 3 ciclos por fila * 1000 usec =.015 seg -> Hz 66,67
Si usted percibe parpadeo puede disminuir a 500 para un ritmo de 133,33 Hz
Timer1.Initialize(1000); fuego la interrupción cada 1000 microsegundos
Timer1.attachInterrupt(Display); llamar display() en cada interrupción.
El principal lazo simplemente pasos a través de todos nuestros cuadros de animación.
void loop() {}
incrementar el índice de marco y abrigo si fuera necesario
Si (++ curFrameIdx == FRAMECNT) {}
curFrameIdx = 0;
}
Seleccione el marco para la exhibición
setFrame(curFrameIdx);
Delay(400); esperar tiempo entre fotogramas en ms - reducir este valor a la velocidad de la animación, aumentarlo para ralentizarlo
}
El bosquejo entero se coloca por debajo.