フォト
2018年6月
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
無料ブログはココログ

« Arduino STM32で漢字表示 | トップページ | micro:bitをArduino環境で使う (2)GPIOTEを使ったLチカ »

2017年11月24日 (金)

micro:bitをArduino環境で使う (1)タイマー割り込みでLチカ

前回の「micro:bitはじめました」では、microbitをArduino IDE環境で利用出来るようにしました。
今回はそのArduinoIDEを使ってタイマー割り込みを使ってLチカをやってみました。

Dscn7318


microbitに搭載されているARM Cortex-M0 nRF51822でタイマ割り込みを行う場合、
タイマかRTCを使って実現できるようです。
今回はタイマを使って5x5マトリックス左上LEDを0.5秒間隔で点滅させてみました。


スケッチ

#include "nrf.h"

const int COL1 = 3;     // Column #1 control
const int LED = 26;     // 'row 1' led
uint8_t sw =0;

extern "C" void TIMER2_IRQHandler(void) {
    NRF_TIMER2->EVENTS_COMPARE[0] = 0;  // 割り込みイベントクリア
    sw =!sw;
    digitalWrite(LED, sw);
}

void setup() {
  Serial.begin(115200); 
  Serial.println("microbit is ready!");
  pinMode(COL1, OUTPUT);
  digitalWrite(COL1, LOW);     
  pinMode(LED, OUTPUT);

  //タイマ設定
  NRF_TIMER2->TASKS_STOP = 1;                          // タイマストップ
  NRF_TIMER2->TASKS_CLEAR = 1;                         // カウンタクリア
  NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer;            // モード設定:タイマモード
  NRF_TIMER2->PRESCALER   = 8;                         // プリスケーラ設定:256分周(62.5kHz)
  NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit;   // カウンタ長設定:16ビット長指定
  NRF_TIMER2->CC[0] = 62500/2;                         // コンパレータ0の設定:0.5秒周期
  NRF_TIMER2->INTENSET =                               // 割り込み設定:コンパレータ0と比較
      (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);
  NRF_TIMER2->SHORTS =                                 // ショートカット設定:クリアタスク指定
      (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos);
  
  // タイマ割り込み設定
  NVIC_SetPriority(TIMER2_IRQn, 3);   // 割り込み優先度設定
  NVIC_ClearPendingIRQ(TIMER2_IRQn);  // 保留割り込みクリア
  NVIC_EnableIRQ(TIMER2_IRQn);        // 割り込み許可
  
  NRF_TIMER2->TASKS_START = 1;        // タイマスタート
  
}

void loop(){

}

解説

タイマー割り込みはTIMER2のレジスタを直接操作して実装しています。
(TIMER1は、PWM出力で利用されているため使わない方がよいでしょう)

まず、割り込みで呼び出される関数が、TIMER2_IRQHandler(void)です。
この関数名は固定で、extern "C"を付けてC言語互換にする必要があります。

呼び出された割り込み関数内では、割り込みイベントをクリアする必要があります。
   NRF_TIMER2->EVENTS_COMPARE[0] = 0;

にてそれを行っています。コンパレータ0を使った割り込みのため、対応するイベントを
クリアしています。

次に、タイマ設定についてすが、最初の2行はコメントの通りで、タイマをストップして
カウンタをクリアしてます。
  NRF_TIMER2->TASKS_STOP = 1;     // タイマストップ
  NRF_TIMER2->TASKS_CLEAR = 1;   // カウンタクリア

次の2行は、タイマのモード設定とプリスケーラ(分周)を設定しています。
  NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer;   // モード設定:タイマモード
  NRF_TIMER2->PRESCALER   = 8;                            // プリスケーラ設定:128分周(125KHz)

タイマのモードには、タイマモードと、キャプチャモードがあります。
クロックを供給してカウントする動作を行う場合はタイマモードを指定します。

プリスケーラの設定は0~9まで指定可能です。次の表の感じでシステムクロックの
16MHzを分周して、カウンタのソースクロックの周波数を設定できます。
スケッチでは8を指定しているので、256分周で62,500Hzを利用しています。

  02

さらに次の2行はカウンタ長とコンパレータ0の値を設定しています。
   NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit;   // カウンタ長設定:16ビット長指定
   NRF_TIMER2->CC[0] = 62500/2;                                             // コンパレータ0の設定:0.5秒周期

TIMER2のカウンタ長は8ビット幅、16ビット幅の指定が可能です。
16ビットでは65535カウント(約1048ミリ秒)までカウントできます。

コンパレータはカウンタとの比較に利用するものです。
カウンタ値を一致した場合に割り込みを発生することが出来ます。
コンパレータは4つ利用出来ますが、ここではコンパレータ0を利用しています。

コンパレータ0のビット長はタイマのカウンタ長に準じます。
ここでは62500/2を指定しています。ちょうど0.5秒幅です。

次の4行は、割り込み条件の設定とショートカットの設定を行っています。
  NRF_TIMER2->INTENSET =                               // 割り込み設定:コンパレータ0と比較
      (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);
  NRF_TIMER2->SHORTS =                                 // ショートカット設定:クリアタスク指定
      (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos);

NRF_TIMER2->INTENSET にはコンパレータ0を一致したら割り込み発生するように指定、
NRF_TIMER2->SHORTS には割り込みのイベント発生時にカウントをクリア(0)にする
設定を行っています。この設定を行わないと、コンパレータ0を一致した後もカウンタが
クリアされないので、割り込み周期は16ビット幅のオーバーフロー発生の周期になります。
NRF_TIMER2->SHORTSを行わずに、割り込み関数内でカウンタをクリアしても良いです。

次の3行は、割り込み優先度の設定等です(コメント参照)
   NVIC_SetPriority(TIMER2_IRQn, 3);       // 割り込み優先度設定
   NVIC_ClearPendingIRQ(TIMER2_IRQn);  // 保留割り込みクリア
   NVIC_EnableIRQ(TIMER2_IRQn);           // 割り込み許可

最後に、タイマをスタートさせます。
   NRF_TIMER2->TASKS_START = 1;        // タイマスタート

タイマについては、PPI(Programmable Peripheral Interconnect)との連携方法がまだわかりません。
PPIを使えば、割り込みを使わずにLチカ出来ると思っているのですが。

     => 2018/06/22 PPIの使い方がわかりました。下記の記事を参考願います。
        micro:bitをArduino環境で使う (5) PPIを使ったLチカ

このあたりのレジスタマップ定義はArduino IDEのnRF51環境にnRF51 SDKが
組み込まれているために利用出来ているようです。
まとまったドキュメントを探しているのですが、見つからないので
Arduino IDEのnRF51環境周りをdoxygenにかけてドキュメント化して利用しています。

03_2

2017/11/25 追記
Arduino IDEのnRF51環境周りのファイルを調べると、nRF5_SDKのうち、
ヘッダファイルの一部しか入っていないことが判明。SDKは実質レジスタ等の定義のみです。

関連記事
  micro:bitをArduino環境で使う (2)GPIOTEを使ったLチカ
  micro:bitをArduino環境で使う (5) PPIを使ったLチカ

« Arduino STM32で漢字表示 | トップページ | micro:bitをArduino環境で使う (2)GPIOTEを使ったLチカ »

arduino」カテゴリの記事

ARM」カテゴリの記事

micro:bit」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/571408/66081854

この記事へのトラックバック一覧です: micro:bitをArduino環境で使う (1)タイマー割り込みでLチカ:

« Arduino STM32で漢字表示 | トップページ | micro:bitをArduino環境で使う (2)GPIOTEを使ったLチカ »