目次

タイマー操作

 LPC1114には、2種4個のタイマーカウンタがあります。

 16ビットのタイマーカウンタは、CT16B0、CT16B1の2種、
 32ビットのタイマーカウンタは、CT32B0、CT32B1の2種。

 タイマーカウンタは、コンペアマッチ出力、キャプチャ
 入力ができます。

 タイマーカウンタに関係するピンアサインは、以下。



 16ビットだけに限定したピンアサインを見ると、コンペアマッチ
 とインプットキャプチャで、以下。



 32ビットだけに限定したピンアサインを見ると、コンペアマッチ
 とインプットキャプチャで、以下。



 コンペアマッチとインプットキャプチャに分けて、動作を確認します。


コンペアマッチ  ピンアサインを確認したならば、CONFIGRATIONに移ります。  タイマーカウンタに関係するSFRを探すと、以下。 16ビットのタイマーカウンタ関係。 32ビットのタイマーカウンタ関係。  タイマーカウンタでは、プリスケーラとカウンタが一体となり  分周したクロックを生成します。  16ビットは、CT16B0とCT16B1の2チャネルあり、プリスケーラと  カウンタは16ビットになっています。  同様に、32ビットは、CT32B0とCT32B1の2チャネルあります。  プリスケーラ、カウンタともに32ビットで構成。  カウンタと4つあるレジスタの値を比較して、一致したときに  何をするのかを指定するのがコンペアマッチ操作。  レジスタは、CT16B0とCT16B1が16ビット、CT32B0とCT32B1が  32ビットになっています。  出力がどこにアサインされているかを見れば、使いたい  タイマーカウンタとビット数が整合しているか、判断  する材料になります。  CT16B0に関係するレジスタのアドレスは、以下。  CT16B1に関係するレジスタのアドレスは、以下。  CT32B0に関係するレジスタのアドレスは、以下。  CT32B1に関係するレジスタのアドレスは、以下。  LPC1114には、PLLのハードウエアがあるので、動作する  最高周波数として、48MHzを設定しておきます。  Forthワードでは、次のように定義すればよいそう。 : 48MHz ( -- ) 0 $40048070 ! \ MAINCLKSEL: Switch to IRC "Internal RC oscillator" clock 0 $40048074 ! \ MAINCLKUEN: Toggle this bit from zero 1 $40048074 ! \ to one to update clock selection 1 7 lshift $40048238 bis! \ PDRUNCFG: Set power-down bit for PLL \ FCLKOUT = M * FCLKIN = FCCO / (2*P) \ Specify the input clock frequency FCLKIN. \ Calculate M to obtain the desired output frequency FCLKOUT with M = FCLKOUT / FCLKIN. \ Find a value so that FCCO = 2 * P * FCLKOUT. \ FCCO needs to be between 156 and 320 MHz. \ Ensure that FCLKOUT < 100 MHz. \ Here: FCLKIN = 12 MHz \ M = 48 MHz / 12 MHz = 4 \ FCCO = 2 * 2 * 48 MHz = 192 MHz 3 \ Feedback divider value, ranging from 0 (M=1) to 31 (M=32) 1 5 lshift or \ Post divider ratio: 0: P=1 1: P=2 3: P=4 4: P=8 $40048008 ! \ SYSPLLCTRL: Configure PLL dividers 1 7 lshift $40048238 bic! \ PDRUNCFG: Clear power-down bit for PLL begin $4004800C @ until \ SYSPLLSTAT: Wait for lock of PLL $4003C010 @ 3 bic 2 or $4003C010 ! \ FLASHCFG: Set wait states for frequencies up to 50 MHz 4 $40048098 ! \ UARTCLKDIV: Divide 48 MHz / 4 = 12 MHz to get desired baud rate of 115200 baud. 3 $40048070 ! \ MAINCLKSEL: Switch to PLL output 0 $40048074 ! \ MAINCLKUEN: Toggle this bit from zero 1 $40048074 ! \ to one to update clock selection 48000 flash-khz ! \ Update current clock frequency, it is needed to write flash. ;  上のワードをTeraTermを利用して、ワード「48MHz」をタイプすれば  48MHzでシステムが動くようになります。  デフォルトでは、12MHzになっているよう。  動作指定のレジスタがあるので、このレジスタに  パラメータを設定してモードを指定します。  タイマーカウンタを使うか否かは、コントロールレジスタで制御。  コントロールレジスタに与える値が1で利用、2を設定すると  タイマーカウンタをクリアになります。  コントロールレジスタのアドレスは、以下。
  • $4000C004
  • $40010004
  • $40014004
  • $40018004  ワード「constant」で定義すると、次のようになるでしょう。 $4000C004 constant CT16B0TCR $40010004 constant CT16B1TCR $40014004 constant CT32B0TCR $40018004 constant CT32B0TCR  コンペアマッチで、ピンに接続したLEDを点滅させられます。  点滅には、タイマーカウンタの内蔵ブロックをどう接続して  信号を渡すのかを図示して考えます。  PIO1_9に論理値の'1'か'0'を出力するために、コンペアマッチ  レジスタ0を利用。  タイマーカウンタの値が、コンペアマッチレジスタ0の値より  小さいと'0'を出力し、以上であれば'1'を出力する仕様から  カウンタの値Nを決定します。  タイマーカウンタの値が指定値Mになったならば、ゼロに  戻るように、コンペアマッチレジスタ1にMを設定。  N<Mという条件をつけることに注意です。  点滅動作を確定したので、プリスケーラで、どのくらいの  周期(周波数)でタイマーカウンタの値を増やすのかを  決めておきます。  プリスケーラは、16ビットカウンタなので、12MHzを12  分周して、1MHz(=1us)を生成。  プリスケーラの値は、分周比の値より1だけ小さくします。  次にコンペアマッチレジスタに設定する値のN、Mを考えて  いきます。1秒ごとに点灯、消灯を交互に繰り返すとすると  1000msごとに、タイマーカウンタをリセットすればよいので  1MHz/1kHz=1000Hz/1Hz=1000と計算できます。  1周期の間に、'1'と'0'を並べて、'1'の割合を示す数値を  Duty比と呼びますが、このDuty比を決めればよくなります。  Duty比を50%にすると、N=500、M=999と計算  できます。  CT16B1にクロックを供給し、動作するようにして  さらに、コンペアマッチ処理を指定します。 \ SFR $40048080 constant CLKCTRL $40044038 constant PIO1_9 \ enable CT16B1 1 8 lshift CLKCTRL bis! \ select compare match PIO1_9 @ 1 or PIO1_9 !  ここまでの内容をコードで設定すると、以下。 \ SFR $40048080 constant CLKCTRL $40044038 constant PIO1_9 $40010004 constant CT16B1TCR $40010008 constant CT16B1TC $4001000C constant CT16B1PR $40010010 constant CT16B1PC $40010018 constant CT16B1MR0 $4001001C constant CT16B1MR1 \ enable CT16B1 1 8 lshift CLKCTRL bis! \ select compare match PIO1_9 @ 1 or PIO1_9 ! \ stop timer counter 1 2 CT16B1TCR ! \ set prescaler 11 CT16B1PR ! \ clear prescaler counter 0 CT16B1PC ! \ clear timer counter 0 CT16B1TC ! \ set match register 0 500 CT16B1MR0 ! \ set match register 1 999 CT16B1MR1 !  コンペアマッチが発生して、一致したときに出力が  どうなるかかを指定します。一致したときに出力値  が反転するように設定してみます。  コンペアマッチ割込みに関係する設定は、マッチコントロール  レジスタで指定する仕様。3ビットずつ、合計12ビットの  設定値になります。  マッチコントロールレジスタの構成は、以下。  コンペアマッチレジスタ1の値で、カウンタをリセットすると  同時に割込みを発生させるので、レジスタへの設定は、次の  コードになります。 $40010014 constant CT16B1MCR \ if MR1 = TC , then reset and enable interrupt $10 CT16B1MCR !  トグル動作をするので、その設定が必要。  タイマーカウンタ1のコンペアマッチに関係する  レジスタのアドレスは、$4001003Cになっています。  このレジスタのビット5、4でマッチレジスタ0の  値が一致したときに、トグル動作になるよう指定。  トグル動作にするので、Forthコードは以下。 $4001003C constant CT16B1EMR \ if TC = MR0 , send 'H' or 'L' to pin 3 4 lshift CT16B1EMR !  I/Oピンでは、タイマーカウンタの機能を利用できるように  設定しなければなりません。PIO1_9に関係するレジスタの  ビット構成は、以下。  LEDを点滅させるForthコードにまとめます。 \ SFR $40048080 constant CLKCTRL $40044038 constant PIO1_9 $40010000 constant CT16B1IR $40010004 constant CT16B1TCR $40010008 constant CT16B1TC $4001000C constant CT16B1PR $40010010 constant CT16B1PC $40010014 constant CT16B1MCR $40010018 constant CT16B1MR0 $4001001C constant CT16B1MR1 $4001003C constant CT16B1EMR \ CT16B1 enable 3 7 lshift CLKCTRL bis! \ set P1.9 compare match output with CT16B1_MAT0 PIO1_9 @ 1 or PIO1_9 ! \ Time Control Register disable 2 CT16B1TCR ! \ MR1 -> Reset TC 1 4 lshift CT16B1MCR bis! \ Set Prescale Register 11 CT16B1PR ! \ 500 -> MR0 500 CT16B1MR0 ! \ 999 -> MR1 999 CT16B1MR1 ! \ if TC = MR0 , send 'H' or 'L' to pin 3 4 lshift CT16B1EMR ! \ start 1 CT16B1TCR !  これらのコードを、端末で正確に入力するのは  大変なので、TeraTermを利用してエディタから  Clip Board経由でのDrag & Dropするのが良い  でしょう。  周波数に関係する処理なので、PIO1_9に  スピーカを接続し、動作チェックしました。  LPC1114のPIO1_9のドライブ能力でも、矩形波を  出力するので、スピーカを鳴らせます。
    インプットキャプチャ  外部信号を受けたときに、その時点のカウンタの値を  コピーしてレジスタに格納します。そのレジスタが  キャプチャレジスタで、16ビットと32ビットでそれ  ぞれ2個用意されています。  ピンアサインは、以下。  制御レジスタとキャプチャレジスタのアドレスは、以下。
  • CT16B0CCR $4000C028
  • CT16B1CCR $40010028
  • CT16B0CR0 $4000C02C
  • CT16B0CR1 $4000C030
  • CT16B1CR0 $4001002C
  • CT16B1CR1 $40010030
  • CT32B0CCR $40014028
  • CT32B1CCR $40018028
  • CT32B0CR0 $4001402C
  • CT32B0CR1 $40014030
  • CT32B1CR0 $4001802C
  • CT32B1CR1 $40018030  キャプチャレジスタの面白いのは、ブロックが  異なっても、ビットサイズが同じなら入力ピン  を指定できます。  制御レジスタのビット割当ては、以下となっています。  信号のrising_edge、falling_edgeのどちらで  内部カウンタの値をコピーするかと割込みを  発生させるか否かを指定します。  カウンタを指定クロックでインクリメントして  割込みでカウンタの値を読み込んで差を求める  と、信号の周期やHあるいはLの時間を計算する  ことが可能に。  信号のrising_edge、falling_edgeの両方で  内部カウンタの値をコピーして2値を取得。  得られた2値の差の絶対値に係数を乗算して  みれば、時間差を求められます。  タイミングチャートで見ると、以下。
     32ビットのタイマーカウンタを利用してみます。  PIO1_1、PIO1_2は、機能設定されていません。  実際に端末ソフトで確認しました。  PIO1_1、PIO1_2を、GPIOとして利用するには  該当するレジスタの値で、LSBを1にします。 $4004407C @ 1 OR $4004407C !{enter} $40044080 @ 1 OR $40044080 !{enter}  これが、正しく動作するのかは、PIO1_1、PIO1_2を  出力に設定して、2進数で3、2、1、0をライト  すればよいはず。 $3FF $50018000 ! \ all outputs 3 1 lshift $50013FFC ! \ MSB = 1 LSB = 1 2 1 lshift $50013FFC ! \ MSB = 1 LSB = 0 1 1 lshift $50013FFC ! \ MSB = 0 LSB = 1 0 1 lshift $50013FFC ! \ MSB = 0 LSB = 0  PIO1_1、PIO1_2を、タイマーカウンタのコンペア  マッチ出力として利用するには、次のワード設定  が必要。 $4004407C @ 3 OR $4004407C !{enter} $40044080 @ 3 OR $40044080 !{enter}  カウンタタイマーモジュールには、クロックを  与えないと、使えないので、供給。  動作は、次のワード定義と設定で処理。 \ SFR $40048080 constant CLKCTRL $4004407C constant PIO1_1 $40044080 constant PIO1_2 $40018004 constant CT32B1TCR $40018008 constant CT32B1TC $4001800C constant CT32B1PR $40018010 constant CT32B1PC $40018014 constant CT32B1MCR $40018018 constant CT32B1MR0 $4001801C constant CT32B1MR1 $40018020 constant CT32B1MR2 $40018024 constant CT32B1MR3 $4001803C constant CT32B1EMR $40018074 constant CT32B1PWMC \ enable both 32bits timer counter 3 9 lshift CLKCTRL bis! \ select compare match 3 PIO1_1 @ OR PIO1_1 ! 3 PIO1_2 @ OR PIO1_2 ! \ stop timer control 2 CT32B1TCR ! \ clear timer counter 0 CT32B1TC ! \ set prescaler 119 CT32B1PR ! \ clear prescaler counter 0 CT32B1PC ! \ set match registers 50 CT32B1MR0 ! 50 CT32B1MR1 ! 50 CT32B1MR2 ! \ set match register 3 100 CT32B1MR3 ! \ set clear condition 1 10 lshift CT32B1MCR ! \ if TC = MR3 , send 'L' to pin (H -> L) 5 4 lshift CT32B1EMR ! \ enable PWM with MAT0 and MAT1 3 CT32B1PWMC ! \ start 1 CT32B1TCR !  PWM波形を出力するようにしたので  DUTY比を変更したいときには、2つ  のレジスタに与える値を変えること  で対応します。 10 CT32MR0 ! 80 CT32MR1 !  PWM波形出力をやめるときには、タイマーへの  クロック供給を停止で対応。 2 CT32B1TCR !  DCモータの回転数を変える場合は、2つのレジスタに  与えるDUTY比率を一度に変えるように、ワードを定義  して処理すればよいでしょう。 : SET.DUTY 100 swap - CT32B1MR1 ! 100 swap - CT32B1MR0 ! ;  左、右の順でDUTY比を並べて対応。 10 45 SET.DUTY  また、PWM機能を使うか、停止するのかを指定  できるワードを定義して使った方が楽でしょう。 : PWM.START 1 CT32B1TCR ! ; : PWM.STOP 2 CT32B1TCR ! ;  ポート1に、次のHブリッジICを接続して、制御する  ことを考えます。  1チャネルにつき、2ピンの制御が必要。P1.1からP1.4を  利用することを考えてみます。  ポート1のほぼ全ピンを利用して、センサーデータ入力と  PWM波形出力ができるようにワードを定義すると、以下。 0 variable SENSOR : INIT.P1 $40044078 @ 1 or $40044078 ! \ P1.0 GPIO $4004407C @ 3 or $4004407C ! \ P1.1 MAT0 output $40044080 @ 1 or $40044080 ! \ P1.2 GPIO $40044090 @ 3 or $40044090 ! \ P1.3 MAT2 output $015 $50018000 ! \ P1.5 , P1.8 and P1.9 input , P1.0 output ; : GET.SEN $50013FFC @ dup 5 rshift 1 and swap 7 rshift 6 and or SENSOR ! ; : INIT.PWM 3 9 lshift $40048080 \ enable both 32bits timer counter 2 $40018004 ! \ stop timer 0 $40018008 ! \ clear timer counter 1119 $4001800C ! \ set prescaler 5000 $40018018 ! \ set match register 0 5000 $40018020 ! \ set match register 2 10000 $40018024 ! \ set match register 3 5 4 lshift $4001803C ! \ set clear condition 5 $40018074 ! \ enable PWM with MAT0 and MAT2 ; : SET.DUTY 2 $40018004 ! \ stop timer 100 * SWAP 100 * $40018018 ! \ set right duty ratio $40018020 ! \ set left duty ratio 1 $40018004 ! \ start timer ;  ポート1の0ビットから3ビットは、デフォルトでは機能指定が  されていないので、GPIOでの利用とコンペアマッチ出力で使うと  宣言しなければなりません。  ワードを定義したなら、次のようにタイプして利用。 \ initialize I/O INIT.P1 \ initialize timer / counter INIT.PWM \ control motor 10 80 SET.DUTY  ユーザー定義のワードでも、組込まれているワードと  同等に使えるのがForthの利点。  内部モジュールの機能設定の場合、データシートを  読み込んで、動作を理解しないと、思わぬ落とし穴  にはまるので、要注意。

  • 目次

    inserted by FC2 system