Ich versuche, mit einem ATtiny13A eine ferngesteuerte RGB-LED zu erstellen.
Ich weiß, dass der ATtiny85 für diesen Zweck besser geeignet ist, und ich weiß, dass ich möglicherweise nicht in der Lage bin, den gesamten Code anzupassen, aber im Moment ist es mein Hauptanliegen, eine Software-PWM mithilfe von Interrupts im CTC-Modus zu generieren.
Ich kann nicht in einem anderen Modus betrieben werden (außer für schnellen PWM mit OCR0A
wie TOP
das ist im Grunde dasselbe ist) , weil der IR - Empfänger Code verwende ich eine 38 kHz Frequenz benötigt , die es mit Hilfe erzeugt CTC und OCR0A=122
.
Also versuche ich (und ich habe gesehen, dass Leute dies im Internet erwähnen) die Output Compare A
und Output Compare B
Interrupts zu verwenden, um eine Software-PWM zu generieren.
OCR0A
, der auch vom IR-Code verwendet wird, bestimmt die Frequenz, die mir egal ist. Und OCR0B
bestimmt den Arbeitszyklus der PWM, die ich zum Ändern der LED-Farben verwenden werde.
Ich erwarte, dass ich eine PWM mit einem Tastverhältnis von 0-100% erhalten kann, indem ich den OCR0B
Wert von 0
auf ändere OCR0A
. So verstehe ich, was passieren soll:
Aber was tatsächlich passiert, ist Folgendes (dies stammt aus der Proteus ISIS-Simulation):
Wie Sie unten sehen können, kann ich einen Arbeitszyklus von 25% bis 75% erreichen, aber für ~ 0-25% und ~ 75-100% bleibt die Wellenform einfach hängen und ändert sich nicht.
GELBE Linie: Hardware PWM
ROTE Leitung: Software-PWM mit festem Arbeitszyklus
GRÜNE Linie: Software-PWM mit variierendem Arbeitszyklus
Und hier ist mein Code:
#ifndef F_CPU
#define F_CPU (9600000UL) // 9.6 MHz
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
int main(void)
{
cli();
TCCR0A = 0x00; // Init to zero
TCCR0B = 0x00;
TCCR0A |= (1<<WGM01); // CTC mode
TCCR0A |= (1<<COM0A0); // Toggle OC0A on compare match (50% PWM on PINB0)
// => YELLOW line on oscilloscope
TIMSK0 |= (1<<OCIE0A) | (1<<OCIE0B); // Compare match A and compare match B interrupt enabled
TCCR0B |= (1<<CS00); // Prescalar 1
sei();
DDRB = 0xFF; // All ports output
while (1)
{
OCR0A = 122; // This is the value I'll be using in my main program
for(int i=0; i<OCR0A; i++)
{
OCR0B = i; // Should change the duty cycle
_delay_ms(2);
}
}
}
ISR(TIM0_COMPA_vect){
PORTB ^= (1<<PINB3); // Toggle PINB3 on compare match (50% <SOFTWARE> PWM on PINB3)
// =>RED line on oscilloscope
PORTB &= ~(1<<PINB4); // PINB4 LOW
// =>GREEN line on oscilloscope
}
ISR(TIM0_COMPB_vect){
PORTB |= (1<<PINB4); // PINB4 HIGH
}
OCR0A
wird vom IR-Code verwendet, also habe ich nur OCR0B
. Ich versuche, damit Software-PWM auf 3 Nicht-PWM-Pins zu generieren.