続いてタイマーを使ってみようの回です。需要なんて無視して進めていきます(前回の記事のアクセス数が少ない...)。
ユーザマニュアルの入手
忘れていました。その前に、ユーザマニュアルを入手しましょう。STCmicro のデータシートは 間違いが多い ので、Intel のものを見ることがおすすめです。「intel 8051 user manual pdf」とでも検索すれば出ると思います。
タイマーを使ってみる
タイマーは Timer0 と Timer1 の2つがあるのですが(STC マイコンは 8052 ベースなので Timer2 もある)、動作モードが複数あります。
今回はカウントアップによるオーバーフロー と リロード値の設定ができる Mode 2 を扱います。
また、クロックは システムクロックを12分周したもの となっていますので、XTAL に 12MHz を入れた場合は 1MHz で動くんですね。
簡易1msecタイマー
とりあえず汎用のディレイを作りましょう。ソースコードを以下に示します。
#include <stdint.h>
#include <8052.h>
void ms_wait(uint32_t ms) {
TMOD |= 0x02; // timer0, mode2
TL0 = 256U - 100U; // counter
TH0 = 256U - 100U; // reload
TR0 = 1; // (TCON) timer0 enable
for(uint32_t i=0; i<ms * 10UL; i++) {
while( !TF0 ); // (TCON)
TF0 = 0;
}
TR0 = 0; // (TCON) timer0 disable
}
Mode2 では、TLx
がカウンター、THx
がリロード値として働き、それぞれ 8bit 値です。このモード設定を TMOD
で行っているというわけです。
タイマークロックは 1MHz なのでオーバーフローイベントを 1msec 毎に起こせば解決なのですが、リロード値を 1000
とするとこれは 8bit に収まりませんから、とりあえず 100
として、ループ側で対応をしています。
タイマーがオーバーフローを起こすと TFx
がセットされます。割り込みを有効化するとベクタに飛び、自動的にフラグがクリアされるのですが、今回は割り込みを使用しないため手動でクリアしています。
使い方はこんな感じにすればいいと思います。
#include <stdint.h>
#include <8052.h>
int main(void) {
while(1) {
P1_0 ^= 1;
ms_wait(1000);
}
}
割り込みを起こす
この場合の初期化コードは上とそれほど変わりません。ただし、追加で以下の設定が必要です。
IE
レジスタで全割り込み有効化IE
レジスタで Timer0 のオーバーフロー割り込み有効化
ペリフェラル側の設定は要らないようで(外部入力割り込みの場合は設定が必要、でも今回は関係ないですね)、比較的シンプルに書けます。
ここで、sdcc
コンパイラ特有の書き方に注意です。割り込み関数は __interrupt(vector_num)
ということを書かなければなりません。また、割り込み関数を別ファイルに書いた場合、main 関数があるファイル内にも __interrupt()
付きの関数プロトタイプ宣言を記載する必要があります。
それでは初期化関数は以下です。
void timer0_irq_init(void) {
EA = 1; // (IE) enable all interrupts
ET0 = 1; // (IE) timer0 interrupt enabled
TMOD = 0x02; // timer0, mode2
TL0 = 256U - 100U; // counter
TH0 = 256U - 100U; // reload
TR0 = 1; // (TCON) timer0 enable
}
割り込み関数と main 関数はこんな感じでいいですかね。こちらも 1msec で LED をチカチカさせるようにしてあります。
int main(void) {
timer0_irq_init();
while(1);
}
void timer0_isr(void) __interrupt(1) {
volatile static uint32_t cnt = 0;
if( cnt++ == 1000U * 10 ) {
P1_0 ^= 1;
cnt = 0;
}
}
これでタイマーの使い方は以上です。設定が簡単でしたね。
これは機能が少ないからであって、AVR のような CTC や、その他 PWM 等の機能はありません。