AVR ATMEGA / ATTINYタイマーミラー出力の理解に助けが必要


10

Arduinoで使用されているAtMega328またはATTiny85のいずれかのAtmel AVRマイクロコントローラーのTimer1を使用して、互いに鏡像の2つのクロック信号を出力しようとしています。私が生成しようとしている周波数は1 MHzから2 MHz以上の可変であり、コントローラーで他にほとんど何もしたくない場合を除いて、出力ピンを切り替えるコードを使用してこれを行うには高すぎます。したがって、関連するピンで直接タイマー出力を使用したいと思います。私はGCCツールチェーンを使用しているため、arduinoライブラリまたは言語に制限されません。

Atmega328のTimer1には2つのピンが関連付けられており、それらから2つの同じ1MHz〜2MHz信号を取得できます。データシートに反転波形が表示されるようですが、混乱しています。Timer1のPWM設定を使用して、1 MHzでデューティサイクルが異なる2つの信号を取得することもできますが、両方の信号が同時にハイになり、短い方が早くローになります。これは私のプロジェクトに役立ちません。PWMパルス幅の変動も必要ありません。反対位相の2つの同一の「クロック」タイプの信号が必要なだけです。

私がこれを行うためのコードを書くことを誰かに求めているのではなく、タイマーのどのモード/フラグがタイマーに関連付けられた2つのピンの1つに単純な反転波形を与えるべきかを誰かに教えてくれる必要があります。それが唯一の選択肢でない限り、可能であれば、出力の1つに外部反転回路を使用しないようにします。

これがATTinyで可能な場合は、さらに良いでしょう。ATTinyには、1つのタイマーに関連付けられた2つのピンもありますが、ATMegaと同じオプションがあるかどうかはわかりません。

PCBに接続された20 MHzの水晶振動子とコンデンサーを既に持っており、20 MHzのクロックはATMega328で確実に機能しています。ATTiny85 PCBには8 MHzの水晶があり、これも確実に機能しています。

助けてください。ありがとうございました。


更新:これまでの回答とコメントにはいくつかの無効な仮定がありますので、おそらく明確にする必要があります:私の元の投稿では、8 MHzではなく 20 MHzクロックを使用していること、およびPWMは不要であることを指摘しました

PWMモードは2 MHzの出力では機能しないため、十分に高い出力周波数を提供する唯一のモードはCTCモードのようです。CTCモードでタイマー1の出力Aまたは出力Bを反転する方法はありますか?

私のコードをチェックするために、自分の20 MHzボードではなく、標準のArduino Uno(ATMega328、16 MHz)に切り替えました。これは、CTCモードでピン9と10からの安定した2 MHzクロックのタイマーです。タイマー1つの出力ピン:

#define tick 9
#define tock 10

void setup() {
  pinMode(tick, OUTPUT);  
  pinMode(tock, OUTPUT); 

  TCCR1A = _BV(COM1A0) | _BV(COM1B0) ;   // activate both output pins 
  TCCR1B = _BV(WGM12)| 1;                // set CTC mode, prescaler mode 1

  // various frustrating attempts to invert OC1B failed. What do I put here?

  OCR1A = 3;                             // set the counter max for 2 MHz

}

void loop() {
}

両方のピンのオシロスコープのトレースは同一で同期していますが、2つの信号のいずれかを反転するにはどうすればよいですか?データシートの反転モードは、CTCモードでは何もしないようです。データシートを間違って読んでいますか、それとも結局、低い周波数とPWMモードを使用する必要がありますか?

特定の「賞金」の質問を元のクエリに追加するには:
上記のコードにどのような変更を加える必要がありますか。16MHzクロックの可能な最高周波数でピン9と11に完全に反転した信号を提供するには、それは2 MHzかどうか?

とりあえず標準のArduino Unoを使い続けます。ホームスパンボードによってエラーモードが導入されることはなく、Arduinoを持っている人は誰でも上記のコードを試して、私が述べたとおりに機能することを確認できます。必要!


