【Arduino工作〜発展編】AVR-RustでAtmega328pからPWM波形を出力したい!
※ 当ページには【広告/PR】を含む場合があります。
2021/10/29
AVRマイコンでのPWM概論
AVRマイコンのタイマーモード
「標準モード」:
いわゆる普通のタイマー。
8bitと16bitの2種類があり、カウンタとして動作させたい時に使用
「CTCモード」:
コンペアマッチ(指定値とタイマーカウントが一致)を使うモード。
この指定値はOCR●AかOCR●Bで設定する。
タイマーカウントがその指定値を超えたら矩形波形が出力電圧を反転し、
同時にタイマは0に戻る
「高速PWMモード」:
PWM波形を出力する際に使用。
ただしタイマー波形はノコギリ波ベースとなる
「位相基準PWMモード」:
こちらもPWM波形を出力する際に使用。
ただしタイマー波形は三角波ベースとなる
CTC
高速PWM
位相基準PWM
高速PWMモード
高速PWMモード?
ICR*レジスタ
OCR*Aレジスタ
タイマーとPWM出力ができるピン
0~255
0~65535
タイマー0:
カウンター:
8bit
ピン出力値レジスタ(ピン名):
OCR0A(PD6)
OCR0B(PD5)
タイマ/PWMの設定レジスタ:
TCCR0A
TCCR0B
タイマー1:
カウンター:
16bit
ピン出力値レジスタ(ピン名):
OCR1A(PB1)
OCR1B(PB2)
タイマ/PWMの設定レジスタ:
TCCR1A
TCCR1B
タイマー2:
カウンター:
8bit
ピン出力値レジスタ(ピン名):
OCR2A(PB3)
OCR2B(PD3)
タイマ/PWMの設定レジスタ:
TCCR2A
TCCR2B
タイマー1のレジスタ操作
TCCR1AとTCCR1Bレジスタ
ビット番号 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
名称 | COM1A1 | COM1A0 | COM1B1 | COM1B0 | 無し | 無し | WGM11 | WGM10 |
COM1A1-COM1A0: OC1Aピンの出力モード
00 ... 出力なし
01 ... コンペアマッチでトグル
10 ... コンペアマッチでLOW(ノン・インバートモード)
11 ... コンペアマッチでHIGH(インバートモード)
COM1B1-COM1B0: OC1Bピンの出力モード
00 ... 出力なし
01 ... コンペアマッチでトグル
10 ... コンペアマッチでLOW(ノン・インバートモード)
11 ... コンペアマッチでHIGH(インバートモード)
ビット番号 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
名称 | 1CNC1 | 1CES1 | 無し | WGM13 | WGM12 | CS12 | CS11 | CS10 |
CS12-CS11-CS10:
000...タイマー停止
001...分周無し(=1)
010...1/8
011...1/64
100...1/256
101...1/1024
110...外部クロックT1立ち下がりエッジ
111...外部クロックT1立ち上がりエッジ
WGM13-WGM12-WGM11-WGM10:
0000...標準・TOP(0xFFFF)
0001...8bit位相標準PWM・TOP(0x00FF)
0010...9bit位相標準PWM・TOP(0x01FF)
0011...10bit位相標準PWM・TOP(0x03FF)
1000...位相/周波数標準PWM・TOP(ICR1)
1001...位相/周波数標準PWM・TOP(OCR1A)
1010...位相標準PWM・TOP(ICR1)
1011...位相標準PWM・TOP(OCR1A)
0100...CTC・TOP(ICR1)
1100...CTC・TOP(OCR1A)
1101...無し
0101...8bit高速PWM・TOP(0x00FF)
0110...9bit高速PWM・TOP(0x01FF)
0111...10bit高速PWM・TOP(0x03FF)
1110...高速PWM・TOP(ICR1)
1111...高速PWM・TOP(OCR1A)
OCR1AとICR1レジスタ
1[μs] * 50000 = 50[ms]
ICR1 = 49999
ICR1 = 50000
1[μs] * 25000 = 25[ms]
OCR1A = 24499
Rustでのプログラム実装
src/main.ts
#![feature(llvm_asm, lang_items, unwind_attributes)]
#![no_std]
#![no_main]
extern crate avr_delay;
extern crate avr_std_stub;
extern crate avrd;
use avrd::atmega328p::{DDRB};
use avrd::atmega328p::{TCCR1A, TCCR1B, OCR1A, ICR1};
use core::ptr::write_volatile;
#[no_mangle]
pub extern "C" fn main() {
unsafe {
//👇①TCCR1Aレジスタ
// COM1A1-COM1A0-COM1B1-COM1B0-無し-無し-WGM11-WGM10
// 1000(コンペアマッチAでLOW)-00-10(高速PWM・TOP(ICR1)モードの下位ビット)
write_volatile(TCCR1A, 0b10000010);
//👇②TCCR1Bレジスタ
// 1CNC1-1CES1-無し-WGM13-WGM12-CS12-CS11-CS10
// [プリスケーラx64]: 00-0-11(高速PWM・TOP(ICR1)モードの上位ビット)-011(1/64)
write_volatile(TCCR1B, 0b00011011);
//👇③周期間隔: 1μs * 65536 ~ 65.5ms
write_volatile(ICR1, 65535);
//👇④HIGH時間: 1μ * 32768 ~ 32.8ms (DUTY比0.5相当)
write_volatile(OCR1A, 32767);
//PB1ピンを出力として設定
write_volatile(DDRB, 0b00000010);
}
}
COM1A1-COM1A0-COM1B1-COM1B0
CS12-CS11-CS10
WGM13-WGM12-WGM11-WGM10
高速PWM・TOP(ICR1)モード
(低速)PWMを目視で確認
1 / 1[MHz] = 1E-6[s] = 1[μs]
1[μs] * 65536 = 65.536[ms]
約0.24Hz程度(4秒に一回)
まとめ
参考サイト
記事を書いた人
ナンデモ系エンジニア
電子工作を身近に知っていただけるように、材料調達からDIYのハウツーまで気になったところをできるだけ細かく記事にしてブログ配信してます。
カテゴリー