Go言語でMCUのコードを生成できるTinyGoでATSAMD21マイコンの周辺回路を勉強しております。前回までunsafeなポインタを使って直接アクセスする不作法をしてました。今回は machine モジュールを使ってTCC1からPWM波形を出力してみます。制御は簡単なのですが、データシートを読むのがメンドイ。
※「AT SAMの部屋」 投稿順indexはこちら
ATSAMD21マイコンのタイマ・カウンタ
Arm Cortex-M0+コア搭載、MicroChip社のATSAMD21は32ビットマイコンとしてはローエンド品種だと思いますが、モダーンなマイコンの通例に漏れずタイマ・カウンタ類は充実しています。TCC(TIMER / COUNTER FOR CONTROL )と表記される入出力機能が充実したゴージャスなタイマ・カウンタを3本。TC(TIMER/COUNTER)と表記される、主に基本的なタイマ/カウンタとして使うけれども入出力もできるものが5本あります。それらには連番が振られています。
-
- TCC0~TCC2
- TC3~TC7
TCCは24ビットのカウンタ1本に対して、4チャネルのコンペア・キャプチャ(CC)を持っています。各チャネルは所定の外部出力端子に接続できるので、TCCを全てPWMに使うとすると4チャネルx3本で最大12端子まで可能です。
一方、TCは基本16ビットのカウンタで、半分の8ビット使いも可能。また2本を組み合わせて32ビットとしても使えるようになっています。各TCには、TCCのものより機能は落ちますがコンペア・キャプチャ(CC)2チャネルがあるので入出力も可能です。こちらを数えれば2x5で10チャネルとな。
出力についてはTCCもTCもチャネルと外部端子の対応関係はハードで決まっています(ただし多対多の関係。)
入力機能はATSAMD21のもつ近代的な制御ハードEVSYS経由でイベントと結び付けられるので出力のようなキメウチでもないようです。また後でEVSYSも動かしてみます。
Seeduino Xiaoボード上で出力に使えるタイマ・チャネル
上記のように充実したATSAMD21のタイマ・カウンタ機能なのですが、出力に限ると実際に使えるタイマは限られます。まずXiaoボードに搭載されているATSAMD21G18は48ピンの比較的小ピンの品種です。出ていない端子があります。さらに超小型のXiaoボードです。使用できるデジタルピンの数はたかだか11端子のみ。
そこでXiaoボードの端子名とATSAMD21マイコンのPIN名、そしてそれらピンに出力可能なカウンタ/タイマとそのチャネル名を以下にまとめました。例えば
TCC0/WO[0]
とかかれていたら、TCC0 のチャネル0の出力をその端子に出力できるという意味です。Func E と Func Fと2つの列がありますが、これは前回も出て来たPMUXレジスタの行き先選択で使える選択肢です。TinyGoの「定数」とは以下のような関係となります。
-
- Func E、PinMode=4 あるいは PinTimer または PinTCC
- Func F、PinMode=5 あるいは PinTimerAlt または PinTCCAlt
Xiao端子名 | ATSAMD21G18 pin名 | Func E | Func F |
---|---|---|---|
D0 | PA02 | — | — |
D1 | PA04 | TCC0/WO[0] | — |
D2 | PA10 | TCC1/WO[0] | TCC0/WO[2] |
D3 | PA11 | TCC1/WO[1] | TCC0/WO[3] |
D4 | PA08 | TCC0/WO[0] | TCC1/WO[2] |
D5 | PA09 | TCC0/WO[1] | TCC1/WO[3] |
D6 | PB08 | TC4/WO[0] | — |
D7 | PB09 | TC4/WO[1] | — |
D8 | PA07 | TCC1/WO[1] | — |
D9 | PA05 | TCC0/WO[1] | — |
D10 | PA06 | TCC1/WO[0] | — |
今回実験のソースコード
以下のような設定でPWM信号を出力してみます。
-
- 外部出力端子 D3
- 使用するタイマ・カウンタは TCC1、チャネルは1番
- 周波数 100kHz
- デューティ 25%
ソースコードが以下に。
package main import ( "fmt" "machine" "time" ) func main() { counter := 0 pwmOut := machine.D3 pwmOut.Configure(machine.PinConfig{Mode: machine.PinTimer}) machine.TCC1.Configure(machine.PWMConfig{Period: 10000}) ch, _ := machine.TCC1.Channel(machine.D3) machine.TCC1.Set(ch, (machine.TCC1.Top() / 4)) for { counter++ fmt.Println(ch, counter) time.Sleep(1000 * time.Millisecond) } }
実機動作確認
D3端子に出力された波形を観察したものが以下に。ほぼ100kHz、25%デューティとなってます。
今回はunsafeなポインタ使わなかった。よかった?また次回は分かりませぬが。