ロボットを創ろう
ロボットを創ろうの掲示板 二足歩行ロボット掲示板 新型ロボットプランニング研究サークル

4月29日 コンペアマッチタイマ(CMT)を使う


現在の構成です。電源+5V、SH2(7045f)、16*32赤LEDです。

コンペアマッチタイマを使って1秒間隔でLEDの点灯と消灯を繰り返すプログラムを作ります。

 簡単にコンペアマッチタイマと言っても、私は何も知りません。どういうものなのか、どういった機能なのか・・・全てがわかりません。回りでは簡単だよ・・・なんて声が聞こえますが、私は何も知らない初心者です。
 というわけで、まずはハードウェアマニュアルを見て勉強してみます。

 ハードウェアマニュアル 17章コンペアマッチタイマ(CMT)を読みます。専門用語が多すぎて、さっぱりわかりませんがいずれ理解できるものだと思って、17章を読みきりました。ここでは、内容を噛み砕いたものを書くということはしませんので、みなさん自分で読んでみてください。私には噛み砕くなんてことはできませんので・・・
 マニュアルを読んだだけではさっぱりわかりません。なんとなく機能を知ることはできました。次は、サンプルプログラムを見ます。人が作ったプログラムをみて、どのように使われているのかを見ます。
 このプログラムはベストテクノロジーのホームページからダウンロードできます。
 このサンプルプログラムをみて、何やら見たことのある文字があります。ハードウェアマニュアルに書いてある文字がありました。自分なりに1秒をカウントするプログラムに作り直してみます。
 実行結果はこんな感じです。(76.7kByte)


 私が作ったプログラムは・・・・・普通のLEDの点灯ではないので役に立たないですね。while文の中にあるdot()を自分の環境にあわせてLED点灯にしてください。dot(x、y)は(x,y行)のLEDを光らせるというものです。

それでは具体的にプログラムの中身を見ていきます。タイマーに関連しているのはinitSH()関数です。


  CMT0.CMCSR.BIT.CMIE = 0; // 割り込み禁止
  CMT0.CMCSR.BIT.CKS = 1; // φ/32=875kHz
  CMT0.CMCSR.BIT.CMF = 0; // フラグクリア
  CMT0.CMCNT = 0; // コンペアマッチカウンタクリア
  CMT0.CMCOR = 875; // コンペアマッチコンスタントカウンタ 1ms


CMT0 : コンペアマッチタイマ0
┣CMCSR : コンペアマッチタイマコントロール/ステータスレジスタ
┃  ┗BIT : ビット
┃    ┣CMIE : コンペアマッチ割り込みイネーブル
┃    ┣CKS : クロックセレクト
┃    ┣CMF : コンペアマッチフラグ

┣CMCNT : コンペアマッチタイマカウンタ
┗CMCOR : コンペアマッチタイマコンスタントレジスタ

ここまでくると、さっきハードウェアマニュアルを読んでおいてよかったなぁって思います。すぐにどこに何が書いてあったかがわかるし、プログラムもある程度読めました。構造体ってやつは、ドットで名前をつなぐことで表現しているってことでしょうか

CMCSR
ビット: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- - - - - - - - CMF CMIE - - - - CKS1 CKS0
初期値: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
R/W R R R R R R R R R(W*) R/W R R R R R/W R/W


  CMT0.CMCSR.BIT.CMIE = 0; // 割り込み禁止
コンペアマッチタイマ0のコンペアマッチタイマコントロール/ステータスレジスタを変更しています。このレジスタのCMIEというビットの値を変更します。1を入れるとコンペアマッチ割り込みを要求し、0を入れると割り込みを禁止します。

  CMT0.CMCSR.BIT.CKS = 1; // φ/32=875kHz
 システムクロックφ(28MHz)を分周して得られる4種類の内部クロックからCMCNTに入力するクロックを選択します。CKSに1を入れるとφ/32が選択されます。0だとφ/8、2だとφ/128、3だとφ/512です。詳細はハードウェアマニュアルp.612です。

  CMT0.CMCSR.BIT.CMF = 0; // フラグクリア
 CMFには0のみを書き込むことができます。CMCNTとCMCORが一致するとこのCMFの値が1になります。

  CMT0.CMCOR = 875; // コンペアマッチコンスタントカウンタ 1ms
 CMCORは16ビットのレジスタです。パワーオンリセットまたはスタンバイモードでH'FFFFに初期化されます。マニュアルリセットでは初期化されません。つまり電源を入れるとH'FFFFに初期化されてるが、リセットボタンを押しても初期化されません。
 875という値は、φ/32=875kHzより、875回カウントすると1msになるということです。1msごとにCMFが1になります。CMIEが1になっていたならば、1msごとに割り込みが発生するということです。

 ここまででタイマの初期化が終わりました。それではタイマーを早速使ってみましょう。
  /*--------------------------------------------------------------*/
  /* ウェイト */
  /*--------------------------------------------------------------*/
  void wait(long num)
  {
  int i;

  CMT.CMSTR.BIT.STR0 = 1; // カウント開始
  for (i = 0; i < num; i++) {
  while (!CMT0.CMCSR.BIT.CMF) ;
  CMT0.CMCSR.BIT.CMF = 0;
  }
    CMT.CMSTR.BIT.STR0 = 0; // カウント停止
  }



  CMT.CMSTR.BIT.STR0 = 1; // カウント開始
 CMSTRはCMT0,CMT1で共通になっています。STR0はCMCNT1を動作させるか、停止させるかを選択します。詳細はp.611

  while (!CMT0.CMCSR.BIT.CMF) ;
 CMT0.CMCSR.BIT.CMFが0である間は、無駄にループしてます。がついているので、値が反転します。1msでループから出ます。

  for (i = 0; i < num; i++) {
  while (!CMT0.CMCSR.BIT.CMF) ;
  CMT0.CMCSR.BIT.CMF = 0;
  }
 1msをnum回繰り返します。numが1000であれば、1秒間ループします。

 初心者には優しくない解説になっています・・・・質問をしてもらえれば、よりよい記事がかけますので、是非掲示板に書き込みをしてください。可能な限り調べて答えます。

以上

このページで紹介している写真は無断で転載することを禁止します。ただし、記事を模倣してロボットを創ることは大歓迎です。