Attiny85 PWM no funciona

0

Soy nuevo en la programación de AVR. Tengo un Attiny85 y un LED conectado al pin 5 en el chip (PB0). Mi objetivo es lograr que el LED se apague, luego se apague y repita. Cuando le doy poder al chip, el LED se enciende muy poco. Es un brillo muy tenue. Permanece con el mismo brillo durante varios segundos y luego se ilumina hasta alcanzar su brillo máximo. Abajo está mi código.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

double dutyCycle = 0;

int main() {

    DDRB = (1 << PORTB0); // Set PB0 as output

    TCCR0A = (1 << COM0A1) | (1 << WGM00) | (1 << WGM01); // Clear OC0A on compare, WGMxx selscts fast mode
    TIMSK = (1 << TOIE0);

    OCR0A = (dutyCycle / 100.0) * 255.0;

    sei();

    TCCR0B = (1 << CS00); // Set prescalar and start timer

    while (1) {
        _delay_ms(100);
        dutyCycle = dutyCycle + 15;

        if (dutyCycle > 100) {
            dutyCycle = 0;
        }
    }

    return 0;
}

ISR(TIMER0_OVF_vect) {
    OCR0A = (dutyCycle / 100.0) * 255.0;
}

Intenté cambiar el tipo de la variable dutyCycle a un uint8_t pero los resultados fueron los mismos. Eliminé el '.0' de algunos y todos los cálculos matemáticos, pero nuevamente los resultados fueron los mismos.

    
pregunta user3131261

1 respuesta

2

No es necesario asignar OCR0A en cada overlow, solo reasignarlo cuando cambie. Este código elimina el ISR, por lo que es más corto y más simple (y funciona) ...

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

double dutyCycle = 50;

int main() {

    DDRB = (1 << PORTB0); // Set PB0 as output

    TCCR0A = (1 << COM0A1) | (1 << WGM00) | (1 << WGM01); // Clear OC0A on compare, WGMxx selscts fast mode

    TCCR0B = (1 << CS00); // Set prescalar and start timer

    while (1) {

        OCR0A = (dutyCycle / 100.0) * 255.0;

        _delay_ms(100);
        dutyCycle = dutyCycle + 15;

        if (dutyCycle > 100) {
            dutyCycle = 0;
        }


    }

    return 0;
}

Si alguna vez realmente necesitas usar un ISR (a diferencia de este caso), hay complicaciones. Por ejemplo, usted está escribiendo en la variable dutyCycle en el bucle principal, y está leyendo en ISR. Esto significa que la variable debe ser volatile . También es probable que desee evitar hacer cualquier punto flotante dentro de un ISR, por lo que es mejor calcular el valor final en el hilo principal y luego pasar solo el nuevo byte al ISR para que pueda hacer su trabajo y regresar tan rápido como sea posible.

    
respondido por el bigjosh

Lea otras preguntas en las etiquetas