ほとんどのマイコンではタイマの横にコンペア/キャプチャ/PWMといった入出力チャネルがぶら下がっていてそれらを駆使することで入力イベントの時間間隔とか、パルス幅、周期といったことを測定できます。勿論PICマイコンも同様なことを出来るのですが、専用のFSMモジュールが用意されてます。専用モジュールなので設定もお楽。
※『PIC三昧』PIC関係の記事総目次はこちら
前回はデジタル出力信号を変調できるDSMでした。今回のSMTはデジタル入力信号を測定できるモジュールです。反対方向なのね。
SMT(Signal Measurement Timer)
SMTモジュールは「入力キャプチャ」関係の仕事を幅広くこなすことができるモジュールです。PIC16F18855の場合2ユニット搭載。汎用のタイマにぶら下がったインプットキャプチャ機能よりも良いところとして、そのビット幅があります。24ビットね。多くのマイコンのタイマが16ビットでありインプットキャプチャもそれに合わせた16ビットが多いじゃないかと思います。このレゾリューションの細かさは何気に強力かも。
また細かく11種の動作モードに対応しているので、やりたい事を決めてしまえば設定は明快じゃないかと思います(個人の感想っす。)
端子に加わる外部信号だけでなく、内蔵の各種ペリフェラルの出力信号を入力としてとることもできるので、処理の幅も広がるというもの。専用化のお陰かもしれませぬ。
MCC Classicを使ってコンフィギュレーション
いつものとおりMicroChip社MPLAB X IDEの自動コンフィギュレーションツールMCCのClassic版を使ってソースコードを自動生成します。まずは、SMTの「リソース」をProjectに取り込みます。以下のDevice Resources画面から2個あるSMTのうち、SMT1の左横の+ボタンをクリックしてProject Resourcesに加えます。
上記で、SMT1を加えた直後に、ピンマネージャを開いてみると、SMT1への入力端子は、PortB、PortCから幅広く選べるようになっているのですが、デフォはPC0とPC1になってました。ムムム。
実は、今回SMTで測定した結果(数値)を標準出力へのPrintfで表示してお茶を濁そうなどと不埒なことを考えておったのです。たまたまなのですが、実験に使っている開発ボードのUSB-UARTが以下に接続されてました。
-
- TX PC0
- RX PC1
もろ被りね。USB-UARTの接続はボード上の配線で変更できないので、PC0とPC1はEUSARTに割り当て、SMT1の入力信号をPC2とPC3に移しました。こんな感じ。
SMTのWin信号端子も一応アサインしてますが、今回のソフトでは Period and Duty Cycle aquisitionモードを使用なので使用するのはSMT1SIGの方だけです。
ここで一つ思い出しました。以下の別シリーズ記事で経験した件です。
鳥なき里のマイコン屋(171) MCC MelodyとMCC Classicどっち?
手元のMPLAB X IDE(v6.10)のMCC Classicがstdioのサポートのために自動生成してくれる char getch(void) が、CコンパイラであるXC8がもともと持っている int getch(void)の型と矛盾しているいためにコンパイルエラーになることです。そこで上記記事と同様に、char getch(void)の方をコメントアウトしてます。もっと良い方法が無いものか? なお、MCCでもMelody版が自動生成してくれるソースでは上記の問題がでないです。
念のため、USBシリアルにPrintfするためのEUSARTの設定が以下に。
また、肝心のSMT1の設定が以下に。SMTには以下のように多くの動作モードがありますが、その中でPeriod and Duty Cycle aquisitionを選択します。
以下がSMT1設定後の様子です。
SMT1の設定で気になるのは、Clock Selectのところの HFINTOSC 16MHzという表示です。こう設定するとHFINTOSCは16MHz設定になっている、と見えてしまうのですが、調べたら勝手にそうしているという事実は無さそうでした。最高16MHzまで対応可能、という文脈の16MHzではないかと思えます。知らんけど。
クロック設定画面では以下のようになっています。HFINTOSCを4分周して1MHzのFOSC(システムクロック)を作ってます。
上記のクロック設定については、以下の回で外部に信号出力しているので、多分、間違いないっす。
PIC三昧(1) PIC16F18855のCLKOUTとビットバンギングで周波数確認
ということで、クロック速度は以下のようになっている筈。
HFINTOSC 4MHz
Generateしてソース書き込み
今回は入力されるパルス信号の「幅」と「周期」の両方を測定し、結果をPrintfしようとしているので、いつもよりmainルーチンが長めです(勿論、吉例Lチカもしぶとく残ってます。)といってもこんだけ。
void main(void) { SYSTEM_Initialize(); INTERRUPT_GlobalInterruptEnable(); INTERRUPT_PeripheralInterruptEnable(); SMT1_DataAcquisitionEnable(); printf("SMT Period and Duty Cycle mode test.\n"); while (1) { RA0 = 1; uint32_t pulseWidth = SMT1_GetCapturedPulseWidth(); uint32_t signalPeriod = SMT1_GetCapturedPeriod(); printf("W: %lu P: %lu\n", pulseWidth, signalPeriod); __delay_ms(500); RA0 = 0; __delay_ms(500); } }
Buildして実行
ビルドした結果をPIC16F18855へ書き込み、外部から信号を与えて測定結果を観察したものが以下に。
まずは1kHz、デューティ50%の信号。測定クロック=4MHzなのでほぼほぼ良い結果でないの。
つづいて100kHz、デューティ50%。
ええい、1MHz、デューティ50%でどうよ。
予想どおりの結果じゃね。パルス幅も周期も測り放題?調子こいてんじゃね~