HOME > 技術談話 > PIC microcontroller > シリアル通信

はじめに ライブラリの基本機能 ライブラリの構成 通信速度 フロー制御 関数と定義 汎用ライブラリ 

評価実験回路 上位装置との接続 

サンプルプログラム:割り込み無し(ポーリング) 
サンプルプログラム:割り込み有り、フロー制御無し 
サンプルプログラム:割り込み有り、フロー制御有り 

おしまい 


■はじめに

 既にレガシーインタフェースとなったシリアル通信ですが、ハードウェア、ソフトウェア共に構造がシンプルであり、利用方法が単純であることから現在でも多くのマイコンで機能が実装されています。PICマイコンでも中規模以上(小ピン型を除く)であれば 1ch、もしくは 2ch のシリアル通信機能をサポートしています。

 通信機能を利用するためには、通信ドライバ(ハードウェアデバイス)とソフトウェア機能の付加が必要となりますが、今時のメジャー通信方式である USB や TCP/IP に比べれば非常に低コストで実装することができます。

 装置にシリアル通信機能が実装されていれば外部に専用デバイスを設けることで USB や TCP/IP の利用も可能となるのでシリアル通信に関しては
最後の砦的に利用方法をマスターしておくのも良いと思います。また、開発環境(コンパイラ)によってはソフトウェアライブラリ、もしくはサンプルプログラムが提供される場合もあるので、開発コストを抑えることができます。 

 むむむ。本項を作る意味が…。無い?

 別件でシリアルインタフェースを利用するのですが、どうしても
フロー制御が必要になりました。この制御は開発環境で提供されるプログラム等では対応できません。そこで、カスタマイズ可能な必要最低限の汎用ライブラリを独自に作り込むことにしました。

 数百円のマイコンが高額な上位マシンに対してシステムレベルで「待った」できるのは、見ていて面白いです。

 なお、シリアル通信の世界にも独自の世界観があります。本項ではライブラリを中心に記述を行いますので、細かい話に関しては別項でまとめます → << 準備中 >>


 相変わらず進捗は遅いかも…。そのような場合は「つぶやき」をチェックしてみてください。  
 途中経過やホームページの更新タイミングで何かしら独り言をつぶやいてます。

■ライブラリの基本機能

 作成する汎用ライブラリの諸元を以下に示します。
項目 説明 備考
通信方式 調歩同期式通信(非同期通信) マイコンにUART機能が実装されている事
通信速度 自動計算対応、標準速度定数有り 源発振に応じて自動計算可能、BRG16対応
割り込み 指定有り(ポーリング方式も利用可能) 送受信共に割り込みを使うか否かの指定のみ
フロー制御 ハードウェアフロー制御を選択可能 利用時は割り込み制御、受信バッファ必須
バッファ 任意サイズ指定可能 管理変数型の最適化実施
エラー検出 フレーミングエラー、バッファフル オーバーランエラーも検出可能
データ長 8ビット、パリティ無し、ストップビット1ビット パリティ検出機能は未実装
ブロック制御 無し 方式を特定できないので未実装

 PICマイコンは 2byte 変数の取り扱いが苦手なので、指定されるバッファサイズに応じて管理情報の変数型を自動的に切り替える様に細工します。バッファサイズが 256byte 未満では処理速度、プログラム容量で有利です。

 パリティに関してはエラーの発生確率、エラーの誘発リスクを考慮し、検出機能は未実装です。

 以下の機能はプログラム生成時に有効無効が決定され、プログラム運用時に変更することはできません。
 ・バッファサイズ、フロー制御サイズ
 ・フロー制御有無
 ・源発振周波数

 送受信バッファの構造はリング型としました。可変量を扱う場合に便利ですが、バッファ末端からの先頭への回り込み制御が必要です。この制御がオーバーヘッド要因になりますが、ポーリング方式と上位関数による独自割り込み定義を行う事で高度なバッファ管理を行う事も可能です。


 後付けで恐縮ですが、フロー制御もバッファも無い、シンプルな送受信手法も提供します。

■ライブラリの構成

(1)位置づけ

 これまでに公開してきたライブラリと同様、シリアル通信ライブラリもミドルウェア的な位置付けです。
 フロー制御信号の基本制御(定義)はデバイスドライバが提供しますが、シリアル通信ライブラリが信号線を直接制御しても問題有りません。

 総ての制御をシリアル通信ライブラリで行いたいのですが、マイコン割り込み制御の一部はアプリケーションが補う必要があります。全体割り込みの許可と周辺割り込みの許可、そして割り込み導入部がコレに当たります。

 フロー制御、割り込みを利用しない構成であるならば、アプリケーションによる補助的な作業は不要です。

 シリアル通信ライブラリとデバイスドライバの接点はフロー制御信号と源発振定数の定義ですが、マイコンデバイスの入出力ポートの初期設定についてはデバイスドライバで管理します(TX/RX端子を入力モードにする件)。

(2)ファイル構成

 これまでに公開してきたライブラリと同様、シリアル通信ライブラリも3つのファイルで構成されます。
 原則としてプログラム(DrvCom.c)、公開情報(DrvCom.h)を修正する必要は無く、定義情報(DrvCom.u)を修正するだけで利用できます。
 アプリケーションを作成する場合は公開情報(DrvCom.h)をインクルードすればOKです。

