/ 更新: 2019/5/31

プログラマがシリアル通信のプログラムを書くために役立つイメージ

プログラミング


RS-232cなどのシリアル通信機器を制御するプログラムを書くときに、VB.netならSerialPortクラスがあるので、シリアル通信の細かい仕組みを知ることなくプログラムを記述することができます。 機器の制御コマンドのマニュアルを見て、なんとなくプログラムを書いて動かしてOKということの繰り返しです。 何年たっても、新しい機器を目の前に出されて、「これ使える?」って聞かれても自信を持って、「はい!」と答えることができません。 ということで、シリアル通信のプログラムを書くときに役立つイメージのようなものを記述します。 理論的なこととかではなくて、VB.netのSerialPortクラスで動作を確認しながら書いています。 [adsense]

シリアル通信の仕組みの教科書はあるの?

シリアル通信の仕組みそのものを詳しく説明する書籍はいろいろありますが、初心者プログラマが悩むような、実際にどうすればよいの?ということに関しては、知っている人にとっては、当たり前すぎるのか、教科書となるような書籍もみあたりません。

プログラムから見たシリアル通信のパターン

シリアル通信のパターンは、基本的に以下の2パターンです。

①シリアルポートに機器からデータが来るのを見張る。 ②シリアルポートに対してプログラムからコマンドを送信してから、シリアルポートに機器からデータが来るのを見張る。

①は、郵便ポストに広告などを入れられるイメージです。 ②は文通のイメージです。 受信バッファの動作 機器から受信したデータは受信バッファにたまります。 Q&A方式で書きます。 Q.機器から受信したデータはどうなるの? A.受信バッファにたまります。 Q.複数たまったデータを読み取ったら、どういう順番で取得できるの? A.古いものが一番前です。 FIFO方式です。 「性別は?」コマンドのレスポンスが「男性です。」 「年齢は?」コマンドのレスポンスが「40歳です。」 というパターンだとしたら、 性別は?性別は?年齢は? とコマンドを送ると、 男性です。男性です。40歳です。 年齢は?性別は?性別は? とコマンドを送ると、 40歳です。男性です。男性です。 となります。 なので、レスポンスを要求するコマンドを送信する場合、直前に受信バッファをクリアするか、DataReceivedイベントの中で処理することになります。 そうしないと過去に受信したけど未処理のデータが邪魔をして現在取得したい内容が取得できません。 Q.読み取ると受信バッファのデータは消えるの? A.消えます。 VB.netのSerialPortクラスの場合、Readコマンドで読み取ると受信バッファの内容がクリアされます。 連続して読み取ろうとしたところ、2回目はフリーズしました。 BytesToReadプロパティが0より大きい場合は、受信バッファにデータがあって、Readコマンドが使えますが、BytesToReadプロパティが0の場合、Readコマンドでフリーズするということがわかりました。 ということで、読み取る前に読み取るべきデータがあるかどうか確認するために、BytesToReadプロパティをチェックしたほうが良さそうです。

受信データの処理方法

データは1バイトずつ届きます。 機器のマニュアルを見ると、レスポンスのデータの記述は3パターンです。

①2進数で8ビットの各フラグのON/OFFで判別 ②10進数 ③16進数

結果的には、全部ほぼ同じです。 ①だけは、判別するときに少し苦労します。 例えば2ビット目がONのパターンは、以下のように、かなりいろいろあります。

000000010 000000011 001000010

実際には、パターンは限られているので、10進数や16進数で網羅的にリストアップしておいてプログラムを書いても良いし、ビット演算で判別するようにプログラムを書いても良いです。