ATMega328p (168p) の Arduino で PWM の周波数を変えたい。ちゃんと理解をするには
を読めば良い。けどそもそもタイマーレジスターとは…、という自分の知識だったので動くコードを見つつ考えたい。
のページではコードの実例が載っていて解りやすい。
そして
には、ずばりチートシートが載ってるので、これを見ると目的の周波数をセットするにはてっとり早い。
Pins 5 and 6: controlled by Timer 0 in fast PWM mode (cycle length = 256)
Setting Divisor Frequency
0x01 1 62500
0x02 8 7812.5
0x03 64 976.5625 <--DEFAULT
0x04 256 244.140625
0x05 1024 61.03515625
TCCR0B = (TCCR0B & 0b11111000) | <setting>;
みたいに、周波数を設定するために何をレジスタに代入すればよいのかがすぐ解るコードがまんまのってる。
TCCR0B = (TCCR0B & 0b11111000) | 0x01; // 62500Hz
analogWrite(5, 128); // duty比 50%
これで 16us 周期の PWM がうまく出力された。
注意事項
TCCR0B (uno や nano の 5,6 ピンの PWM) の周波数を変えると、同じタイマの Timer 0 を使ってる標準関数の delay() や millis() などに影響が出る。
標準の 976.5625 Hz では delay(1000) で約一秒待つが、62500Hz に変更した場合、62500 / 976.5625 = 64000 で delay(64000) が約1秒となる。
2016年3月時点の Arduino のソースコードを見る限り、このへんで固定されてしまっていて良い回避策が無くて wiring.c を自分で書き換える必要がある…。良い方法知ってる人が居たら教えてください…。