65486
STM32F767ZI(Nucleo-144)のUARTを用いて複数バイト(4byte)送信して、  
PC側アプリ(C#)で受信しようとしています。

PC側アプリで4byte受信できているのですが、受信データのバイト列の開始位置が、  
アプリ起動毎に代わってしまいます。

何か対処法はありますでしょうか。

```

    private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                int length;
    
                length = serialPort.Read(data, uart_data_offset, uart_data_len);
    
                float f_test = BitConverter.ToSingle(data, 0);
                Console.Write("data[0] = {0:x}, data[1] = {1:x}, data[2] = {2:x}, data[3] = {3:x}\n", data[0], data[1], data[2], data[3]);
                //Console.Write("f_test = {0:f}\n", f_test);
                Console.Write("f_test = {0,7:f}\n", f_test);
            }
    
```
CC BY-SA 4.0
2020-04-09T06:28:25.983
65485
2020-04-10T10:36:29.030
2020-04-09T06:33:27.433
32986
19860
question
c#
C#とマイコン(STM32F767ZI)とのUART通信
それは無手順の通信では避けられない課題です。

データ自身に特徴や法則がある(第nバイト目は値がXX/特定のBitが必ずONまたはOFFなどで、他のバイトはそうではない)場合は、それをバイトごとに判定してチェックし、そうしたものが無いなら、前や後にそうしたデータを付加して、それを基に同様にバイトごとに判定してチェックしてください。

要は何らかの手順を作りましょう、ということです。  
既に従っている手順があるなら、それに合わせたプログラムを作成してください。

* * *

本格的な手順の例としては以下のものがあります。

[BASIC手順](http://software-engineering-lab.com/network/basic.html)

非常に単純な独自の例としては以下になります。

[byte aligning in serial
communication](https://stackoverflow.com/q/9468615/9014308)

組み込み系(レシートプリンタ)の例です。

[GS a - 自動ステータス送信の有効・無効](https://reference.epson-
biz.com/modules/ref_escpos_ja/index.php?content_id=122)

他にはGPSの通知フォーマットとかは全てテキストでやっていますよね。

[NMEA 0183の情報](https://www8.garmin.com/manuals/webhelp/gpsmap1002-1202/JA-
JP/GUID-891D6EC7-169E-4146-8279-8400626217D0.html)  
[GPSのNMEAフォーマット](https://www.hiramine.com/physicalcomputing/general/gps_nmeaformat.html)  
[NMEA Revealed](https://gpsd.gitlab.io/gpsd/NMEA.html)

* * *

ちなみに考えすぎかもしれませんが、独立したアーキテクチャの間で浮動小数点数のバイナリフォーマットが完全な互換性を保っているとは限りません。細かい準拠版数の関係で微妙に違うデータが発生する可能性が考えられます。  
まあ実用上の問題は無いと思われますが、両方のプログラムがC#で作られているのでなければ、BitConverter.ToSingle()を使うのは注意した方が良いかもしれません。

(太字は引用者)  
[STM32 Nucleo-144 Development Board with STM32F767ZI
MCU](https://www.element14.com/community/docs/DOC-83084/l/stm32-nucleo-144-development-
board-with-stm32f767zi-mcu-supports-arduino-st-zio-and-morpho-connectivity)

> The STM32F765xx, STM32F767xx, STM32F768Ax and STM32F769xx devices are based
> on the high-performance ARM®Cortex®-M7 32-bit RISC core operating at up to
> 216 MHz frequency. The Cortex®-M7 core features a floating point unit (FPU)
> which supports ARM® double-precision and single-precision data-processing
> instructions and data types. It also implements a full set of DSP
> instructions and a memory protection unit (MPU) which enhances the
> application security.

[Cortex-M7](https://en.wikipedia.org/wiki/ARM_Cortex-M#Cortex-M7)

> Optional floating-point unit (FPU): (single precision) or (single and
> double-precision), both **IEEE-754-2008** compliant. It is called the FPv5
> extension.

[Single 構造体](https://docs.microsoft.com/ja-
jp/dotnet/api/system.single?view=netframework-4.8)

> Single 型は、バイナリ浮動小数点演算の **IEC 60559:1989 (IEEE 754)** 標準に準拠しています。
CC BY-SA 4.0
2020-04-09T06:58:42.180
65486
2020-04-10T10:36:29.030
2020-04-10T10:36:29.030
26370
26370
65485
answer
ふつう、シリアル通信は文字列のやり取りを行います（例外はもちろんあり）  
で、一つのメッセージの最後に改行コードを入れ、行単位のメッセージのやり取りとします。  
こうしておけば、改行コードの受信で、一つのメッセージの区切りが判明しますんで、それまでに受信した文字列を持って内容の解釈を行うようにします。
CC BY-SA 4.0
2020-04-09T13:47:17.683
65500
2020-04-09T13:47:17.683
27481
65485
answer
通常シリアル通信は1バイト単位の送受信となります。従いまして複数バイトで1つの意味をなすデータは、どこからどこまでが1つの固まりであるか、明確にする必要があります。  
従いまして、y_waiwaiさんの説明のように、固まりの最後に改行コードを入れるか、頭にSTXを送信し、最後にETXを送信するような方法をとります。  
必ずこうしなければいけないということはありませんが、送信側でデータのひとかたまりがわかるような方法で、送信する必要があります。  
例えば送信側でひとかたまりのデータを1秒単位で送信し、受信側では0.5秒以上データが来なかったらすべてのデータを受信したことにするような実装方法もあります。  
また、常時データを送信するのではなく、リクエストを受信してデータを送信する方法など、いろいろな実装方法がありますので、検討してみてください。
CC BY-SA 4.0
2020-04-10T07:10:41.407
65514
2020-04-10T07:22:11.630
2020-04-10T07:22:11.630
24490
24490
65485
answer