No estoy seguro de por qué está utilizando el registro de desplazamiento en lugar de tres pines MCU. En cualquier caso, esto se denomina LED multiplexado o escaneado, y es una configuración muy común (ya que el número de resistencias y pines varía O (registro N) con el número de LED, en lugar de O (N)). p>
La visión humana tiene problemas para ver algo más rápido que unos 10 ms, y puede aguantar mucho más lento. Tenga en cuenta que los televisores a menudo escanean la pantalla a 50 o 60 Hz. Entonces, si escaneas mucho más rápido que eso, nadie lo notará.
En su caso de registro de turnos, configura una interrupción para que se apague de vez en cuando, por ejemplo 1000 Hz (intervalos de 1 ms). Esto le proporciona aproximadamente 330 exploraciones por segundo (frecuencia dividida por el número de LED; desea mantener este número por encima de 100 Hz aproximadamente). Cada interrupción, los pines se actualizan y se cambia el registro de desplazamiento. El código probablemente se vería así:
int ledNum = 0;
int colorLED[3] = {0}; // Sets all elements to 0.
// Colors: black = 0, red = 1, green = 2, yellow = 3,
// blue = 4, magenta = 5, cyan = 6, white = 7
Interrupt()
{
// Load a 1 into the SR if this is the start of the cycle.
if(ledNum == 0)
SR_D = 1;
else
SR_D = 0;
// Set the color.
PORTA = (PORTA & ~7) | (colorLED[ledNum] & 7);
// Clock the shift register.
SR_CLK = 1;
SR_CLK = 0;
// Update for next loop.
ledNum = ledNum + 1;
if(ledNum == 3)
ledNum = 0;
}
Ten en cuenta que esto solo te da 8 colores. Para obtener más información, deberá aumentar la velocidad de escaneo porque cambiará los LED con PWM. Código de ejemplo para 4 bits por color, que proporciona 4096 colores y necesita 15 veces la tasa de interrupción (15 kHz o 0.067 ms):
int ledNum = 0;
int pwmStep = 0;
int colorLED[3] = {0}; // Sets all elements to 0.
Interrupt()
{
// Load a 1 into the SR if this is the start of the cycle.
if(step == 0)
{
if(ledNum == 0)
SR_D = 1;
else
SR_D = 0;
// Clock the shift register.
SR_CLK = 1;
SR_CLK = 0;
}
// Set the color.
int reg = PORTA & ~7;
if((colorLED[ledNum] & 0xF) > step)
reg |= 1;
if(((colorLED[ledNum] >> 4) & 0xF) > step)
reg |= 2;
if(((colorLED[ledNum] >> 8) & 0xF) > step)
reg |= 4;
PORTA = colorLED[ledNum];
// Update for next loop.
if(step == 0)
{
ledNum = ledNum + 1;
if(ledNum == 3)
ledNum = 0;
}
// Next PWM step
step = step + 1;
if(step == 15)
step = 0;
}
Tenga en cuenta que el número de pasos en PWM es el mismo que el valor máximo, no uno más alto. Entonces, cuatro bits, que pueden representar 0-15, necesitan 15 pasos, no 16.
Las optimizaciones, por supuesto, se dejan como un ejercicio para el lector.
Una última cosa que hay que comprobar es que el pin del registro de desplazamiento es capaz de hundir la corriente de tres LED a la vez, dados los valores de su resistencia. De lo contrario, deberá obtener algunos FET o BJT para cambiar los pines del cátodo común de los LED.