search
LoginSignup
47

More than 5 years have passed since last update.

posted at

updated at

シリアル通信でバイト列を扱うときのフレーム構造

問題

マイコン触っているとPCとのインターフェースにUARTを使うことがよくある。(UART-USB変換ICとか入れて)
単純なデータであればASCIIコードの文字列でやり取りすればいい。

例えばこんな感じ

元データ
{文字列}

変換後
<STX>{文字列}<ETX> 
(<STX>=0x02,<ETX>=0x03)

フレームはSTXが来たら開始、ETXが来たら終了となる。

さて、送りたいデータが増えてくると、テキストではなく生バイト列で送りたくなってくる。
しかしバイト列には当然0x00~0xFFが含まれ得るので、
何も考えずに文字列と同じようにSTXETXで挟んで送ると
データに0x020x03が含まれる場合、意図しないところでフレームの切れ目を認識してしまう。
ではどうするか?
先人たちの知恵を調べた。

(一番楽なのはUARTを投げ捨てることだが。)

時間を空ける

マイコン側が面倒。

データリンク拡張を使う

制御文字のDLE=0x10を使う方法。
送りたいデータ中の0X10を特別扱いする:
送りたいデータ中にDLEが入っていた場合にはDLE DLEに置換する。
要するにエスケープシーケンス。

{データ}
|
V
<DLE><STX>{変換データ}<DLE><ETX> 
変換前
00 02 10 1A 00 10 10

変換後(除Header,Trailer)
00 02 10 10 1A 00 10 10 10 10

特に難しいロジックでもなく、フレーム検出、変換の実装が容易。
ただし、元データ中にDLEが多く含まれると、変換後のフレーム長がやたら長くなる。
全データがDLEなら変換後はデータ部分が2倍になってしまう。

文字列に変換する

バイナリデータをASCIIで印字可能な文字列に変換すれば、制御文字を使用して送信できる。
変換方法に例えばBase64を使うと、データサイズ約33%の増加で文字列化できる。
Base64エンコード/デコード処理のマイコン向け実装もネットの海に転がっている。

Consistent Overhead Byte Stuffing1 (COBS)

長さが同じなら、どんなデータでも変換後のオーバーヘッドがだいたい等しくなるような変換方法。

0x00を特殊なバイトとして、データ中に0x00が出る場合は別のバイトで置換する。

  • フレームの切れ目は0x00で表現する:元データ先頭と末尾に0x00を追加する。
  • 末尾以外の0x00を、次の0x00までのバイト長(=0x00~0x00間にあるバイト数+1)で置換する。
  • 次に0x00が出てくるまでのバイト長が0xFF以上になる場合、0xFFに置換して、0xFF後に次の0x00が出てくるまでの(残りの)バイト長を入れる。

フレームの切れ目が0x00固定なので簡単にフレームを検出可能。
オーバーヘッドがそこそこ安定している。(254byte以下なら確実に+2byte)
ただし変換が若干面倒。

変換例

元データ + 末尾00
変換データ

   01 (00)
02 01 00

   00 (00)
01 01 00

   00 00 (00)
01 01 01 00

   01 02 00 03 04 00 (00)
03 01 02 03 03 04 01 00

   01 02 ... FE (00)
FF 01 02 ... FE 00

   01 02 ... FE FF (00)
FF 01 02 ... FE 02 FF 00

エラーチェック付きヘッダーをつける

フレームの長さが書かれたヘッダーを付ける。
当然長さ情報だけではフレームの区切りがわからないので、
一緒にヘッダーのエラーチェックなどをつける。
多分シリアルポート界では定番。とあるGNNS付き9軸+αセンサーもこうなっていた。

Generic Framing Procedure(GFP)だと
長さ2byte + ヘッダーエラーチェック2byte

オーバーヘッドが固定。
変換もヘッダー付け外しするだけなので簡単。
ただしフレーム開始の検出が(他の方法に比べ)面倒。


Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
47