Question

J'essaie d'utiliser PWM pour une LED sur un ATMEGA8, toute broche de Port B. Configuration des minuteries a été ennuyeuse, et je ne sais pas quoi faire avec mon OCR1a. Voici mon code et j'aimerais quelques commentaires.

J'essaie juste de comprendre comment utiliser PWM. Je connais le concept, et OCR1A est censé être la fraction de toute la contre-la seule fois sur laquelle je veux le pouls.

#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;
}
Était-ce utile?

La solution 2

Vous devez initialiser votre OCR1A avec ces deux lignes:

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

Puis utilisez ceci:

OCR1A = in

Et sachez que la gamme est de 0-255. Comptez vos pourcentages, et là vous l'avez!

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

Autres conseils

Non cela est ne pas La façon dont vous devez faire un PWM. Par exemple, comment définissez-vous un taux PWM, par exemple, 42% avec? De plus, la taille du code est grande, elle peut être fait de manière beaucoup plus efficace. En outre, vous perdez une minuterie 16 bits pour effectuer des opérations 8 bits. Vous avez 2x minuteries 8 bits (minuterie / compteur 0 et 2), et une minuterie 16 bits, Timer/Counter 1.

C'est aussi une mauvaise idée de définir des Portpins inutilisés sur la sortie. Tous les Portpins qui ne sont connectés à rien doivent être laissés comme entrées.

L'ATMEGA8 a un générateur PWM intégré sur les minuteries 1 et 2, il n'est pas nécessaire de la simuler via un logiciel. Vous n'avez même pas besoin de définir vos ports manuellement (vous n'avez qu'à définir le portpin correspondant sur la sortie)

Vous n'avez même pas besoin d'interruption.

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

Notez que vous pouvez utiliser une autre LED avec un autre PWM, en utilisant la même minuterie et en définissant OCR2B au lieu d'OCR2A. N'oubliez pas de définir TCCR2A pour activer OCR2B comme sortie pour votre PWM, comme dans cet exemple, seul OCR2A est autorisé.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top