では続いてタイマー割り込みでLチカを行ってみたいと思います。
実はここ、結構ハマったポイントでして、それをやや強調して記事としていきたいと思います。
割り込みベクタ
ユーザーガイドで確認です。と調べると...
!?
device-specific ってなんじゃああいと言わんばかりの表です。申し訳ないが、ほぼ情報量ゼロ。
と文句垂れていますが、型番ごとに具体的な記述が何処かにあるのでしょう。これ以上は面倒くさくて調べなかったので僕にも落ち度はあります(?)。ここはひとまずペリフェラルの設定をしてしまいましょう。
設定箇所
今回は適当に TimerA を用いてLチカします。レジスタ一覧を見ると、ひとまず TACTL と TACCTL0 をいじればいいとわかります。やることとしては
- クロックソースの選択
- カウントモードの選択
- 分周の設定
- コンペアマッチ割り込みの設定
だけで良さそうです。なんだか単純で安心しました。
あ、実はまだクロックの種類と周波数さえ把握していないのですが、とりあえず動けばいいので今のところ適当にやっていきます(トホホ
割り込み関数の記述
ここが一番のハマりポイントです。そもそも記述法には2つあり、イマドキの方とレガシーな方です。とりあえずイマドキな方を調べてみた所、「以下のように書けばいいよ」と言っているサイトが多数ありました。
#pragma vector = TIMER0_A0_VECTOR
__interrupt TimerA0_Vect(void) {
hoge;
hage;
}
で実際にやってみたらこのエラーですよ。
要は「pragma vector
??そんなの知らないんだからねっ!!」ってことです。とりあえず闇雲に標準のヘッダファイルを見たり、ググってみたりしましたが解決せず。一度この書き方を諦めてレガシーな方で書いたんですが、まあレガシーですからね。そんなに良いものではないです。
というわけでイマドキな方法に戻ったのですが、なんと奇跡的にこのサイトを見つけました。どうやら gcc
では pragma
は使わずに、いつもの __attribute__()
を使えということらしいのです。なるほど!!実際にやってみました。
__attribute__((interrupt(TIMER0_A0_VECTOR))) void TimerA0_Vect(void) {
hoge;
hage;
}
これでコンパイルがなんとか通りました!良かったぁ...
ところでこれ、何でいつも括弧が二重に必要なんですかね??
この __attribute__()
についてです。割り込み関数では対応する割り込みを表すマクロを入れて「これこれの割り込み用の関数だよ〜ん」と gcc に教えてあげます。マクロの一覧は以下。
PORT1_VECTOR
PORT2_VECTOR
ADC10_VECTOR
USCIAB0TX_VECTOR
USCIAB0RX_VECTOR
TIMER0_A1_VECTOR
TIMER0_A0_VECTOR
WDT_VECTOR
COMPARATORA_VECTOR
TIMER1_A1_VECTOR
TIMER1_A0_VECTOR
NMI_VECTOR
RESET_VECTOR
記述する時はそれっぽいものを使えばいいと思います。
割り込みベクタへの登録
あまり良く分かっていないのですが、ひとまずグローバル割り込みを有効化すればいいらしいです。AVR みたいなものなのですかね。
つまり
_BIS_SR(GIE);
を書けばいいということになります。
そーすこーど
というわけで、出来たコードを以下に示します。
一旦〆
ということで動作できました!1秒間に大体3回くらいチカチカしていると思いますよ。え?PWM 使え??たしかにそうですね。
んで、実はまだ省電力設定をしていません。具体的には不要なクロックを止める、CPU 自体の電源を切ってしまう ということです。詳しくはまた次回!
追伸
自動車教習の卒検受かりました。AT限定で。