ファイル名 修正 内容
DrvCom.c 不要 プログラム本体(初期設定、送受信ポーリング、バッファ管理、フロー制御等)
DrvCom.h 不要 関数のプロトタイプ宣言、定数宣言
DrvCom.u 必要 バッファサイズ、信号制御手法

 ライブラリと言いながら、ファイル名の接頭語が「ドライバ(Drv)」。このあたりは慣例と言うことで(汗

(3)ファイル関連図

 プログラムと公開情報、定義情報の関連を後述のサンプルプログラムを例として以下に示します。

 色塗りのボックスがコンパイル対象です。上図では main.c, DrvCom.c, device.c の3ファイルが該当します。
 矢印は情報の参照方向を示します。矢印側に include が記述されるイメージです。

 _AtrDef.h, _AtrMpu.h はデータ型や定数が記述された標準シンボルになります。 → 標準シンボルの解説 

 シリアル通信ライブラリでは標準シンボルを参照するのがプログラム(DrvCom.c)ではなく定義情報(DrvCom.u)になっています。これはできる限りライブラリ本体の修正不要を目標としたため、この形になりました。

 更に、よくよく見ると公開情報、定義情報が複数参照されている様に見えます。例えば main.c では都合2回の標準シンボルの参照を行います。ですが大丈夫。二重定義にならない様にガードをかけています

■通信速度

(1)誤差の許容範囲

 調歩同期式通信ではスタートビットをトリガとし、続くデータビットのサンプリングを行い、ストップビットで終了します。サンプリング周期は通信速度に依存し、この周期が送信側、受信側で一致していないと正しくデータを伝えることができません。そうそう、スタートビット、各データビット、そしてストップビットの時間幅は総て同一です。コレ大事。

 経験上、通信速度の誤差は 3% 以下であれば問題無く通信できますが、これは送信側、受信側を組とした相対誤差です。送信側が +3%、受信側が -3% の誤差がある場合、都合 6% の誤差になり正しくデータを伝えることが困難になるので注意が必要です(条件が良ければ 7% の誤差でも通信できる場合がある)。

 今回公開するシリアル通信ライブラリでは通信速度設定に必要なボーレートレジスタへの設定値を自動計算できる様にしています(実体はマクロ命令)。レジスタ設定用に整数値を算出するのですが、誤差が生じても、より少ない誤差を選択する様に演算を行っています。

(2)設定の種類

 通信速度の設定は BaudRateGenerator(BRG) にて行い、その通信速度計算式は下表に依ります。

BRG16 BRGH SPBRG/SPBRGH 通信速度計算式 備考
0 0   8bit mode, SPBRG  Fosc / (64 * (n + 1))  低速通信
0 1   8bit mode, SPBRG  Fosc / (16 * (n + 1))   8bit
1 0  16bit mode, SPBRG & SPBRGH  16bit
1 1  16bit mode, SPBRG & SPBRGH  Fosc / ( 4 * (n + 1))  高速通信

 BRG16はPIC18系のPICマイコンの一部でサポートされて、16bitレジスタでの制御有無を指定します。

 通信速度の基準は源発振の分周により行われます。そのため、目標とする通信速度が綺麗に算出できない場合が多々あります。よく使われる通信速度に 9600bps や 19200bps がありますが、この通信速度を誤差 0% で実現する場合、源発振の選択は 18.432MHz、14.7456MHz、12.288MHz といった半端(?)な源発振が必要になります。 簡単に計算ができるように表計算データを添付(次セッションで記述)しましたので色々な値を入れて実験してみて下さい。

 誤差 0% の通信速度を得るために半端な数値の源発振を利用するのも良いのですが、今度はタイマーの管理で端数が生じます。例えば 1ms、10ms の周期を得ようとした場合に端数が生じます。

 源発振の選択は…。

 何を重要視するかです。少なくとも調歩同期式通信では誤差が存在する状態でも通信は可能です。また、源発振と動作温度の関係で少なからず誤差が生じます。水晶発振子と使用した場合と内蔵クロックを利用した場合でも異なります。要は、使用目的と環境を考慮した上で源発振の値とデバイスの種類を選択することが大切です。経験上、通信速度が速ければ速いほど、源発振の精度はシビアです。

(3)誤差の確認

 自動計算とはいえ、実現不可能な通信速度を指定した場合は…とんでもない値を導き出します。例えば、
  ・源発振が低速で通信速度が高速の場合。
  ・源発振が高速で通信速度が低速な場合。
  ・源発振で綺麗に分周できない通信速度の場合。
が該当します。

 シリアル通信ライブラリを利用することで通信速度の計算を行わなくても済みますが、実現できるか否かの判断はマイコンの仕様と源発振の値を元に把握しておくことが必要です。コレ重要。

 結局、電卓片手に計算が必要… orz

 大丈夫です。表計算で簡単に求めることができます

  pic_uart_speed.zip … Excel2007を利用しました。保存してからアプリケーションを起動して下さい。

 源発振と通信速度を与えるだけで設定値、誤差が求められるのは便利です。

 利用したい通信速度が求められない場合は源発振を変更するか、上位のPICマイコンを選択します。
 それから忘れがちになりますが
源発振が温度により誤差が変動することを頭に入れておいて下さい。

 通信速度の誤差が許容範囲内であれば、大抵の場合…問題無く通信することができますが、誤差がある状態での運用についてはシステム作成者の最終判断が必要です。

■フロー制御

(1)はじめに

 フロー制御とは、受信バッファ残量が少なくなった時、相手装置に対してデータ送信の一時停止を要求し、受信バッファのオーバーフローを抑止します。処理が進んで受信バッファ残量に余裕ができた場合は相手装置に対してデータ送信の再開を要求します。

 フロー制御は通信に関わる処理の最下層に位置し、強力な権限を持ちます。安価なPICマイコンと最高速のパソコンを接続した場合でもPICマイコン側が一時停止を要求したならばパソコン側は直ちに送信を停止しなければなりません。但し、お互いの装置でルールを守らない場合は受信バッファのオーバーフローが発生するので注意して下さい。

 フロー制御には大きく分けて以下の様な方式があります。

制御方式 要求と解除 ハードウェア 備考
信号線 信号線の論理制御 信号線を追加 ハードウェアによる割り付けが必要
コード X-ON/X-OFFコード 通信線で兼用 バイナリデータの扱いが困難

 コード制御の場合、ハードウェア回路の追加は不要ですが、フロー制御で用いる X-ON/X-OFF と呼ばれる特別なコードが通信データに利用できません(0x11/0x13)。普段利用しているデータが ASCII データであれば問題有りませんが、ソフトウェアの負荷が高くなる場合が多々あるので今回は見送りました。

 フロー制御は、受信時と送信時の双方をサポートするのが一般的ですが、特別な仕様により一方のフロー制御しかサポートしない場合もあります。今回提供するシリアル通信ライブラリは双方をサポートする制御を行いますが、定義の仕方で一方の制御しか行わない様にすることもできます。

 フロー制御は通信速度と同様、簡単ですが奥が深いです。本件も含め別項にてまとめたいと思います。

(2)フロー制御イメージ

 受信時におけるフロー制御の例を以下に示します。

 受信バッファは空状態から開始します。

 データの受信でバッファに格納を行いつつ取り出しを繰り返すのであればバッファへの蓄積はありません。ですが、取り出しが遅れると蓄積が始まります。

 受信バッファのサイズが必要十二分であればフロー制御は不要ですが、時としてバッファサイズ以上のデータを取り扱う場合はフロー制御で送信を一時停止しないと受信バッファオーバーフローが発生します。

 上図を例に取りますが、フロー制御は受信バッファ空き容量(使用量から逆算も可)を基準に行います。
 
上図Bは受信バッファ空き容量が少なくなり送信側に一時停止を要求するポイントです。
 
上図Cは受信バッファの取り出しにより空き容量が回復したので送信側に送信再開を要求するポイントです。

 パラメータBとCは以下の関係を持たなければなりません(いわゆるヒステリシス)。
  ・C = B + n ただし n > 0 、 B > 0  … 一時停止要求に対して再開要求は余裕を持つ必要がある

 差分 n は 1 でも良いのですが、実運用上は16、32、時には 256 等、余裕を持った値を指定することが多いです。
 差分 n=1 の場合は信号線の変化が激しくなるのお薦めできません。

 更に B > 0 は大切です。
上図Aを見ると明らかなのですが、送信側に一時停止要求を行っても、送信側が送信を直ちに止められない場合があるからです。これにはいくつかの要因があり、
 ・受信側のシリアル通信機能(ハードウェア)が複数の受信データを保持できる場合。
 ・送信側のシリアル通信機能(ハードウェア)が複数の送信データを保持できる場合。
 ・送信側の処理がブロック(複数バイト一括)転送行い、かつ、ブロック転送前にしか信号線を確認しない場合。
が挙げられます。

 大抵の場合 B >= 8 あれば問題回避できますが、ハードウェア仕様、転送仕様の確認が必要です。

 2010.01.08 追記

 申し訳ありません。余裕代を気分的に増やしました(ベストではない)。
 たまに相手側が複数バイトのFIFOを装備している時もあるんですよね。その場合は B >= 16 位。何分にも実験しないとわからない場合もあるので「プログラムの罠」を試してみることを勧めます。受信バッファオーバーフローで記録やLED表示をするイメージです。その時オシロスコープがあると上図Aの動作がビジュアルに見ることができます。 

(3)補足

 今回提供するシリアル通信ライブラリでは、バッファサイズやBusyOn/BusyOff量をカスタマイズすることができます。もちろんフロー制御を無効にすることもできます。組み合わせは多々ありますが、目的にあった組み合わせを指定することでシリアル通信を容易に実現することができます。

 フロー制御でやっかいなことが2つ。

 前述した件ですが「送信側がブロック転送の前にしか信号線を確認しない場合」です。送信側は 1byte 単位の処理が無くなるので簡単な構造になりますが、問題は受信側が処理できるか(受信バッファに余裕があるか)?です。
 前述の B点 の量に余裕を持てば対策はできますが、このあたりは送信側の仕様を調査する必要があります。場合によっては 256byte 一括転送してくるシステムもあるので注意して下さい(某UNIXシステム等)。

 もう1つ。

 受信側の BusyOn 状態を送信側は監視しているわけですが、気長に待ってくれるとは限りません。
 専用の上位アプリケーションを作成するのであれば要求状態に応じてタイムアウト監視を伸ばす等で対応できますが、既存システムに接続する場合はタイムアウトが発生してしまう可能性を否定できません。

 今回のシリアル通信ライブラリでは対策を施しませんが、BusyOn 状態でも定期的(数100ms単位)に BusyOff をすることで対策できる可能性があります。但し、前述したブロック転送が組み合わされた場合は危険です。タイムアウトしないように回避したつもりが、そのタイミングでブロック転送を行う。そうなると受信バッファがいくらあっても足りません。

 以上2件、懸念材料を挙げましたが、最終的には通信仕様次第です。既存システムに接続する場合でも、その仕様が明らかであれば、その仕様に準じてバッファを確保します。PICマイコンの場合はRAM容量が厳しいですが(汗

 要は「何でもかんでもできる」というのは避けた方が無難です。組み合わせるシステムにとって必要最低限の機能を実装することが成功への近道です。


 作成するPICマイコン側のプログラムが上位システムとして位置付けられるならば、あまり気にすることはありませんが、使われる側の下位システムの都合も考えてプログラムを作成したいですね。

■関数と定義

(1)関数一覧

 各関数のパラメータと機能詳細については…。量が多すぎるので割愛します(部分的に後述)。
 プログラムに日本語コメントを入れてあるので、そちらを参考にして頂けると幸いです。 

グループ 関数名 処理内容 A B C
設定 DrvComInit 初期設定
DrvComSetSpeed マニュアル通信速度設定
DrvComSetCfg 通信環境設定(通信速度の指定)
DrvComModeAct 通信開始(割り込み有無の指定)
DrvComModeStp 通信停止
ポーリング DrvComChkC 受信確認
DrvComGetC バイトデータ受信(受信確認待機を含む)
DrvComPutC バイトデータ送信
DrvComIsTxEnd 送信完了確認
ステータス DrvComGetSts 受信ステータス確認
受信バッファ DrvComGetData 受信バッファからデータ取得
DrvComClrRxBuf 受信バッファクリア
DrvComGetRxCnt 受信バッファ格納済み容量の取得
送信バッファ DrvComGetTxCnt 送信バッファ格納済み容量の取得
DrvComGetTxGap 送信バッファ空き容量の取得
DrvComPutData 送信バッファへデータの格納と送信起動
割り込み DrvComRxIpt 受信割り込みハンドラ
DrvComTxIpt 送信割り込みハンドラ
ミニサーバー DrvComTxSvr 送信サーバー(送信再開)
マクロ mComCalcRate 通信速度に応じたレジスタ値の算出

 利用するシチュエーション別に利用の機会が多い関数をマーク(●:頻度大、○:任意)してみました。
 ・
Type A … 割り込み未使用、ポーリング運用
 ・
Type B … 割り込み使用、バッファ運用、フロー制御無し
 ・
Type C … 割り込み使用、バッファ運用、フロー制御有り
 実運用では利用しない関数もあると思いますが、そのあたりは・・・ご自由に。。

 「割り込み未使用」と「割り込み使用」の双方の運用を同一システム内で切り替えるこができます。同時利用はできませんが、保守用途で利用すると便利かもしれません。

 
シリアル通信ライブラリでは以下の処理、操作は含まれません。上位関数にて処理することが必要です。
 ・端子の初期設定(TX/RX端子は入力設定であることが必要です)
 ・グローバルな割り込み許可
 ・周辺割り込み許可
 ・割り込み優先度設定
 ・割り込み導入部(いわゆる interrupt 関数)

(2)定数

 通信速度は 2400bps〜230400bps まで、パソコン等で比較的利用されることの多い通信速度8種に対応します。それ以外にもマニュアル通信速度指定用に「COM_SPEED_MANUAL」という定数を利用できます。これらのシンボルの詳細は公開情報(DrvCom.h)を参照願います。

 通信速度を自動算出するために源発振キーワード「_XTAL_FREQ」の事前定義が必須です。このキーワードを参照してレジスタ設定値を自動計算しています。自動計算故、最終的に利用可能な通信速度であるか否かはボーレートレジスタ幅と誤差に依ります。詳しくは前述の「通信速度」の項を参照願います。

 受信ステータス構造体により異常内容の詳細を取得することもできますが、上位関数は個別にエラー確認するよりもエラーがあったのか無かったのか、すなわち 0x00 か否かの判断でも実運用上は問題有りません。

(3)ユーザカスタマイズ

 カスタマイズ可能な「あまりにも基本情報」に関してはプログラムで指定するのではなく、コンパイル時に定数やデータ型を固定することでプログラム容量の削減と処理速度の改善を図ります。

 ユーザカスタマイズは定義情報(DrvCom.u)を利用します。現時点で定義可能なキーワードは以下の通りです。

機能 シンボル 指定 備考
通信速度レジスタ COM_SPEED_REG16 0/1 ifdef レジスタ幅切り替え用、デバイス依存有り
受信バッファサイズ COM_SIZE_RXBUF 総容量 未使用時は 0
送信バッファサイズ COM_SIZE_TXBUF 総容量 未使用時は 0
容量警告発生条件 COM_FLOW_BUSY_ON バッファ残量 未使用時は 0、警告値< 解除値
容量警告解除条件 COM_FLOW_BUSY_OFF バッファ残量 未使用時は 0、解除値≦受信バッファ
フロー制御許可 COM_FLOW_ENABLE 0/1 ifdef 許可時は容量警告、バッファ指定必要
対装置ビジー判断 mComFlowPcIsBusy 命令、関数 真偽判定、未使用時は空欄(再設定有り)
対装置レディー判断 mComFlowPcIsReady 命令、関数 真偽判定、未使用時は空欄(再設定有り)
自装置ビジー出力 mComFlowMeSetBusy 命令、関数 未使用時は空欄、回路に依存
自装置レディー出力 mComFlowMeSetReady 命令、関数 未使用時は空欄、回路に依存

 通信速度レジスタはPICデバイスの種類により利用可否があります。利用できないPICマイコンを選択した場合はコンパイルエラーになるのでご用心。16bit幅の通信速度レジスタでは利用可能な通信速度の範囲が大きくなります。

 バッファサイズに応じて処理内で使用される管理情報のデータ型が最適化されます。送受信双方のバッファサイズが 255 以下の場合は 1byte 変数を利用するので、処理速度、プログラム容量の面で有利です。

 バッファサイズを大きくしすぎると…。PICデバイスの容量を超えて指定することはできません。割り当て不可能な旨をコンパイルエラーで検出することができるので調整してみて下さい。

 バッファサイズ、容量警告、信号制御の組み合わせについては下表を目安に指定します。

機能 割り込み未使用 割り込み使用
フロー制御無し フロー制御有り
受信バッファサイズ 0 必須 必須
送信バッファサイズ 0 必須 必須
容量警告発生条件 0 0 必須
容量警告解除条件 0 0 必須
フロー制御許可 0 0 1
対装置ビジー判断 任意、空欄可 任意、空欄可 記述
対装置レディー判断 任意、空欄可 任意、空欄可 記述
自装置ビジー出力 任意、空欄可 任意、空欄可 記述
自装置レディー出力 任意、空欄可 任意、空欄可 記述

  特殊なケースとして「割り込み未使用」と「割り込み使用」の双方の運用を同一システム内で切り替える件について前述しました。「割り込み未使用」の場合はポーリング系の関数を利用することになると思いますが、その場合のフロー制御については上位関数でフォローする必要があります。これはハードウェア回路が存在する場合に限ります。

 フロー制御で一方通行だけの場合、例えば信号は入力するけど出力しない場合、あるいはその逆のケース。ハードウェア回路の都合、処理性能の都合で導入する場合が時々あります。その場合は以下の様に対処します。
 ・信号入力がない場合 … ビジー判断は偽条件(FALSEを記述)、レディー判断は真条件(TRUEを記述)
 ・信号出力がない場合 … 記述は空欄

(4)受信ステータス

 受信ステータスの確認で受信エラーの検出を判断しますが、受信データ単位での情報ではなく、経験した情報です。この情報は読み出しを行うか、受信バッファをクリアすることで 0x00 にクリアされます。このあたりは主義でしょうか?使い方としては読み出した値が 0x00 以外の場合は何らかの受信エラーが検出されていると判断できます。

 初めての機器接続でフレーミングエラーが検出されること(大抵は通信速度の誤り)はあっても、実運用でエラーが検出される確率は少ないです。むしろ、エラーの発生しないシステム、構成が望まれますが、信頼性の確保は最低限必要なので経験した情報で判断しても大抵の場合、問題無いと考えます。

 実運用でエラーが発生するケースとして多いのが、通信ケーブルの外れ、もしくは中継機器に起因する通信断。この場合もまた経験した情報で判断、もしくは通信タイムアウト検出(上位関数で用意)で判断できます。

■汎用ライブラリ

(1)ライブラリ

 毎度おきまりのメッセージで恐縮ですが… 注意事項 

 ライブラリを公開します … TemplateCOM_0101.zip 2011/01/20 Ver01.01

 
HI-TECH C v9.70 で作成されたプログラムを v9.81 以降のコンパイラで再コンパイルする際の注意点
  → 開発環境による修正 2011/03/09

 
このライブラリは v9.81 において無修正で利用できましたが、不都合がある場合は再アップします。

 ・マイコン独自のUART機能を操作するためにPIC16系、PIC18系マイコン専用です。
 ・汎用入出力を利用しての疑似通信動作機能はありません。
 ・PIC16系、PIC18系で動作するはずですが、お使いのPICマイコンのデータシートを確認の上、利用して下さい。

 開発環境は、MPLAB IDE V8.40 と HI-TECH C V9.70 を利用しています。
 動作確認済みのデバイスは PIC16F886 ですが、このデバイスと同等の構成であれば利用できるはずです。

 ダウンロードした圧縮ファイルを解凍すると以下の3ファイルが展開されます。

ファイル名 内容 依存度
DrvCom.c プログラム本体 マイコン依存
DrvCom.h 関数のプロトタイプ宣言、定数宣言 マイコン依存
DrvCom.u バッファサイズ、信号制御手法 マイコン依存

 今回のライブラリは 標準シンボル と組み合わせると移植がスムーズです。併せて御確認下さい。

(2)改版履歴

 昨年末の時点でデバッグとサンプルプログラムでの動作確認済みですが、現在再評価を行っています。
 評価の過程で不都合が生じた場合は改版を行いますがご容赦願います。

 動作確認済みデバイスが増えた場合、改版された場合は情報を追加します。
 冒頭に紹介した twitter でもお伝えします。 2011/01/20 現在

版数 日付 変更内容
01.00 2011/01/13 ・公開
01.01 2011/01/20 ・バイトデータ受信(DrvComGetC)にウオッチドッグタイマのリフレッシュを追加
 … ウォッチドッグタイマを利用し、受信確認(DrvComChkC)を使わない人向け

■評価実験回路

(1)回路図例

 毎度おきまりのメッセージで恐縮ですが… 注意事項 

 サンプルプログラムで利用する実験回路を以下に載せます。マイコンは PIC16F886 を使用しました。
 PIC16F886 は端子が多いだけでなく PICkit2 を接続して書き込みと Debug 機能を利用できます。
 源発振は内蔵クロック(4MHz)を利用しているので周辺部品は少ないです。

 ポートBは全ビット共に内蔵プルアップを有効とした入力設定です。他のポートで未使用端子は出力設定です。
 MCLR端子はMCLR機能を選択しています。内蔵プルアップが自動で有効になるのでオープンで略しています。
 
TX/RX端子、UART機能を利用する場合は入力設定が必要です。

 続いてドライバ部です。パソコンとの接続を行うためにシリアル通信ドライバ(専用デバイス)を利用しました。

 通信ドライバには SIPEX社の SP3232ECP を利用しました。送受信各 2ch のドライバが内蔵されます。
 ドライバは他社同等品でもチャネル数が確保されるのであれば問題有りません。

 回路図的に V+/V- に接続されるコンデンサの先に Vcc/GND 間のコンデンサがありますが…
 絵的には問題無いのですが、表現手法が今一つだったかな(汗

 左上にあるのは LED 出力の回路です。電流値が満足したのでPICマイコンに直結しています。
 LEDを接続する場合は1つのポート、全ポートの消費電流が定格の範囲に収まるようにして下さい。

 LED の実装は任意です。あれば「通信データの状態が見える」位の用途で利用しています。仮に省略するのであれば消費電力の面で有利です。場合によっては PICkit2 からの電源供給だけで評価実験回路が動作します。

 最後にシリアルコネクタ部です。ケーブルの種類によりコネクタが変わるので両方掲載します。

 利用するのはどちらか一方でよいのですが、入出力の割り当てが逆になるので注意して下さい。
 逆に接続してパソコンが故障してもフォローすることはできません。このあたりは自己責任ということで。

(2)ブレッドボード実装例

 今回はブレッドボードを利用して実験しました。実装例を以下に。。

 なんとも「ごちゃごちゃ」しています。
 ブレッドボード上をスッキリさせようとしたのですが、確かに実装は楽なのですが、見た目が美しくないです orz

 何となくイメージは伝わると思うのですが、
 ・右上:通信回路を独立させた汎用治具 … ジャンパ切り替えで 5線式*1ch、3線式*2ch を切り替えます
 ・左下:表示回路を独立させた汎用治具 … Source/Sink の駆動方式を選択できます
となっています。

 ブレッドボード上に総ての回路を実装しても良いのですが、手作りの治具を流用するのも手です。
 LEDは秋月電子通商さんの10バーLEDアレイ(I-00217)を利用しています。

 周辺治具を排除してPICマイコンをクローズアップすると、こんな感じ。

 左に伸びる線は PICkit2 への直結線です。

 青いジャンパ線がブレッドボード16番、PIC16F886 の25番ピンに接続されていますが、これは回路図で言うところの BPS スイッチです。サンプルプログラム起動時に通信速度を決めるためのスイッチとして使用しますが、半固定状態なのでジャンパ線で済ませています。

 PICマイコンをブレッドボード(ターゲットボード)にセットして PICkit2 で書き込む場合、PICマイコンは動作可能な状態にあります。ここで注意点。ホビーユーズの場合はPICマイコンを使い回して様々な装置を作る事が多いと思いますが、
新しいターゲットにPICマイコン実装する際は必ず内容が消去された状態であることが大切です。PICkit2 の書き込みに失敗した場合、消去されなかった過去のプログラムの動作が開始され、せっかく作ったブレッドボードや周辺部品を破壊してしまう恐れがあります。

 できることならば、
使い終わったPICマイコンは、当該システム上で消去してから保管するようにして下さい

 専用の書き込み機を利用してのPICマイコンの書き換えであれば問題は少ないのですけどね。。
 いやぁ、PICkit2 を利用しての再書き込みは、抜き差しが不要なので便利便利。横着してしまいます(汗

■上位装置との接続

(1)上位装置の選択

 シリアル通信の一番簡単な確認方法はパソコンに評価実験装置を接続することです。
 簡単な絵で恐縮ですが、RS232Cケーブルで接続するだけです。

 通信ケーブルは大きく分けて、ストレートケーブルとクロスケーブルがあります。

 コネクタ形状が異なるので間違いは無いと思いますが、評価実験装置側のコネクタ形状と信号割り当てが連動していないと意味がありません。間違えた場合は信号が衝突しますのでご用心。

 クロスケーブルは基本的な配線は同じものの、微妙に端子同士が短絡されている場合があるので注意して下さい。
 メーカーさんの製品カタログページを検索すると内部配線が掲載されているので確認できると思いますが、どちらかというと実験にはストレートケーブルを利用する方が悩まなくて幸せになれます。

 参考までにパソコン側シリアルインタフェースのピン割り付けを以下に載せます(9ピンコネクタ割り付けの例)。

番号 シンボル 方向 備考
1 DCD パソコン < 端末 端末がデータ送受信の準備ができていることを示す。
2 RXD パソコン < 端末 端末が通信データで利用する。パソコンの受信。
3 TXD パソコン > 端末 パソコンが通信データで利用する。パソコンの送信。
4 DTR パソコン > 端末 パソコンが接続されていることを示す。
5 SG パソコン − 端末 信号グラウンド
6 DSR パソコン < 端末 端末が接続されていることを示す。
7 RTS パソコン > 端末 パソコンが受信データの受け入れ許可と禁止を示す。
8 CTS パソコン < 端末 端末が受信データの受け入れ許可と禁止を示す。
9 RI パソコン < 端末 端末が電話がかかってきたことを示す。

 昨今のパソコンにはレガシーインタフェースであるシリアルインタフェースを装備していない場合がありますが、その場合は「USB変換ケーブル」を利用することでパソコンにシリアルインタフェースを増設することができます。
 ・秋月電子通商さんなら M-02746 とか。
 ・個人的にはラトックシステムさんの REX-USB60 系が好きです。

 変換ケーブルは時としてパソコンとの相性問題があるので、近くの人が利用実績のある変換ケーブルを持っていれば、その型番を教えてもらうか、借用するのが安心です。

(2)アプリケーションの選択

 WindowsXP 以前の場合は「ハイパーターミナル」が利用することができます(アクセサリに含まれます)。

 Windows7 以降の場合、あるいは「ハイパーターミナル」を利用したくない場合(?)は別途シリアル通信ソフトを用意しなければなりません。シリアル通信ソフトはフリーウェアとして公開されていることも多いです。

 例えば、有名処のフリーウェア。。Vectorさんからダウンロードできます。
 ・Tera Term Pro

(3)その他

 評価実験装置がどんなに頑張って送信してもパソコン側がビジー状態になることは「まず」ありません。
 パソコン側の性能が飛躍的に向上した現在、シリアル通信程度の負荷ではびくともしません。

 けど、実験はしたいですよね。。

 専用のアプリケーションを自作する方法もありますが、前述の Tera Term Pro を利用します。

 連続受信中にタイトルバー(ウインドウの一番上の帯の箇所)をクリックすると処理が一瞬止まりビジー状態を再現することができます。この時、フロー制御が適切に行われていれば受信データの取りこぼしは発生しません。

 なんとも原始的な手法ですが、お試し下さい(バージョン違いで再現できない場合はご容赦)。
 最悪、通信停止と開始操作でフロー制御を確認することができます。

■サンプルプログラム:割り込み無し(ポーリング)

(1)はじめに

 割り込みを使用しない、いわゆるポーリングによる送受信を行うサンプルプログラムです。

 受信オーバーランの可能性が高くなりますが、以下の条件を満足すれば十分利用することができます。
 ・受信を行わない(送信のみ利用する場合)。
 ・確実に1バイト通信時間内に処理が完了する。
 ・送信側で装置側の処理時間を考慮した手順を実施する(エコーバックにより次のデータを送信するような構成等)。

(2)動作仕様

 ・フロー制御は行わず、割り込み無しで送受信を行う
 ・受信したデータを無加工で送信(エコーバック)する。
 ・通信エラー(フレーミングエラー、受信オーバーランエラー等)を検出した場合は受信データを破棄する。
 ・スイッチ(SW)押下中は受信データの検出を行わない(注意:未受信時でもスイッチは有効)。
 ・通信速度選択スイッチ(BPS)は起動時に読み出す(H:19200bps、L:9600bps)。

(3)サンプルプログラム

 サンプルプログラムを公開します → NonIPT_0100.zip 2011/01/20 
 開発環境は、MPLAB IDE V8.40 と HI-TECH C V9.70 を利用しています。

 
HI-TECH C v9.70 で作成されたプログラムを v9.81 以降のコンパイラで再コンパイルする際の注意点
  → 開発環境による修正 2011/03/09

 ライブラリは定義情報(DrvCom.u)をカスタマイズしているので、原本はこちらを利用して下さい。

(4)概略フローチャート

 メイン処理はそれほど多くありません。どちらかというとPICマイコンの初期設定の方が量が多いです。

(5)動作のポイント

 パソコンのターミナルソフト上でキーを押下すると、そのキーに対応する文字コードが送受信され、画面にはキーに対応する文字が表示されます。

 今回利用した PIC16F886 は受信シフトレジスタの他に2個の FIFO を有します。これはプログラムを作成する上で有利です。2バイト受信しても2バイト分の情報が保持されるので、2バイト通信時間内に処理を行うのであれば受信オーバーランの可能性を回避することができます。

 以下の操作を行う事で FIFO の有効性を確認することができます。

 ・ブレッドボード上のスイッチをオン
 ・パソコンのターミナルソフト上でキーを2個押下
 ・ブレッドボード上のスイッチをオフ

 この操作の場合、画面にはキーに対応する2つの文字が表示されるはずです。これが FIFO の働きです。

 一方、キーを3個押下した場合はどうなるでしょう?

 3個目のキーに対応する通信コードの送信完了で FIFO に転送されますが FIFO に未読のデータが残っているので受信オーバーランエラーになります。サンプルプログラムではエラーを検出すると受信データを破棄するので画面に文字が表示されないはずです(受信オーバーランエラーの場合は FIFO も総て破棄)。

 今回のサンプルプログラムでは1バイトの処理時間が短いので、ターミナルソフトからテキストファイル転送を行っても受信オーバーランの発生無しに折り返す(エコーバック)することができます。なお、テキストファイル転送を行う場合の注意点ですが、ターミナルソフトの仕様によっては LF コード(0x0a)が排除されて送信されない場合があるので「行末に改行を付ける」等の設定が必要です。

 蛇足。。

 ターミナルソフトの仕様に依りますが、 CTRL + 英字キー で 0x00〜0x1f の制御コードを送信できます。
 LED を実装した場合には是非お試し下さい。A から順番に試すと幸せになれるかも(笑

■サンプルプログラム:割り込み有り、フロー制御無し

(1)はじめに

 割り込みを使用した送受信を行うサンプルプログラムです。
フロー制御無しのケースです。
 今回のサンプルプログラムでは割り込みを使用するため、メモリ上に送受信バッファを確保する必要があります。

 メイン処理で重い処理を行っていても割り込みが許可されていれば受信オーバーランエラーを気にせず、通信データを順次保持できるのが強みです。

 今回はフロー制御無しなので受信バッファオーバーフローの可能性がありますが…運用仕様次第です。

(2)動作仕様

 ・フロー制御は行わず、割り込み有りで送受信を行う。
 ・受信したデータを無加工で送信(エコーバック)する。
 ・通信エラー(フレーミングエラー、受信オーバーランエラー等)を検出した場合は受信データを破棄する。
 ・スイッチ(SW)押下中は受信データの検出を行わない(注意:未受信時でもスイッチは有効)。
 ・通信速度選択スイッチ(BPS)は起動時に読み出す(H:19200bps、L:9600bps)。
 ・受信バッファ容量 16byte、送信バッファ容量 16byte をメモリ上に確保

 受信処理が割り込みになりますが、併せて送信処理も割り込みになります。送信処理を割り込みにすることで、比較的効率の良いシステムを構築することができます。

(3)サンプルプログラム

 サンプルプログラムを公開します → IPT-NonFlow_0100.zip 2011/01/20 
 開発環境は、MPLAB IDE V8.40 と HI-TECH C V9.70 を利用しています。

 
HI-TECH C v9.70 で作成されたプログラムを v9.81 以降のコンパイラで再コンパイルする際の注意点
  → 開発環境による修正 2011/03/09

 ライブラリは定義情報(DrvCom.u)をカスタマイズしているので、原本はこちらを利用して下さい。

 前述の割り込み無しサンプルとの大きな相違点は割り込みを使用することですが、その他にメモリ上に送受信バッファを構築していることが特徴的です。今回は送受信とも各16byteの容量を持つバッファを準備しました。

(4)概略フローチャート

 今回はメイン処理だけでなく割り込み処理も利用します。まずはメイン処理。
 送受信共にバッファを介してアクセスしている点がポイントです。

 続いて割り込み処理です。PICマイコンでは複数の割り込み要求を1つの割り込み処理で処理します。
 各割り込みハンドラは無条件実行の様に見えますが、各ハンドラの中で実行すべきか否かを判断しています。

(5)動作のポイント

 パソコンのターミナルソフト上でキーを押下すると、そのキーに対応する文字コードが送受信され、画面にはキーに対応する文字が表示されます。

 回路構成は前述の割り込み無し(ポーリング)の時と全く同じですが、
プログラムの構造を変え、割り込みを利用することでシステムの性能が見かけ上アップします(厳密に見れば有意味な作業量は増えています)。


 割り込み処理は許可された割り込み事象が発生するタイミングで実行され、その動作はメイン処理の動作と非同期です。メイン処理が負荷の高い処理、例えば乗除算等の比較的処理時間を要する処理を行っていたとしても、割り込み事象の発生で割り込み処理が動作します。

 前述の割り込み無し(ポーリング)の時は、メイン処理でスイッチオンを認識するとマイコン内蔵のFIFOからのデータ取得ができなくり、受信オーバーランエラーが発生しやすい環境でした。対して割り込みを利用する方法では、マイコン内蔵のFIFOにデータがセットされる(受信完了)度に割り込み処理が実行され、直ちにFIFOの内容を読み出す作業を行うので受信オーバーランは発生しません(一般論でありゼロでは無い)。

 FIFOから読み出したデータはメモリ上に構築された受信バッファに転送され、あたかもマイコン内蔵のFIFOが拡張されたかの如く動作を行います。


 以下の操作を行い、割り込み処理と受信バッファの有効性を確認してみましょう。

 ・ブレッドボード上のスイッチをオン
 ・パソコンのターミナルソフト上でキーを 16 個押下(わかりやすいように 16 進数で入力するとベター)
 ・ブレッドボード上のスイッチをオフ

 この操作の場合、画面にはキーに対応する 16 の文字が表示されるはずです。前回の割り込み無し(ポーリング)の時は2つが限度でしたが、今回は割り込みと受信バッファの働きで 2 個から 16 個に増加しました。


 では、キーを 17 回操作した場合はどうなるでしょう?

 受信バッファ容量は 16byte(カスタマイズ可能)なので、16 個の情報は保持できますが格納できない 17 個目の情報は破棄されます。これが受信バッファオーバーフローと呼ばれるエラー状態です。今回提供する汎用ライブラリでは受信ステータス確認関数(DrvComGetSts)によりエラーが発生したか否かを検出することができます。

 汎用ライブラリの設計思想に依るのですが、今回提供する汎用ライブラリでは受信バッファに格納できる場合は異常が発生した後でも格納動作を実行します。ですが、異常発生時にどの場所のデータが抜けたか?までは管理していません。異常を経験したことを示すステータスの記録のみです。

 今回のサンプルプログラムでは受信エラーのチェックを省略していますが、実際にシステムを構築する場合は、その扱いについて検討することが大切です。


 割り込みを使うと便利な様ですが、スタックを消費するというデメリットがあります。これはスタック領域の少ないPICマイコンならではの課題です。ハンドラを呼び出す都合上、割り込みを利用することで最低でも 2 level のスタックを消費してしまうことになります。


 以上、受信割り込みを中心に解説しましたが、送信の場合も「ほぼ」同様です。
 送信バッファを設けることで複数バイトの送信作業が簡単に、そして最短で完了することができます。割り込み無し(ポーリング)ではPICマイコン側の送信バッファが空くのを待機しなければなりませんが、割り込み任せなら割り込み処理連動できるので…。放置していても連続送信を行えます。

 ちょっと表現が難しいのですが、送信に割り込みを利用することで、
 ・連続で送信するために、メイン処理で「送信バッファ空」を待たなくても良い。
という点がメリットです。劇的な効果を述べるのは難しいのですが、処理はスッキリするはずです。

(6)おまけ

 受信に関して放置できる時間を考えます。要はメイン処理が忙しくて受信済みデータを取得できないケースです。

 割り込み無し(ポーリング)ではマイコン内蔵の FIFO サイズに影響されます。

 9600bps を仮定すると約 1ms/byte ですから、2 個の FIFO があれば 3byte 相当(シフトレジスタ含む)、すなわち約 3ms
未満で FIFO からデータを取り出せば受信オーバーランエラーを回避することができます。ただし、4byte 目以降のデータが続く場合は注意して下さい。どんどん FIFO から取り出しを行わないと、いつかはエラーになります。

 割り込み有り、フロー制御無しの場合は受信バッファサイズに影響されます。

 同じ通信速度で 16byte の受信バッファがある場合は 17byte相当(シフトレジスタを含む)、すなわち約 17ms
未満で受信バッファからデータを取り出せば受信バッファオーバーフローを回避することができます。但し、続くデータがある場合は注意して下さい。いつかはエラーになるので、空いた時間を見つけて取り出しを行って下さい。


 要は、メイン処理で何かしら集中して処理することがあっても、
割り込みを利用することで受信データを消失しない猶予時間を延長することができます。受信バッファを介すこと自体がオーバーヘッドですが、猶予時間が延びることの方が重要です。

(7)その他

 運用中に「割り込み有り」と「割り込み無し」を切り替える…。通信停止と通信開始を利用すれば可能です。
 たまにあるんです、切り替える様な仕様。ちょっとトリッキーですけど。

 割り込みを利用する場合は送受信バッファの定義が必要ですがサイズ 0 でもコンパイルできてしまいます。
 これはプログラム実行中に利用有無が判明するのでコンパイル時にエラーにすることができないのです。

 設計判断を迷うのですが、割り込みを使用する場合は必ず 1 以上の送受信バッファを定義して下さい。
 なお、容量警告の各値については指定してもしなくても問題有りません。

 後述の「フロー制御有り」の場合は、
 ・送受信バッファサイズの確認
 ・容量警告発生条件、解除条件の確認
が行われます。
 「フロー制御有り」という選択肢は特別な項目で、バッファが必ず存在するという前提で処理が行われます。

■サンプルプログラム:割り込み有り、フロー制御有り

(1)はじめに

 割り込みを使用した送受信を行うサンプルプログラムです。
フロー制御有りのケースです。

 作成するプログラムは前述の「割り込み有り、フロー制御無し」と似ていますが、「送信サーバー」が追加されていることに注目です(今回は有意味です)。送信サーバーは相手装置がビジー状態からレディー状態に切り替わることを監視し、ビジー状態により停止していた送信を再開する働きがあります。

 さて、ここから信号の出所が紛らわしい文章が多くなります。間違いの元ですね(汗
 これまでは単に送信、受信でも済んでいたのですが、フロー制御の場合はどっちがどっち?って事になりそうです。
 そこで前述した「上位装置との接続」の項を元に表現を揃えます。

 ・上位装置 … パソコン等のこと(パソコン、相手装置と表現している場合もありますがご容赦)
 ・端末装置 … 評価実験装置(サンプルプログラムが動作しているブレッドボード)のこと


 百円前後のマイコンを使い、上位装置が何億円の装置であろうとも、フロー制御の取り決めがされているならば、端末装置がビジー状態を通知すれば上位装置は送信を停止しなければなりません(逆もまた真)。

 フロー制御。これはある意味、強力な機能です。

(2)動作仕様

 基本的には「割り込み有り、フロー制御無し」と同じですが、空き容量警告に関する項目が明示されます。

 ・フロー制御を行い、割り込み有りで送受信を行う。
 ・受信したデータを無加工で送信(エコーバック)する。
 ・スイッチ(SW)押下中は受信データの検出を行わない(注意:未受信時でもスイッチは有効)。
 ・通信速度選択スイッチ(BPS)は起動時に読み出す(H:19200bps、L:9600bps)。
 ・受信バッファ容量 16byte、送信バッファ容量 16byte をメモリ上に確保

 ・受信バッファ空き容量警告発生条件 8、警告解除条件 12

 以上の仕様で端末装置が出力するフロー制御を確認できますが、何か物足りません。
 そうです、上位装置が出力するフロー制御を確認できません。

 そこで、パソコン側を困らせた時の反応を確認するために、
 ・受信コードが 0x01 の場合、多量のデータをパソコンに送信する。
を追加します。

 ちなみに、パソコンからの送信データ、0x01 を指定する方法は、
 ・通信コード 0x01 をターミナルソフトで指定する場合は、 CTRL + A (CTRLキーを押下しながらA)
で行います。

(3)サンプルプログラム

 サンプルプログラムを公開します → IPT-Flow_0100.zip 2011/01/20 
 開発環境は、MPLAB IDE V8.40 と HI-TECH C V9.70 を利用しています。

 
HI-TECH C v9.70 で作成されたプログラムを v9.81 以降のコンパイラで再コンパイルする際の注意点
  → 開発環境による修正 2011/03/09

 ライブラリは定義情報(DrvCom.u)をカスタマイズしているので、原本はこちらを利用して下さい。

(4)概略フローチャート

 メイン処理と割り込み処理が必要です。まずはメイン処理。
 前述の「割り込み有り、フロー制御無し」では送信サーバーが配置されていましたが、割り込み側に引っ越しました。
 多量データの送信処理が追加されているところもポイントです。

 続いて割り込み処理です。基本的には前述の「割り込み有り、フロー制御無し」と同等ですが、時間監視を行いながら送信サーバーを動かすところが異なります。

 送信サーバーの設置場所は割り込み処理ではなくメイン処理でも大丈夫です。

 送信サーバーの実行周期については早すぎても空振りが多い(ビジー解除されないケース)ですし、長すぎると転送レート(通信速度ではなく単位時間あたりのバイト量)が下がります。処理の負荷も考慮しなければなりません。

 ベストな値を明言することは難しいのですが、10ms前後で問題無いはずです。

 どうしても転送レートを高めたい場合は、パソコン側が出力するフロー制御信号を評価実験装置側の外部入力に接続し、外部割り込みとして処理する方法もあります(処理の追加が別途必要)。

(5)動作のポイント … 基本動作

 パソコンのターミナルソフト上でキーを押下すると、そのキーに対応する文字コードが送受信され、画面にはキーに対応する文字が表示されます。

 前述の「割り込み有り、フロー制御無し」と根本的に異なるのは「フロー制御有り」であること。

 … まんまですね(汗

 まずは、前回の作業でデータが消失した「キーを 17 回押下」を試してみましょう。
 ・ブレッドボード上のスイッチをオン
 ・パソコンのターミナルソフト上でキーを 17 回押下
 ・ブレッドボード上のスイッチをオフ

 前回の操作では 17 個目の情報が失われましたが、今回はフロー制御が有効なので 17 個目の情報を表示できると思います。なお、フロー制御では空き容量警告発生条件に達した時に装置側がビジー状態になるので、キー押下直後にターミナルソフト上に文字が表示されないと思います。このあたりはターミナルソフトの動作仕様に依存します。

(6)動作のポイント … 上位装置から多量データの送信

 パソコンから多量のデータを送信すれば端末装置側のフロー制御が反応します。

 ターミナルソフトから「テキストファイルの送信」を試します。端末装置は受信したデータを折り返す(エコーバック)ので送信内容と受信内容が一致するはずです。この時、端末装置のスイッチを適度にオン、オフすると端末装置のフロー制御の動きが画面上で見えると思います。

 なお、ターミナルソフトの設定によっては行末の改行コード(0x0a)を削除してしまう場合があるので注意して下さい。設定上は「行末に改行コードを付ける」が必要です。

端末装置上のスイッチをオンした場合
 ch1:パソコンの送信データ信号
 ch2:端末装置のフロー制御信号

 端末装置上のスイッチをオンすると受信バッファからの取り出しを停止します。その状態でパソコンからのデータを受信し続けると端末装置の受信バッファ残量が少なくなり端末装置はビジー状態になります。

 端末装置がビジー状態になるとパソコン側の送信は一時停止しますが、数バイト分のデータは流れてしまいます。この量はパソコン側のシステムに依存します。


端末装置上のスイッチをオフした場合
 ch1:パソコンの送信データ信号
 ch2:端末装置のフロー制御信号

 端末装置上のスイッチをオフすると受信バッファからの取り出しを再開します。すると端末装置の受信バッファ残量が回復してビジー状態を解除します。

 端末装置のビジー状態が解除されるとパソコン側は送信を再開します。この再開時間はパソコン側のシステムに依存します。

 端末装置のビジー状態を確認するとパソコン側の送信は一時停止しますが、ビジー状態成立後に流れるデータ量は不定です。現在送信中の 1byte 送信後、すぐに停止する場合もあれば数百バイト送信してから停止する場合があります。このあたりは上位装置のシステム仕様です。

 旧式の「とある大型汎用マシン」では 128byte 単位で送信を行います。送信開始前に端末装置のビジー状態を確認しますが、送信中はオーバーヘッドになるので端末装置のビジー状態を確認しません。少々ルール違反の感がありますが、そんなシステム仕様もあります。なお 128byte は一例です。実験しないとわからない場合も多々あります。

(7)動作のポイント … 端末装置からの多量データ送信

 これがまた難しい。今時のパソコンは高性能すぎてシリアル通信レベルではビジー状態になりません。
 唯一、通信の開始と停止でビジー状態が変化するので、これを利用します。

 厳密に言うと、ターミナルソフト上で通信の停止と開始を繰り返すと、ターミナルソフトの初期設定の関係で受信データが抜ける場合があるので、その点は考慮して下さい。

 ターミナルソフト上で CTRL + A キーを押下(0x01 の送信)してみましょう。すると装置は自動的にデータの送信を開始します。通信速度により異なりますが数秒間の連続送信を行います。その間にターミナルソフト上で通信の停止と開始を切り替えます。

ターミナルソフトで通信停止操作を行った場合
 ch1:装置の送信データ
 ch2:パソコンのフロー制御信号

 パソコンがビジー状態に切り替わるので以後の送信が停止します。左図では約 1byte 分の送信が行われていますが、これはマイコン側の仕様です。マイコンが有するシフトレジスタと送信レジスタ分のデータを限度として送信を継続するので、今回利用する汎用ライブラリでは最大 2byte の送信を行う事になります。


ターミナルソフトで通信開始操作を行った場合
 ch1:装置の送信データ
 ch2:パソコンのフロー制御信号

 パソコンのビジー状態が解除されるので端末装置からの送信が再開しています。

 左図の場合、同時期に送信を再開していますが、今回のサンプルプログラムでは約 2ms 周期で送信サーバーを処理しているので、この時間を上限とした遅延が生じます。

 送信時のフロー制御、受信時のフロー制御、双方で似た様な波形になっていますが、微妙に信号の振幅幅が異なることで信号の変化元がどちらの装置であるかを察して下さい。これは利用するハードウェアドライバの仕様に依ります。

(8)ビジーの要因

 フロー制御は受信バッファをオーバーフローさせないための制御です(一部例外仕様を除く)。通信を行う2つの装置の性能差がある状態では非常に便利に働きます。ですが、ビジー状態が長くなった場合は問題も生じます。

 ビジー状態が長く続いた場合、その要因が
 ・フロー制御によるビジー状態?
 ・通信ケーブルが切断された状態?
 ・自身も含めて相手側のシステムトラブル?
等々の可能性を検討しなければなりません(フロー制御無しでも似た様な課題はあります)。

 この要因を排除する方法として「時間監視」と呼ばれる手法があります。

 通信データがある一定サイズのデータの塊(パケットとも呼ぶ)とし、その通信時間を予め規定します。規定時間内に受信(送信)を完了しなければ通信エラーとして異常処理を行います。

 通信時間を決める場合は余裕代(2倍程度)が必要です。通信時間だけでなく応答時間を定める場合もあります。

 過去のシステムの例ですが、やむを得ない事情でビジー時間が延びてしまう場合の対処方法として「定期的にビジー状態を解除する方法」を適用しました。この場合、結果として 1byte 受信を定期的に行います。上位装置の時間監視が 1byte 単位で行われている場合には有用ですが、データの塊を単位としている場合には通用しません。

(9)情報の鮮度

 別な問題「情報の鮮度」も考慮しましょう。

 定期的に情報を発信しているシステム、もちろん、フロー制御有り、送信バッファ有りと仮定します。

 上位装置がビジー状態に変化すると端末装置は送信を停止しなければなりませんが、その間にも送信バッファには新たな情報が蓄積します。上位装置のビジー状態が解除されると送信バッファのデータの送信再開を行いますが…。

 その時、送信される情報は「いつ頃の情報」でしょうか?意外と古くありませんか?

 非常に悩ましい問題ですが、情報の鮮度を期待するシステムにおいてフロー制御を適用するのは…難しいです。

 やろうと思えば送信バッファをクリアする方法もありますが、前述のデータの塊の考え方で、塊の途中で送信を一時停止した場合は中途半端な状態に陥ります。この場合、上位装置はデータの分析に苦労すると思います。

 フロー制御を有効とした状態での対策方法としては、
 ・部分的にフロー制御を適用しない … 上位装置のビジー状態は無いという仕組み(定義情報の応用です)
でしょうか?

 その他にも対策策はありますが…。非常に長くなりそうなので今回は割愛します。

(10)処理時間

 送受信の各割り込みハンドラ処理時間を調べてあったので追記します。

 今回使用したコンパイラは Lite モードであるため、最適化は最低、むしろ、マイナスの最適化(余分な情報が付加されている)ですが、それなりの処理速度は得られました。以下の数値は PIC16F886 内蔵クロック 4MHz の例です。

・受信データ有り … 80us ※受信バッファアクセスとフロー制御診断を含む
・受信データ無し … 24us
・送信データ有り … 56us ※フロー制御確認と送信バッファアクセスを含む
・送信終了 … 31us ※送信バッファ空で連続送信を終了するタイミング
・送信データ無し … 18us

 コンパイラのマイナス向き(?)最適化状況と源発振を考慮すると、いい感じの数字です。
 今回は源発振が 4MHz なので、例えば 16MHz を利用するのであれば、処理時間は 1/4 になります。
 割り込み処理時間が短くなれば、より高速度のシリアル通信に対応できます(但し、通信誤差少ないこと)。

■おしまい

 枯れた通信手段であるシリアル通信ですが、ちょっとしたデータのモニタ手段としては非常に便利です。
 端末装置の動作状況を把握する時にも利用できますし、やろうと思えばデバッグに利用する事ができます。


 昨今、USB、TCP/IP が主流ですが、その通信を行う場合は難しいプロトコル(通信ルール)に則って行わなければなりません。そのためのプログラム容量は半端無く大きく、処理時間も多く費やします。

 シリアル通信もプロトコルを実装すればプログラム容量を必要としますが、単にモニタするだけであれば、
  TXREG = 0x12; … バイトデータ送信(DrvComPutC)参照
の様な感じで任意の 1byte データを送信することができます。プログラムへの負荷は少ないです。


 送信の例を挙げましたが、受信も同様です。やろうと思えば割り込み無しで上位装置と通信することができます。その時のキーワードはマイコンが備える FIFO とバイト通信時間です。マイコンが備える FIFO をバイト通信時間内に読み出すことができるのであれば割り込みは不要です。

 通信時間…。

 調歩同期式通信では1byte の情報はスタートビット、ストップビットを含めて全 10bit で構成されます。
 例えば、9600bps であれば約 1041.7us で 1byte の通信が完了します。故に、その半分の時間、約 500us でサンプリングできるのであれば受信オーバーランエラーは発生しません。

 FIFO の状態を常にサンプリングすることができなければ、今度は割り込みの出番です。メイン処理で負荷が高い状態でも受信データを取得することができます。割り込みを利用してもなお、メイン処理の負荷が高い場合は、最終手段フロー制御の出番です。

 要は、システム仕様に基づき、割り込みを使うか、そしてフロー制御まで使うかを判断します。


 高度な機能を持つシステムの場合は前述の時間監視やデータの塊(パケット)を意識したプログラム構成を更に組み込む必要がありますが、今回はそこまで踏み込んでいません。あまりにもシステム仕様に近付きすぎると汎用ライブラリのボリュームが膨大な物になります。このあたりは各自の宿題と言うことで。。


Copyright 2007-2011 PaletteSoft LLC. All rights reserved. 利用条件 | HOME | サイトマップ | お問合せ

UART USART シリアル通信 マイコン フロー制御 RTS CTS DSR DTR RI TXD RXD TX RX