最初に
Windows用の開発言語であるVisual Basic 6(VB6)には、シリアル接続
(RS232)の機器をVBプログラムから使用するためのMSCommというコントロールが標準で付属していました。
このMSCommコントロールを利用すると、多くの予備知識を必要とせず、ちょっとしたシリアル通信プログラムであれば簡単に作成することができました。
2002年に発売されたVisual Studio(VS)はVC++以外の言語は.Net
Framework(ドットネットフレームワーク)専用言語に移行され、VB.Net(VS2002,VS2003)となると、OSにとって都合の悪い旧タイプの周辺インターフェース(レガシーデバイス)が排除される動きが出てきて、残念なことにシリアルポートに対する制御が
言語仕様からばっさりと削除されてしまいました。
VB.Netでシリアルポートに接続された周辺機器をアクセスするためには、Windowsの持つWin32APIと呼ばれる
機能の中の、いくつかのファンクションを自分で構成する事で、ようやくシリアル通信ができました。
しかし、VB.NetではWin32APIというVBから離れたWindows自体の内部機能を呼び出して使う必要ために、ある程度深い知識を必要とし、ちょっと簡単にシリアル通信を使ってみる
という事ができなくなりました。
(ドットネットフレームワークで作成されたプログラムはマネージドと呼ばれる構成となり、Win32APIなど従来のWindowsのベースであるCOM(シリアル
ポートのCOMではなく、Component
Object Modelの事)と呼ばれる技術と異なります。)
しかし、PCレジやPC-POS用機器など多くの業務用PC機器はシリアル接続を必要としています。
現在でも多くのUSB機器はプログラムからの制御は公開されておらず、自分で制御するためには困難を極めています。
そのために、Windows標準でない多くの周辺機器をプログラムから制御する必要がある、レジやPOSなどのプログラムは非常に作りにくくなってしまいました。
結果的にWindows=ブラウザベースソフト的なプログラムが増え、以前のDOSやWindows Me時代までに比べ、パーソナルなコントローラ的なソフトは非常に少なくなってしまいました。
VB.Netは、.Net
framework用開発言語となり、従来のX86用開発言語ではなくなっています。また、ネットという言葉がついているために、インターネット用の開発言語という誤った認識がVB開発者にひろまってしまったようです。
MicroSoftも.Net化で大きくゆがんでしまった路線(?)を元に戻すべく、なんとドットネットという冠さえ、言語名称からはずしてしまいました。
その改良を加えたものが.Net Framework 2.0と2005年末に発売された.Net Framework 2.0開発用言語であるVB2005です。(私の勝手な想像です...)
多くの改良点の中で、SerialPortクラスはPC-POS周辺機器を扱うプログラマにとって、ちょっとうれしい新機能です。
ここではVB6時代のMSCommと比較しながら、SerialPortをちょっと観察してみます。
追記:2008年にVB2008がリリースされましたが、SerialについてVB2008の考え方はVB2005と同じです。
SerialPortコントロール
ここでは、現在でも多くのレジ周辺機器で利用されているシリアルポートをVB2005から利用する方法を紹介します。
これまでVB.NetでWin32APIを呼び出していたのと比較すると、非常に簡単にシリアルポート機器が使用できます。
以下は使用例です。
(説明画面のために、下記フォームは小さく表示し使用しています。)
1.ツールボックスからSerialPortコントロールを選択する。
SerialPortコントロールはRS232のCOMポートを制御するコントロールで、このコントロールは実行時にフォームでの表示を伴いません。
VB6の場合、表示を伴わないコントロールは、フォームのどこか(空いたスペース)に配置する必要がありました。
VB2005では表示を伴わないコントロールはフォームには張り付かず、デザイン画面の下に表示されます。
1つのフォーム中では、すべてのコントロールは識別のために独自(ユニークな)の名前を持つ必要があります。
コントロールを配置すると、コントロール名の末尾に番号がついたコントロール名が自動的に割り当てられます。
SerialPortコントロールの場合、最初に配置したものはSerialPort1という仮の名前が与えられます。
名前の変更は、このフォームデザイン画面のプロパティからできますし、そのまま変更せずに使用することもできます。
2.SerialPortのプロパティを設定する。
通信条件をSerialPortのプロパティに設定することで、プログラムから通信条件を設定せずに、実行後から通信を行うことができます。
プログラムを用いて、動的な設定もできますが、ここでは通信条件は固定として設定を行います。
コントロールを貼り付けた際表示される、デザイン画面左下のSerialPortコントロールをクリック選択することで、画面右側のビューにてプロパティの設定ができます。
プロパティメニューの項目中に、BaudRateやDataBits,Parityなど、基本的なシリアル設定項目があることがわかります。
主なプロパティ名 |
内容 |
設定例 |
その他の設定例 |
(Name) |
コントロール名 |
SerialPort1 |
|
Baud |
通信ボーレート |
9600 |
4800, 19200 |
DataBits |
データ長 |
8 |
|
Handshake |
ハンドシェーク |
RequestToSend |
None, XOnXOff, RequestToSendXOnXOff, |
Parity |
パリティビット |
None |
Odd, Even, Mark, Space |
PortName |
オープンCom番号 |
COM1 |
\\.\COM3 |
StopBits |
ストップビット長 |
One |
|
参考
VB6 MsCommのフォーム編集のプロパティ |
VB2005 SerialPortのフォーム編集のプロパティ |
|
|
TopやLeftなどコントロールの配置に
関してのプロパティが見受けられる。
COM番号はポート番号で与える。 |
Default値から変更されるとBold表示となる。
TimeOut項目が追加されている。
COM番号はPort名称で与える。 |
Tips: COM番号の与え方 MSComでは、プロパティの数値のみでCOM番号
(コムバンゴウ)を指定する方式のため、COM番号の上限に制限がありました。これは、Win32APIのCreateFileでCOM+数値を用いた場合、Windowsの問題でCOM10以上
は指定できないことに由来しているようです。(実際のOSのCOM最大数としては、Windows 2000/NT:最大256COMポート, Windows 95/98/ME:128 COMポート
のようです。
)
SerialPortコントロールからは、COM番号がTEXT名称で与えられるように変更になりました。
USB-COM変換インターフェースなどを用いた場合、接続するUSBポートを差し替えることで、WindowsにリザーブされたCOM番号が増えてしまい、アプリケーションで使用できるCOM番号範囲内からあふれることがありました。
このような多くのCOM番号が存在する場合でも、"\\.\COM10"という記述方式を用いることで、アサインされているすべてのCOM番号が使用できます。
備考:
\文字コードは、英文字ASCIIでは同じ文字コードのフォントはバックスラッシュ [
\ ]となります。
英語圏での表記(英文Font)では 「 \\.\
」 となります。
また\は\nなど書式制御を示すエスケープキャラクタコードです。
プログラムの String文字列中内では、 " を "" と記述するのと同様に、\ をあらわすのに \\ のように2回繰り返し1文字を記述します。
("\\\\.\\COM10"となる。)
追加情報:
VB2008のSerialPortコントロールでは、上記
\\.\形式で指定を行うと、例外エラー(Argument Exception)となるようです。 [PortName プロパティに、"\\" で始まる値が設定されました。]
|
3.プロパティの内容を調べる。
プロパティの設定を行う際は、その項目の内容を知る必要があります。
VB2005のプロパティの項目をクリック選択することで、プロパティの下段に簡単な概要のHelpが表示されます。
また、もっと詳しい内容を知りたい場合はキーボードのファンクションF1キーで選択した項目のHelpが表示できます。
画面デザイナの場合、操作に関するヘルプが表示されたり、うまく出ない場合Helpの中の検索を利用することで、詳しいHelpを得ることが可能です。
また、コントロールによってデザイナ設定のプロパティでは表示されない項目も多くありますので、すべての内容を使用されるコントロールについてはHelpで確認しておくことを薦めます。
まずプロパティやメソッド項目名の一覧を得るには、ヘルプのメンバを見るとすべての公開項目を調べることができます。
4. SerialPortのメンバを調べる。
では、実際にHelpでSerialPortコントロールを調べてみましょう。
Helpを見ると、SerialPortコントロールは、SerialPort クラスと呼ばれるライブラリモジュールであり、System.IO.Portsの名前空間に存在することがわかります。
名前空間とはライブラリの住所みたいなもので、SerialPortのクラスが Systemの中の、IOの中の、Portsという空間に存在していることを示します。
これは同じ名前をもったクラスがクラスライブラリ中に存在しても、名前空間を与えることで区別できるようになっています。
では、SerialPort クラスを見てみます。
プロパティやメソッドと呼ばれるメンバを持っています。
SerialPort クラスには、どのようなメンバがあるかヘルプを使って見てみ
しょう。
先ほどのデザイン画面のプロパティと比べ、なんかたくさんな項目がありそうですね。
これらは、プログラムから使用することができます。
これらの中でプロパティとメソッドを主に使用します。
プロパティは、主にコントロールに値を設定や取得する場合に使用します。
たとえばBaudRateというプロパティは、書き込むとボーレートを設定し、読み出すと現在設定されているボーレートが返ります。
メソッドは、そのコントロールで何かを実行するための呼び出しです。
たとえばOPENというメソッドを呼び出すことで、シリアルポートをオープンします。
すべてを使用することはありませんが、どんなメンバがあるかを最初にざっと見ておくことで、そのコントロールが見えてきます。
VB6のコントロールと比べると、設定できる項目がかなり増えていることがわかります。
Encodeingプロパティにより、日本語処理が非常に簡単になりました。
多くの場合Windows内のUnicodeからShift-JISへエンコードを変換する必要があります。
VB.Netでは、日本語文字列を送信する前に、バイト配列などにデータを一旦おき、それにEncodeをかけてバイナリ送信(受信の場合はその逆)する必要がありました。
Null処理なども考慮されているということで、VB6以前で発生していた問題も、かなり改善したようです。
VB6のMsCommコントロールでは直接できなかったタイムアウト関連の設定ができることがわかります。
MsCommではコントロールだけではタイムアウト制御やいくつかの制御ができなかったため、実用的なプログラムを作成するためには、必ずWin32APIを利用する必要があったため、結果的に一部の制御しか行えないMSCommを利用する必然性がありませんでした。
タイムアウトが設定できるようになったことで、SerialPortコントロールを用いて実用的なシリアル通信プログラムが作れそうです。
5. ちょっと高度な使い方へのヒント
このページでは、なるべく簡単に、わかりやすくプログラムを作ることとしているために、SerialPortコントロールを用いています
。
プログラムに慣れてくれば、SerialPortコントロールを使用せず、その元であるSerialPortクラスを直接呼び出してシリアル通信を行
うことができます。
プログラム記述を助けるコードスニペットにも、SerialPortクラスのサポートがあります。
自分でSerialPortクラスを用いプログラムを作成される場合の注意点として、プログラム実行期間中はリソースを自分で管理する必要が
あることがあげられます。
SerialPortコントロールの場合、フォーム中のコントロールという存在により、フォームが存在する間、そのポートを管理し続けることできます。
たとえば、プログラム的には送信し終わっていても、実際にはWindowsの中にはデータを受け渡していく何段かの仕組みがあります。
そのために、送信データを渡した直後にシリアル通信リソースを全て開放してしまうと問題を発生する可能性があります。
これはWindows内部で非同期(シリアル通信の非同期の意味ではなく、Windowsのファンクション実行が終了を待たずに次の処理に入る非同期処理という意味)で処理が継続されるからです。
.Net frameworkやWin32APIが持つキューバッファ、デバイスドライバの通信バッファ、通信LSI内部のFIFOなど、データが蓄積され
送り終わるごと流れていくため、アプリケーションに伝えられるデータ残量と制御線情報、Windows中が抱えるデータと実際の通信制御線はタイミング的に異なることに注意ください。
受信イベントも以下を考慮してください。(従来から、この辺は特に変わりませんが..)
非常に大まかな説明ですが、シリアル通信LSIがデータを1バイト受信すると、ハードウェア割り込みが発生します。
ハードウェア割り込みによりデバイスドライバは、シリアル通信LSIのFIFOからデータを受け取り、自分のドライバ内の受信バッファに保存するとともに、Windowsにメッセージ通知します。
(昔のPCではROM BIOSが割り込み受信処理を行っていましたが、近年のWindowsではROM
BIOSによる周辺機器制御は行われていません。)
Windowsのメッセージ処理により、Win32APIやSerialPort制御ルーチンへ通知され処理が行われ、そこからさらにアプリケーションにデータ受信のイベントは送信されます。
アプリケーションに渡されるイベントは、1バイト受信ごとに発生するハードウェア割り込みではありません。
多くの場合、転送途中に非同期的に受信イベントは発生しますので、分割された受信データを必要によって連結して処理する必要があります。
また、SerialPortコントロール(SerialPort
クラス)で、シビアなタイミングで制御線を制御する用途に使用することは避けたほうが良いようです。
Win32APIでの動作と異なり、内部でいくつかのポート処理が加わるようで、クラスからの制御がダイレクトにPORT制御線の操作につながっていないようです。
厳密なタイミングを要求する用途で、思ったように動作が行えない場合は、Win32APIでの実装を試すことも必要かと思われます。(残念ながらタイミング遅れ量についてのスコープ計測はしていません。)
シリアル通信の速度は、現在のCPUから見るとかなり低速です。 最終段にあるシリアル通信のLSIからデータビットが信号線に全て送り出されるまでは通信は完了していません。
大きなサイズの送信バッファで、大きなデータを扱う場合は注意が必要となってきます。
クローズ処理を行うと通信制御線 が閉じる事が考えられるため、ハードウェアハンドシェーク制御を行っていた場合で、完全にデータが送り終わっていない場合はデータがバッファに残る事があります。
またそれを制御するリソース管理はすでに終了しています。
データ転送には時間がかかることを常に頭においてプログラムを作成してください。
自分で処理を記述される場合は、メイン処理とは別のスレッドを設けて通信管理を行うことが望ましいと思われます。
スレッドを分けた場合の注意点として、別スレッド(セカンダリスレッド)でのイベント内では、実行されているメモリ空間が異なりますので、UIに対して直接制御
すると実行時に例外エラーを発生することが予想されます。(PinvokeやデリゲートについてHelpを参照ください。)
VB2005では、スレッドに関しても、BackgroundWorkerというスレッドを管理するクラスも利用できるため、簡単にバックグラウンドで別処理が行えます。
SerialPortコントロールもスレッドを分けていると思われます。
Helpでも、SerialPortコントロールのセカンダリ スレッドで発生するイベントについて、メイン スレッド内の一部の要素 (UI
要素など) を変更しようとすると、スレッドの例外が発生する可能性があ ることが明示されています。
6. シリアルポートのちょっとした歴史
歴史の古いシリアルポートはいろいろな呼び方をされることがあります。
シリアル通信の電気的規格で、アメリカのEIA(電子工業会)の古い規格番号であるRS232C(アールエス232シー)が有名です。
末尾は規格の改版番号を示しており、現在ではパソコンの周辺機器の変化に伴い、改版が進んでいるためC版ではありません。
1987にD版, 1991年にE版, 1997年にF版に改版され RS232という名称も、ANSI/TIA/EIA-232-Fと変更されています。
RS-232のC版が長らく規格の中心として広まっていたので、現在でもRS-232Cと呼ばれることがよくあります。
同様規格としてはITU(International Telecommunication Union:国際電気通信連合) RecommendationのV.28があります。
以前はRS232規格のシリアル通信を行うためには±12Vの電源を必要としました。代表的なドライブICとしてMC1488があります。
ICメーカーのMaxim社のMAX232という通信ドライバICの登場により、+5V単一電源からコンデンサの倍電圧回路と反転回路により±10Vを作成し通信できるICが主流となりました。
それまで、電子回路ではアナログ回路などで使用する±12Vの電源はポピュラーであったのですが、これにより、PCの電源ではマイナス電源を使う回路が廃止され、やがて電源の中からなくなっていきました。
シリアルの規格自体がかなりデファクトスタンダードの流れに乗っており、現在では3.3Vをベースに±6.6Vで動作する通信ドライバICも使用できる規格に進化しているようです。 RS232は電圧レベルで動作し、レシーバのHigh/Lowの閾値電圧は、設計値によって変わってきますが(レシーバはノイズ耐性のためにヒステリシス特性を持っているため)0.9から1.9VくらいにあるためにTTLレベル(VIH=2.0V,VIL=0.8V)の閾値に近く、最近ではTTLレベルを使用した擬似的なRS232(TTLシリアル)の周辺機器も近距離通信用として多く使われています。
参考
シリアル通信関連 参考情報
シリアル開発
RS232シリアル情報
シリアル接続機器
その他参考
技術情報Index
参考技術情報
Last Update :
2023/03/06
|