Erklärung des Problems
Bei der Entwicklung eines anderen Geräts auf einem Mikrocontroller stieß ich auf eine Situation, in der eine kontinuierliche Aufzeichnung einer großen Datenmenge erforderlich war. Das Gerät musste einen Datensatz, der aus einem Zeitstempel und sechs ADC-Messungen von 100 Mal pro Sekunde bestand, auf einer SD-Karte speichern (nennen wir diesen Datensatz ein Paket) und diese Daten dann in Form von Grafiken auf einem Computer analysieren. Parallel zum Schreiben von Daten auf eine SD-Karte und deren Übertragung über UART war dies ebenfalls erforderlich. Diese Daten sollten so wenig Platz wie möglich beanspruchen, da viele Daten vorhanden sind. Gleichzeitig war es notwendig, diese Pakete irgendwie zu trennen, da die Daten in einem kontinuierlichen Strom gingen. Nachdem ich im Internet nichts Gutes gestöbert hatte, fand ich es nicht, und so wurde beschlossen, mein eigenes Protokoll und meine eigenen Bibliotheken dafür zu erstellen.
Und dann erschien er - Packet Streaming Protocol (PSP1N)
Aufgrund einiger Überlegungen wurde Folgendes entschieden: In dem Protokoll werden die Daten in Paketen übertragen, die aus N Bytes bestehen, wobei das erste Bit jedes Bytes dem Startbitzeichen für die Paketsynchronisation (daher der Protokollname) zugewiesen wird, die verbleibenden sieben Bits den Daten zugewiesen werden. Die Reihenfolge und Größe der Daten sind im Voraus bekannt.
Ein Beispiel:
Wir weisen 32 Bit für den Zeitstempel zu, 60 Bit für die ADC-Messungen (6 Kanäle mit 10 Bit), insgesamt 92 Bit. Da Sie 7 Bits nützlicher Daten in einem Byte übertragen können, besteht das Paket aus 14 Bytes (92 Bits / 7 Bit = 13,14 ... auf 14 aufrunden). Es gibt 112 Informationsbits in 14 Bytes, von denen 14 Bit durch das Startbitattribut von 92 Bits nützlicher Daten belegt sind, es gibt 6 nicht verwendete Bits (in die wir einige weitere Informationen schreiben können, aber der Einfachheit halber werden wir sie nicht verwenden).

Wo das 7. Bit das Vorzeichen des Startbits ist (zeigt den Beginn des Pakets an), sind 6,5,4,3,2,1,0 Datenbits.
Die empfangende Seite weiß auch, dass sie ein Paket von 14 Bytes empfängt, in dem das erste Bit des ersten Bytes das Startbit (1) ist (in den verbleibenden Bytes sind die Startbits 0), dann in den Datenbits in der Reihenfolge 32 Bits des Zeitstempels, dann 10 Bits der ADC-Messnummer. 1, dann 10 Bit ADC # 2 und so weiter ...
Ebenso erfolgt das Schreiben auf die SD-Karte und das Lesen von dieser gemäß dem Protokoll. Insgesamt erhalten wir für einen Tag Aufzeichnung auf einer SD-Karte 115,4 MB Informationen (14 Byte x 100 Messungen pro Sekunde x 3600 Sek. X 24 Stunden).
Eine solche Datenstruktur ist immer noch praktisch, da wir in Zukunft Datenblöcke von überall in der Datei auswählen und in Form von Diagrammen anzeigen können, wodurch nicht die gesamte Datei in den Arbeitsspeicher geladen wird (der mehrere zehn Gigabyte erreichen kann). Außerdem können wir das bequeme Scrollen dieser Diagramme implementieren, indem wir die erforderlichen Pakete laden.

Es ist Zeit, die Software-Implementierung für den Mikrocontroller zu starten
Wir schreiben die Bibliothek für den Mikrocontroller in C ++.
Erstellen Sie der Einfachheit halber eine Klasse:
class PSP { public: void init(byte startBit, byte* arrayByte, byte sizeArrayByte); void pushData(byte sizeBit, uint32_t value); byte* popData(); protected: byte startBit;
Bei der Initialisierungsmethode ist meiner Meinung nach alles klar:
void PSP::init(byte startBit, byte* arrayByte, byte sizeArrayByte) { this->startBit = startBit; this->arrayByte = arrayByte; this->sizeArrayByte = sizeArrayByte; }
Das Hinzufügen von Daten ist komplizierter. Hier platzieren wir die Daten durch listige bitweise Manipulationen in unserem Byte-Array.
void PSP::pushData(byte sizeBit, uint32_t value) { byte free; byte y; int remBit = 0;
Methode zum Abrufen eines Arrays von Bytes eines Pakets
byte* PSP::popData() { position = 0;
Und zum Schluss noch ein paar Zusatzfunktionen:
Zusammenfassend
Als Ergebnis der geleisteten Arbeit wurden das kompakte Protokoll für das Streaming von Daten PSP1N und vorgefertigte Bibliotheken, die hier von GitHub heruntergeladen werden können, „geboren“. In diesem Repository finden Sie:
- Beispiel für die Verwendung der Bibliothek "ExampleColsolePSP1N / C #"
- PSP1N_CPP / enthält die PSP-Bibliothek für die Arbeit mit dem Protokoll und ein Beispiel für dessen Verwendung auf Arduino
- PSP1N_CSHARP / Protokollbibliothek für .NET
Um die Funktionsweise des Protokolls zu demonstrieren, können Sie die Skizze in Arduino flashen und im Beispiel ExampleSerialPortRead auf dem Computer Daten vom Mikrocontroller über den COM-Port empfangen. Dort werden diese Daten entschlüsselt und in einer Konsolenanwendung angezeigt. Ich werde ein anderes Mal über die in C # geschriebene Bibliothek für die empfangende Seite sprechen.
TestingConsole:

UPDATE (31.03.19): Der Kodierungs- und Dekodierungsalgorithmus wurde geändert