1
atmega8L データシートの97〜98ページを見ると、動作モードの表があります。ページ108に、「COM21:0ビットは、生成されたPWM出力を反転するかどうか(反転PWMまたは非反転PWM)を制御する」と記載しています。あなたの成功について投稿してください!
Vorac

ミラーリングされた出力に単純なトランジスタインバータを使用しないのはなぜですか?
Jonny B Good

回答:


10

ATtiny85データシートから:

動作モード、つまり、タイマー/カウンターおよび出力コンペアピンの動作は、波形生成モード(WGM0 [2:0])とコンペア出力モード(COM0x [1:0])の組み合わせによって定義されます。ビット。比較出力モードビットはカウントシーケンスに影響しませんが、波形生成モードビットは影響します。COM0x [1:0]ビットは、生成されたPWM出力を反転するかどうか(反転または非反転PWM)を制御します。

表11-5に、モードの設定方法を示します。

Mode   WGM  WGM  WGM  Timer/Counter Mode    TOP      Update of    TOV Flag
c0     02   01   00   of Operation                   OCRx at      Set on
==========================================================================
0      0    0    0    Normal                0xFF     Immediate    MAX(1)
1      0    0    1    PWM, Phase Correct    0xFF     TOP          BOTTOM
2      0    1    0    CTC                   OCRA     Immediate    MAX
3      0    1    1    Fast PWM              0xFF     BOTTOM       MAX
4      1    0    0    Reserved                                  
5      1    0    1    PWM, Phase Correct    OCRA     TOP          BOTTOM
6      1    1    0    Reserved                                  
7      1    1    1    Fast PWM              OCRA     BOTTOM       TOP

高速PWMモードが必要な場合(モード3またはモード7)。デューティサイクルを変更したい場合は、モード7が必要で、OCRAを設定してデューティサイクルを変更します。

表11-3は、高速PWMモードのコンペア出力モードの設定方法を示しています。

COM0A1/   COM0A0/
COM0B1    COM0B0     Description
===============================================================================
0         0          Normal port operation, OC0A/OC0B disconnected.
0         1          Reserved
1         0          Clear OC0A/OC0B on Compare Match, set OC0A/OC0B at BOTTOM
                     (non-inverting mode)
1         1          Set OC0A/OC0B on Compare Match, clear OC0A/OC0B at BOTTOM
                     (inverting mode)

つまり、COM0A1:COM0A0 = 0b10を設定することにより、タイマー値== OCR0AのときにOC0A出力をローに、タイマー値== 0x00のときにハイに設定できます。または、COM0A1:COM0A0 = 0b11を設定して、逆も同様です。また、OC0B、OCR0B、COM0B0、COM0B1の場合も同様です。

PWM周波数は、I / Oクロック(8 MHzのように聞こえます)とタイマープリスケーラーの設定によって決まります。また、高速PWMモードの場合、式はf_clk_IO /(N * 256)として与えられます。

したがって、OCR0AとOCR0Bを同じ値に設定し、COM0A1:COM0A0 = 0b10とCOM0B1:COM0B0を0b11に設定することで、OC0Aを「通常」極性に、OC0Bを「反転」極性に使用できます。

更新

出力をできるだけ速くトグルしたい場合、および16MHzで動作するMega328を使用している場合、CTC動作モードでは、次のスイッチング周波数を取得できます。

f_OCnA = f_clk_IO /(2 * N * [1 + OCRnA)= 16e6 /(2 * 1 * [1 + 1])= 4MHz

高速PWMモードでは、次の場所でピンを切り替えることができます。

f_OCnxPWM = f_clk_IO /(N * [1 + TOP])= 16e6 /(1 * [1 + 1])= 8MHz

だから私はまだあなたが高速PWMモードを望んでいると思います。具体的には、50%デューティサイクルのOCR0A = OCR0B = 0x80のモード3。また、COM0Aビットを0x3に、COM0Bビットを0x2に設定して、OC0AとOC0Bの2つの波形を互いに反転させます。

アップデート#2 より多くのMega328このArduinoコードを試してください:

#define tick 9
#define tock 10

void setup(){

  pinMode(tick, OUTPUT);  
  pinMode(tock, OUTPUT); 

  // Setup Waveform Generation Mode 15
  // OC1A Compare Output Mode = inverting mode
  // OC1B Compare Output Mode = non-inverting mode
  // Timer Prescaler = 1
  // TOP = OCR1A = 1

  //COM1A[1:0] = 0b11, COM1B[1:0] = 0b10, WGM1[1:0] = 0b11
  TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(COM1B1) | _BV(WGM11) | _BV(WGM10);

  //WGM1[3:2] = 0b11, CS1[2:0] = 0b001
  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);

  OCR1A = 0x0001;
  OCR1B = 0x0001;
}

