質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
シリアルポート

シリアルポートは一度に一ビットごと移行される物理的なインターフェイスです。一般的には、9ピンのd-subコネクタであるRS-232を指します。

Q&A

解決済

3回答

11019閲覧

シリアル通信でバイト列中に制御コードがある場合の対処方法

bsk

総合スコア174

シリアルポート

シリアルポートは一度に一ビットごと移行される物理的なインターフェイスです。一般的には、9ピンのd-subコネクタであるRS-232を指します。

0グッド

0クリップ

投稿2019/04/11 09:46

前提・実現したいこと

シリアル通信でデータを出力している機器がありこれからデータを拾いたいです。
下記簡略化した仕様の例ですがSTXとETXで開始と終了が区切られています。
{STX} {4バイト整数} {ETX}
データサイズは固定長ですが連続してデータを垂れ流している状態です。

発生している問題

4バイト整数の中にETX(0x03)やSTX(0x02)が含まれる場合があり、単純にSTX,ETXで区切るとデータを正しく拾うことができない時があります。

質問

・受信側のプログラムで対処する方法
・機器側のデータ出力の仕様は妥当なのか
・データ出力の仕様が不適切な場合、バイナリ形式でデータを出力する際はどのような仕様が望ましいのか

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

t_obara

2019/04/11 09:58

4バイト整数がデータを意味しているのですか?また、ETX/STXのバイト数は決まっているのですか?またデータ取得を開始する場合、ETXから流れてくることは保証されているのでしょうか?
bsk

2019/04/11 10:38

4バイト整数がデータを意味しています。ETX/STXは制御コードなので1バイト以外ないんじゃないでしょうか?STX,ETXにデータは囲まれてはいますがデータは垂れ流し状態なのでスタート部分が不明です。
fuzzball

2019/04/11 10:53 編集

質問の例だと、データ部の先頭が0x03のときに問題が出るということでしょうか?
fuzzball

2019/04/11 11:03

あー、垂れ流しの途中からでも拾えるようにしたいってことかな?
guest

回答3

0

(書いてるうちに解決済になってしまった…)

機器側のデータ出力の仕様は妥当なのか

(仕様の簡略化されたところに何かあったりせず、スタート部分が不明で読むことは想定された使い方だとして)
「ほとんどのデータで問題なく動く」でよければ妥当です。
「あらゆるデータで問題なく動く」を求めるなら妥当でないです。

受信側のプログラムで対処する方法

4バイトでないものは弾いて、偶然ETX/STXの間が4バイトのものは不正な値が読めるのは稀なこととして許容するしかないです。
実用上、最初の1回以外で問題が起こることはまずないでしょう。

データ出力の仕様が不適切な場合、バイナリ形式でデータを出力する際はどのような仕様が望ましいのか

確実に問題が起こらないようにするなら、データ内に区切り文字を含まないようにデータをエンコードするしかないですね。
1つは区切り文字だけを別の文字に置き換える方法。仕組みが単純ですが、内容によってデータ長が変わること、特に区切り文字のみが連続した場合に大幅に増えるのが欠点です。
もう1つ、全体をbase64などで変換し区切り文字を含まないデータにする方法もあります。内容によらずデータ長が一定ですが、目視でデータが読めない欠点があります。

問題が稀にしか起こらなければよいのであれば、チェックサムを付けるのもよいでしょう。区切り文字を長くする方法も思いつきます。

投稿2019/04/11 13:57

ikadzuchi

総合スコア3047

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

まず、STX来るまで待って、6バイト取り、最終バイトがETXかを見ます。
そうでない場合は、STXの次のバイトからSTXを探して、そこから6バイト取り、ETXかどうかをみます。
こうやって、STXとETXの組を見つけ、メッセージの同期を取り、データを取ります

データとってる途中で、STX/ETXから外れた場合は、そのデータを捨て、これまたSTXの次のバイトからSTXを探し、、、としていきます

で、こういう仕様は妥当なもので、よく使われてます

まあ、よくやることとしては、STXの次にメッセージのバイト数、チェックサムなどを挟んでETX、として、
可変長メッセージを実装したりしますね

投稿2019/04/11 12:29

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

bsk

2019/04/11 13:32 編集

回答ありがとうございます。仕様としても妥当、バイト数、チェックサムなど挟み可変長も対応できるんですね。アドバイスにそってプログラムを組んでみます。
y_waiwai

2019/04/11 13:41

テキストデータの通信では、ノイズなどでデータが化けた場合、文字化けとかなって検出できんこともないですが、バイナリ通信では、なにもなしではデータが化けたときの判定ができません。 このためもあってチェックサムなんかをつけたりしますね #有線でのシリアル通信でデータ化けってのはよーーーーーっぽどのことがないと起こりませんがw
guest

0

データ部を16進数の文字列で送ります。
データ量は増えちゃいますが。

例えば、0x01234567, 0x89abcdefならSTX "01234567" ETX STX "89abcdef" ETXとなります。

単にカンマ区切りとかでいいような気もしますが。
"01234567,89abcdef"

p.s.
ボケた回答をしてしまったのでお茶濁しです‥。

投稿2019/04/11 15:04

編集2019/04/11 15:47
fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問