9

ATmega8のLED、ポートBの任意のピンにPWMを使用しようとしています。タイマーの設定が面倒で、OCR1Aをどうすればよいかわかりません。これが私のコードです、そして私はいくつかのフィードバックが欲しいです。

PWMの使い方を理解しようとしています。私はその概念を知っています、そしてOCR1Aは私がパルスをオンにしたいカウンター時間全体の一部であると思われます。

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

2 に答える 2

6

次の2行でOCR1Aを初期化する必要があります。

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

そして、これを使用します:

OCR1A = in

そして、範囲が0〜255であることを知ってください。あなたのパーセンテージを数えてください、そしてあなたはそれを持っています!

#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);
    }
}
于 2012-02-28T21:34:14.573 に答える
6

いいえ、これはPWMを実行する方法ではありません。たとえば、PWMレートをたとえば42%に設定するにはどうすればよいですか?また、コードサイズが大きいため、はるかに効率的な方法で実行できます。また、8ビット演算を実行するために16ビットタイマーを浪費します。2x 8ビットタイマー(タイマー/カウンター0および2)と1つの16ビットタイマーがありTimer/Counter 1ます。

未使用のポートピンを出力に設定することもお勧めできません。何にも接続されていないすべてのポートピンは、入力として残しておく必要があります。

ATmega8にはタイマー1と2にPWMジェネレーターが組み込まれており、ソフトウェアでシミュレーションする必要はありません。ポートを手動で設定する必要はありません(対応するポートピンを出力に設定するだけです)

割り込みも必要ありません。

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

同じタイマーを使用し、OCR2Aの代わりにOCR2Bを設定することにより、別のPWMで別のLEDを使用できることに注意してください。この例ではOCR2Aのみが許可されているため、PWMの出力としてOCR2Bを有効にするようにTCCR2Aを設定することを忘れないでください。

于 2012-03-23T07:35:36.677 に答える