Estoy intentando conducir 8 LED conectados a un registro de desplazamiento 74HC595
con PWM. Quiero poder configurar cada LED a un brillo diferente. La señal PWM está conectada al pin Enable Output
del registro de desplazamiento (es de baja actividad, por lo que la señal PWM debe invertirse). Seleccionando cada LED (solo un LED a la vez) y configurando la frecuencia PWM, pensé que se habría realizado. Así que actualmente tengo el siguiente enfoque:
- establecer la frecuencia PWM
- "active" el LED deseado escribiendo el valor correspondiente al registro de desplazamiento (por ejemplo, el primer LED sería
0b00000001
- escriba el valor del registro de desplazamiento para cambiar las salidas del registro estableciendo la entrada
Latch
en1
y vuelva a borrarlo a0
- comience de nuevo con la nueva frecuencia PWM y el próximo LED
Esto da como resultado el siguiente fallo: Cuando configuro el primer LED en brillo total y el siguiente LED en sin brillo (apagado), observo que durante un breve tiempo el brillo completo del primer LED aparece en el próximo LED . Este comportamiento le da al segundo LED un poco de brillo, lo cual es malo porque no quiero brillo (apáguelo). Sé que podría saltar sobre el LED para dejarlo apagado, pero me gustaría controlar solo el brillo de los LED al configurar la frecuencia PWM. También tengo este efecto al configurar, por ejemplo, el primer LED para brillo total y el siguiente LED para brillo medio. Siempre hay un brillo del LED anterior en el siguiente LED por un corto tiempo.
Creo que es porque no puedo controlar la salida de PWM, ya que puedo controlar la salida del registro de desplazamiento mediante su cierre. La frecuencia PWM se aplica tan pronto como la establezco en mi código. Esto provoca un breve parpadeo con el brillo del LED anterior. También intenté cambiar el orden de los pasos en mi enfoque.
¿Tienes alguna idea de cómo resolver este problema?
Algunas líneas de mi código real (si el pseudo código no es suficiente):
OCR0A = 0; // set PWM to full brightness
SPDR = 0b00000001; // select first LED
while(!(SPSR & (1<<SPIF))); // write to shift register
PORTB = 0; // latch outputs
PORTB = 1;
_delay_ms(1);
OCR0A = 255; // set PWM to no brightness (off)
SPDR = 0b00000010; // select second LED
while(!(SPSR & (1<<SPIF)));
PORTB = 0;
PORTB = 1;
_delay_ms(1);
Mi hardware de destino es un ATmega168
sincronizado a 20 MHz. Estoy usando avr-gcc
.