void loop(){

}

これを少し噛んで、うまくいくかどうか見てみましょう。ありがとうございました。
エキサイティングな

今日あなたの答えをもう一度読んで試してみたところ、いくつかの無効な仮定が表示されました。「(8MHzのように聞こえます)」ではなく、20 MHzクロックを指定しました(これで16 MHzに切り替えました。また、PWMパルス幅の変動は必要ないことを指定しているので、「デューティサイクルを変動させたい場合、そのように聞こえる場合」をどこで推測したかはわかりません
エキサイティングな

@ExcitingProjects「ATTiny85 PCBには8 MHzクリスタルがあり、それも確実に機能しています。」そして私の答えはATtiny85に関連しています。私はあなたの更新された質問に答えて私の回答を更新しようとします。
vicatcu 2012年

@vicateuありがとうございます。質問を更新しました。いくつかの手順を省略しない限り、反転モードはCTCモードでは効果がないように見えます。
エキサイティングな

ATmega328データシートの@ExcitingProjects:「非PWMモードの場合、COM0x1:0ビットは、コンペアマッチで出力を設定、クリア、またはトグルするかどうかを制御します」
vicatcu

1

ATtinyX5ファミリは内部にPLLを備えています。

私は内部PLLを使用してCPUクロックにも電力を供給し、XTALなしで16Mhzを使用しています。ピンが5つしかないので、これは貴重です。(私はリセットピンを数えません)。また、1つのPLL付きPWM(OCR1B)は、オプションの相補出力を備えたXTALピンで実行されます。16Mhz Xtalless ATtinyのヒューズを調整するだけです...または、CPUを8Mhzで実行し、ヒューズを変更せずに64MhzクロックでPWMを実行します。

最大64 MhzのクロックPWMを使用できます(ただし1ビットの分解能)。または、125Khz @ 8ビットの解像度。OCR1Cレジスタを減らすことで、PWMの分解能を下げ、速度を上げることができます。

1 Mhzの場合、OCR1Cを63に設定する必要があります。2Mhzの場合、OCR1Cを31に設定する必要があります。4Mhzの場合、OCR1Cを15に設定する必要があります。

このコードでPLLを有効にするだけです:

PLLCSR |= (1 << PLLE);           //Start PLL
while( !(PLLCSR & (1<<PLOCK)) ); //Wait for PLL lock
//PLLCSR |= (1<<LSM );           //Low Speed PLL that clocks 32Mhz, not 64Mhz
PLLCSR |= (1 << PCKE);           //Enable PLL

これで、「OCR1B0 / OCR1A0」PWMに64 Mhzのクロックがあります。

また、OCR1 [A / B] 0とXOCR1 [A / B] 0を調整してミラー出力することもできます。

if(0){ //Synch mode
     //OCR1A & XOCR1A enable for Synch operation but not allow odd PWM values!
     TCCR1 |= (1 << PWM1A) | (0 << COM1A1) | (1 << COM1A0); 
     //Also ATtinyX5 has "Dead Time Generator", use it ;)
     DTPS1 = 3;   //8x Prescaler for dead time generator (maximum)
     DT1A = 0xff; //Clk dead on both channels (maximum)
     }
   else
     TCCR1 |= (1 << PWM1A) | (1 << COM1A1) | (0 << COM1A0);  //ONLY OCR1A enabled

OCR1A = 1に設定した場合、デッドタイムジェネレーターはPWMアウトアウトを食べることを知っておく必要があります。むだ時間よりも高い値が必要です。

よろしく、

エルデム

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.