前回のクロック設定に引き続き、ひとまずマイコンの登竜門、Lチカをしていきましょう。
...とはいっても、このマイコンは ARM なので、サクッと終わってしまいます。
SysTickタイマの設定
毎度おなじみ、SysTick です。ここでは割り込みを入れずにカウントしたいと思います。早速ですが、1msec ウェイトをするプログラムを示します。
// CPU clock is divided by 1
void ms_wait(uint16_t msec) {
SysTick->LOAD = 48e6 / 1e3 - 1;
SysTick->VAL = 0;
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
for(uint16_t i=0; i<msec; i++) {
while( !(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) );
}
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}
どうやら SysTick のクロックは CPU からの分周無しで接続されているようです。よって、1msec タイマーとするために 1000(1e3
)で割っておきました。
レジスタの打ち方
ちょっと一癖あります。普通のマイコン通り、構造体ポインタを使えば良いのですが、ちょっと独特です。
例えば PM
というクロック供給関連のペリフェラルにある APBCSEL
レジスタにアクセスしたい時は PM->APBCSEL.reg
と .reg
が必要です。これはルネサス系マイコンの .BYTE
や .WORD
に対応するものです。更に、レジスタのビットに直接アクセスしたい時は PM->APBCSEL.bit.APBCDIV
というふうに .bit
をつければいいです。これもルネサス系マイコンでは .BIT
で表現されますね。
これとは別に、同じペリフェラルでも動作モードの違いを書く必要があるというクセがあります。例えばシリアル通信をするペリフェラルの1つである SERCOM0
です。SPI 通信で使う時は SERCOM0->SPI.BAUD.reg
というように SPI
を記述し、I2C で使う時は SERCOM0->I2CM.BAUD.reg
と記述します。
他にも、タイマーである TC
でも、「TC3
の 16bit カウント動作時の CTRLA
レジスタ」は TC3->COUNT16.CTRLA.reg
となります。げえぇっ。
更に更に、今回使う PORT
にもクセがあります。IO ポートには PAx や PBx がありますが、まずここで PAx を Group[0]
として見ます。同じように PBx は Group[1]
です。この時に DIR
レジスタにアクセスしたいなぁとなった時は PORT->Group[0].DIR.reg
になります。う〜〜ん、分かりづらい。
他にも、PORT でピンのマルチプレクシング設定やプルアップの設定を行うレジスタ(PINCFG
)は各ポートごとに独立したレジスタになっていますから、PORT->Group[0].PINCFG[9].reg
と書く必要があったり...結構大変です。
今回は Lチカ だけなので設定自体はだいぶ楽です。
PORT
いわゆる GPIO です。他のマイコン(STM32 とか)ではこのペリフェラルに対してクロック供給をすることが必要でしたが。このマイコンではデフォルトでオンのため、設定が不要です。ですのでいきなりポート設定に入ってしまいます。
今回は PA15 (24番pin) でチカチカさせたいと思います。
入出力方向
LED をチカチカさせるためには OUTPUT とする必要があります。データシートを見ながらそのコードを書いてみると以下のようになるでしょう。
PORT->Group[0].DIR.reg |= (1 << 15); // output
もちろんこれで良いです。ただ、データシートをよく見ると SET 用、 CLEAR 用のレジスタがわざわざ用意されているので、
PORT->Group[0].DIRSET.reg = (1 << 15); // output
としたほうが簡単っちゃ簡単です。
データ出力も同様で、High を出すために
PORT->Group[0].OUT.reg |= (1 << 15);
としても
PORT->Group[0].OUTSET.reg = (1 << 15);
としてもいいです。なお、この SET 用レジスタは PORT のみにあるようです。
さらに、今回は LED をチカチカするので 1秒ごとに出力を反転させたいです。そのためにうってつけのレジスタがあって、OUTTGL
(Output Toggle) です。これを使えばスマートにかけますね。
そんな訳で、Lチカのプログラムを以下に示します。sysclk_init
は前回の記事を参考にしてください。