FrontPage > マイクロコントローラ > AVRの覚書
PWM †
ATmega328Pの16-bitタイマ/カウンタのMode 15(Fast PWM)を使用して
周期:20ms、パルス幅:2msの波形を出力してみる。
出力はOC1B(PB2)ピン
1. 波形生成の仕組み †
PWMの波形は下図のように、カウンタが最大値までカウントを繰り返している状態で、
0のときにセット、比較値と一致したときにクリアされる。(逆も可)
- 最大値を求める
今回はカウンタのクロックにシステムクロック16MHzを8分周して用いるので、
1カウントの時間は
8 / 16Mhz = 0.5μs
周期が20msとなるカウンターの最大値は
20ms/0.5μs -1 = 39999 = 0x9C3F
- 比較値を求める
パルス幅が2msとなる比較値は
2ms/0.5μs = 4000 = 0xFA0
2. レジスタ †
- TCCR1A, TCCR1B (Timer/Counter1 Control Register A,B)
(TCCR1A)
bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
---|
COM1A1 | COM1A0 | COM1B1 | COM1B0 | - | - | WGM11 | WGM10 |
(TCCR1B)
bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
---|
ICNC1 | ICES1 | - | WGM13 | WGM12 | CS12 | CS11 | CS10 |
- COM1A1,COM1A0(Compare Output Mode)
OC1Aピンは未使用のため"00"を設定。
- COM1B1,COM1B0(Compare Output Mode)
OC1Bピンへ比較一致でクリア、0でセット出力なので"10"を設定。
- ICNC1, ICES1
未使用のため"00"
- WGM[13:10](Waveform Generation Mode)
Fast PWMモードで最大値はOCR1Aの値を使用するので"1111"を設定。
- CS[12:10](Clock Select)
8分周するので、"010"を設定。
- OCR1A(Output Compare Register 1A)
最大値"39999"を設定。
- OCR1B(Output Compare Register 1B)
比較値"4000"を設定
3. プログラム †
(PWm_test.c)
#include <avr/io.h>
int main(void)
{
// カウント最大値設定(20ms周期)
OCR1A = 0x9C3F;
// パルス幅設定(2ms)
OCR1B = 0x0FA0;
// Timer/Counter1 Controlレジスタ設定
TCCR1A = _BV(COM1B1) | _BV(WGM11) | _BV(WGM10);
TCCR1B = _BV(WGM13) | _BV(WGM12) |_BV(CS11);
// PORT-BのBit-2(OC1Bピン)を出力に指定
DDRB |= _BV(DDB2);
while(1)
{
//TODO:: Please write your application code
}
}
4. 実行結果 †
- 出力された波形をオシロスコープで確認
周期20msを確認。
パルス幅2msを確認
5. サーボモータを制御する。 †
ホビー用サーボモータの角度はPWMによって制御される。
試しにPWM出力をサーボモータに接続して
0°→ -90°→ 90°→ 0°と動かしてみる。
5.1 接続図 †
5.2 プログラム †