Pregunta

Estoy tratando de usar PWM para un LED en un ATMEGA8, cualquier PIN de Puerto B. Configuración de los temporizadores ha sido molesto, y no sé qué hacer con mi OCR1A.Aquí está mi código, y me encantaría algunos comentarios.

Solo estoy tratando de averiguar cómo usar PWM.Sé el concepto, y se supone que OCR1A es la fracción de todo el tiempo que quiero el pulso.

#define F_CPU 1000000  // 1 MHz

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

int main(void){

    TCCR1A |= (1 << CS10) | (1 << CS12) | (1 << CS11);
    OCR1A = 0x0000;
    TCCR1A |= ( 0 << WGM11 ) | ( 1 << WGM10 ) | (WGM12 << 1) | (WGM13 << 0);
    TCCR1A |= ( 1 << COM1A0 ) | ( 0 << COM1A1 );
    TIMSK |= (1 << TOIE1); // Enable timer interrupt
    DDRB = 0xFF;
    sei(); // Enable global interrupts
    PORTB = 0b00000000;

    while(1)
    {
        OCR1A = 0x00FF; //I'm trying to get the timer to alternate being on for 100% of the time,
        _delay_ms(200);
        OCR1A = 0x0066; // Then 50%
        _delay_ms(200);
        OCR1A = 0x0000; // Then 0%
        _delay_ms(200);
    }
}

ISR (TIMER1_COMA_vect)  // timer0 overflow interrupt
{
    PORTB =~ PORTB;
}

¿Fue útil?

Solución 2

Debe inicializar su OCR1A con estas dos líneas:

TCCR1A = (1 << WGM10) | (1 << COM1A1);
TCCR1B = (1 << CS10) | (1 << WGM12);

y luego use esto:

OCR1A = in

y saber que el rango es 0-255.Cuenta tus porcentajes, ¡y ahí lo tienes!

#define F_CPU 1000000  // 1 MHz
#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>

int main(void){
    TCCR1A = (1 << WGM10) | (1 << COM1A1);
    TCCR1B = (1 << CS10) | (1 << WGM12);
    DDRB = 0xFF;
    sei(); // Enable global interrupts
    PORTB = 0b00000000;

    while(1)
    {
        OCR1A = 255;
        _delay_ms(200);
        OCR1A = 125;
        _delay_ms(200);
        OCR1A = 0;
        _delay_ms(200);
    }
}

Otros consejos

No, esto es no de la forma en que debe hacer un pwm. Por ejemplo, ¿cómo establece una tasa de PWM, por ejemplo, 42% con ella? Además, el tamaño del código es grande, se puede hacer de una manera mucho más eficiente. Además, desperdicias un temporizador de 16 bits para hacer operaciones de 8 bits. Tiene 2 veces temporizadores de 8 bits (temporizador / contador 0 y 2), y un temporizador de 16 bits, Timer/Counter 1.

También es una mala idea establecer los portadores no utilizados para que salgan. Todos los portadores que no están conectados a nada, deben dejarse como entradas.

El ATMEGA8 tiene un generador PWM incorporado en los temporizadores 1 y 2, no hay necesidad de simularlo a través del software. Ni siquiera tiene que configurar sus puertos manualmente (solo tiene que configurar el portpin correspondiente a la salida)

Ni siquiera necesitas ninguna interrupción.

#define fillrate OCR2A 


 //...

 // main()

PORTB=0x00;
DDRB=0x08;  //We use PORTB.3 as output, for OC2A, see the atmega8 reference manual

// Mode: Phase correct PWM top=0xFF
// OC2A output: Non-Inverted PWM
TCCR2A=0x81;
// Set the speed here, it will depend on your clock rate.
TCCR2B=0x02;

// for example, this will alternate between 75% and 42% PWM
while(1)
{
    fillrate = 191; // ca. 75% PWM
    delay_ms(2000);

    fillrate = 107; // ca. 42% PWM
    delay_ms(2000);
}

Tenga en cuenta que puede usar otro LED con otro PWM, usando el mismo temporizador y configurando OCR2B en lugar de OCR2A. No se olvide de establecer TCCR2A para habilitar OCR2B como salida para su PWM, como en este ejemplo, solo se permite OCR2A.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top