7bits エンコーダ/デコーダ
最近、以前PC接続用基板を作ったXBeeを用いて、シリアル通信(より正確にはUART)をしていますが、少し困ったことがありました。当然やり取りされるデータは1byte単位なので、複数バイトで意味を持つような通信はちょっとした工夫をしないと、どこのバイトからどこのバイトが一つの意味単位を構成しているのかが不明になってしまいます。そこで今回はその工夫、題して7bits エンコーダ/デコーダについて記そうと思います。
実はこういうことはよくある話で、車輪の再発明であることは十分自覚していますが、せっかくコードを書いたので晒してみようと思います。
複数バイトで一つの意味を表すための工夫としてはいくつかの方法が考えられますが、今回は各バイトの先頭1bitを情報開始フラグとして利用することにしました。つまり先頭のバイトではそのフラグを落とし残り7bitsで情報を表す、例えば2進表記で0b0XXXXXXXのようにします。以降のバイトについてはそのフラグを立てて0b1XXXXXXXとし、同じく残り7bitsで情報を表すことにします。これでどこから意味単位が始まるのか簡単に把握できます。
ここで問題になるのが7bitsで情報を表す、ということです。1byte=8bitsなのでどう考えても7bitsでは情報量が不足します。そこで7+1に分けて、7bitsについては先頭のバイトに格納し、残り1bitについては次のバイトと混ぜて7+2にし、その7bitsについては2番目のバイトに格納し、
残り2bitについては更に3番目のバイトと混ぜて7+3にし………、という操作を繰り返すと、うまく情報を伝えることができます。これが7bits エンコーダのする仕事です。逆に7bits単位で送られてきた情報を引っ付けて元の情報に戻す、これが7bits デコーダの仕事です。
これをC言語でサクッと実装してみました。bits7.cとbits7.hです。u8 = unsigned charなので必要に応じてtypedefしてください。またテストコードをつけてあります。実行するには#define BITS7_TEST_MODEしてコンパイルしてみてください。
ちなみにですが先ほどの先頭1bitをフラグにする通信方式を利用すると、XBeeでは非常にいいことがありまして、"+++"(+を3文字分)でコマンドモード(GPIOの操作やAD変換値の取得などXBeeがもつ機能へのアクセスモード)に移行してしまうことを抑制できます。ASCII文字で表されてしまうのは先頭の一文字だけですので、複数バイトでやり取りをしている限りは'+'の文字が3個続くことはありません。
コメント
あ、1/256 + パケットヘッダか。
Posted by: 酔漢 : November 8, 2007 10:04 AM>酔漢さん
コメントどうもです。
使用目的として、数バイト程度の少量のバイナリデータ(ASCII文字以外もという意味で)が一つの意味単位になりそうであったので、おそらく上記の方法とお教えいただいた方法で伝送量はそれほど変わらないかと思います。
また、ASCII文字だけの通信でしたら"ESC"によるエスケープが有効ですが、バイナリですと"ESC"+"S"を転送したいという事態が当然ながら発生するので、"ESC"を表現するのに"ESC"+"ESC"にしてみたりと、今回の目的では更におまけをつける必要がありますね。
コメントする
- 匿名でのコメントは受け付けておりません。
- お名前(ハンドル名可)とメールアドレスは必ず入力してください。
- メールアドレスを表示されたくないときはURLも必ず記入してください。
- コメント欄でHTMLタグは使用できません。
- コメント本文に日本語(全角文字)がある程度多く含まれている必要があります。
- コメント欄内のURLと思われる文字列は自動的にリンクに変換されます。
- 投稿ボタンを押してエラーがでなければ、投稿は成功しています。反映されるまでには少し時間がかかります。
車輪の再発明とおっしゃっているのを承知で書き込みます。バイト単位の通信の場合、簡単な方法として情報パケットの先頭に"STX"文字を置くというものがあります。で、情報自体の中に"STX"と同じワードが現れたら、"ESC"+"S"にするといった置き換えをします。この場合、オーバーヘッドは1/128になります。
Posted by: 酔漢 : November 8, 2007 10:02 AM