Domanda

Sto cercando di usare PWM per un LED su un ATMEGA8, qualsiasi PIN di PORT B. IMPOSTAZIONE I TIMERS è stato un fastidioso, e non so cosa fare con il mio OCR1A.Ecco il mio codice e mi piacerebbe un feedback.

Sto solo cercando di capire come usare PWM.Conosco il concetto, e OCR1A dovrebbe essere la frazione di tutto il tempo che voglio il polso su.

#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;
}
.

È stato utile?

Soluzione 2

È necessario inizializzare il tuo OCR1A con queste due linee:

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

e quindi usa questo:

OCR1A = in
.

e sappi che la gamma è 0-255.Conta le tue percentuali, e ce l'hai!

#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);
    }
}
.

Altri suggerimenti

No, questo è non il modo in cui dovresti fare un PWM. Ad esempio, come si imposta un tasso PWM di, ad esempio il 42% con esso? Inoltre, la dimensione del codice è grande, può essere fatta in modo molto più efficiente. Inoltre, si spreca un timer a 16 bit per fare operazioni a 8 bit. Hai 2x timer a 8 bit (timer / contatore 0 e 2) e un timer a 16 bit, Timer/Counter 1.

È anche una cattiva idea impostare i portpin inutilizzati in uscita. Tutti i portpins che non sono collegati a nulla, devono essere lasciati come ingressi.

ATMEGA8 ha un generatore PWM integrato sui timer 1 e 2, non è necessario simularlo tramite software. Non devi nemmeno impostare manualmente le tue porte (devi solo impostare il portpin corrispondente in uscita)

Non hai nemmeno bisogno di interruzione.

#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);
}
.

Nota che è possibile utilizzare un altro LED con un altro PWM, utilizzando lo stesso timer e impostare OCR2B invece di OCR2A. Non dimenticare di impostare TCCR2A per abilitare OCR2B come output per il tuo PWM, come in questo esempio è consentito solo OCR2A.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top