Hallo Mikrocontroller-Gemeinde, wer kann mir mit seinem C#-Wissen weiterhelfen? Ein PC-Programm empfängt über die serielle Schnittstelle (UART vom µC) mehrere Bytes, diese werden im jetzigen Entwurf in ein char Array geladen. Die empfangenen Bytes 2-5 sollen nun zu einem 32bit - unsigned Integer zusammengesetzt werden. Beispiel: Empfangenes Byte 2 = 0x02 Empfangenes Byte 3 = 0xCA Empfangenes Byte 4 = 0x9A Empfangenes Byte 5 = 0x38 Die Bytes sollen zu 0x389ACA02 (dezimal 1.000.000.002) zusammengesetzt werden und in eine uint32 - Variable gespeichert werden, mit der dann im Programm weiter gearbeitet werden kann. Muss hierfür auch in C# mit Schiebeoperatoren gearbeitet werden? Danke für Eure Hilfe. Grüße
Moritz E. schrieb: > Muss hierfür auch in C# mit Schiebeoperatoren gearbeitet werden? Wäre eine saubere und portable Lösung. Hast du denn Angst vor den Schiebeoperationen?
1 | uint32_t ergebnis = |
2 | (((uint32_t)0x02) ) | |
3 | (((uint32_t)0xCA) << 8) | |
4 | (((uint32_t)0x9A) << 16) | |
5 | (((uint32_t)0x38) << 24) ; |
mfg mf
Angst nicht, nur Unwissenheit ;-) Bin nicht so Hochsprachen-affin und habe mich gefragt, ob es hier noch andere Optionen gibt. Danke!
:
Bearbeitet durch User
Moritz E. schrieb: > Bin nicht so Hochsprachen-affin und habe mich gefragt, ob es hier noch > andere Optionen gibt. Du könntest mit 256, 65535 und 16777216 multiplizieren. Wenn der Compiler schlecht ist, wird das allerdings weniger effizient ausgeführt. In C gäbe da noch Unions. C# hat das nicht.
Moritz E. schrieb: > Bin nicht so Hochsprachen-affin und habe mich gefragt, > ob es hier noch andere Optionen gibt. Du darfst dem Compiler aber unterstellen, dass er mit solchen Konstrukten gut umgehen kann.
Hier noch ein Beispiel: Byte[] bytes1 = { 0xEC, 0x00, 0x00, 0x00 }; Int32 value = BitConverter.ToInt32(bytes1, 0));
Wenn man es maximal unportabel, aber schnell haben will, kann man sowas auch als Daten in ein Assemblerfile legen, statt einer Union in C. Damit hat man auch die maximale Kontrolle ueber die Endianness des Resultats. Das schliesst ein, dass man es auch maximal falsch machen kann. Schieben und Odern koennen Compiler aber eigentlich auch ganz gut. Wie gut, dass man in VHDL sowas auch direkt hinschreiben kann.
Moritz E. schrieb: > mehrere Bytes, diese werden im jetzigen Entwurf in ein char Array > geladen Das würde ich in C# lieber nicht so machen. Das nutzt nämlich ein Encoding, um von Bytes auf Zeichen zu kommen. Empfange lieber direkt in ein Array von Bytes (byte[]).
Stefan ⛄ F. schrieb: > In C gäbe da noch Unions. C# hat das nicht. Aber etwas, womit sich das analog bauen läßt. Die Grundlage ist (wie in C) die Struktur, aber die Zugriffssteuerung erfolgt teilweise über Attribute. Die dazu nötigen Attribute findet man im Namespace System.Runtime.InteropServices. Allerdings, wie in mehreren Postings bereits angemerkt: man sollte solche Sachen aus Gründen der Portabilität besser nicht verwenden, oder nur dann, wenn man genau weiss, was man tut. Sonst knallt es z.B. mit Mono auf einem ARM gar fürchterlich, obwohl der Code derselbe ist und die Quelle nach wie vor dieselben Daten liefert... Mit dem, was der genannte Namespace liefert, ist es aber durchaus möglich, solche Konverterstrukturen auch portabel hinzubekommen. Wenn man halt weiss, was man tut...
c-hater schrieb: > Sonst knallt es z.B. mit Mono auf einem ARM gar fürchterlich, > obwohl der Code derselbe ist und die Quelle nach wie vor > dieselben Daten liefert... In C mit Unions liegt der Stolperstein in der Endianness des Systems, aber meines Wissens laufen Windows, Dotnet, Mono und die dazugehörigen Infrastrukturen aber nur auf little-endian-Systemen. Wo liegt denn das Problem mit "Mono auf ARM" hier?
S. R. schrieb: > In C mit Unions liegt der Stolperstein in der Endianness des Systems, Das ist nur einer der möglichen Stolpersteine. Es gibt da auch noch das Alignment-Problem.
c-hater schrieb: >> In C mit Unions liegt der Stolperstein in der Endianness des Systems, > Das ist nur einer der möglichen Stolpersteine. > Es gibt da auch noch das Alignment-Problem. Stimmt, das habe ich verdrängt.
Auch in C# gibt es sowas wie Unions:
1 | using System; |
2 | using System.Runtime.InteropServices; |
3 | |
4 | [StructLayout(LayoutKind.Explicit)] |
5 | public struct Union |
6 | { |
7 | // Vier Bytes |
8 | [FieldOffset(0)] public Byte b1; |
9 | [FieldOffset(1)] public Byte b2; |
10 | [FieldOffset(2)] public Byte b3; |
11 | [FieldOffset(3)] public Byte b4; |
12 | // Oder ein Int32 |
13 | [FieldOffset(0)] public Int32 i; |
14 | } |
Allerdings geht die Diskussion schon völlig über das Problem hinaus. Hier reicht als Lösung der Schiebeoperator oder die BitConverter-Klasse aus. Char sollte wie schon erwähnt nicht verwendet werden, weil in C# Zeichen UTF-16 kodiert sind (also 16-bit breit). Byte ist die richtige Wahl. Sofern .NET Core/.NET 5 zum Einsatz kommt, kann man auch über die Verwendung von Span<T> nachdenken wenn es um Performance geht.
:
Bearbeitet durch User
Hallo nochmal an alle, ich habe es zwischenzeitlich entsprechend euren Hinweisen umgesetzt, die Bytes werden jetzt in ein "echtes" Bytearray gespeichert und durch Schieben wieder zu einzelnen Variablen zusammengesetzt. Zu Beginn war es noch ein Char Array, mit der Umstellung des Encodings (vgl. https://docs.microsoft.com/en-us/archive/blogs/bclteam/serialport-encoding-ryan-byington) lief das auch. Fande die Lösung mit dem Bytearray am Ende aber die "sauberere". An der Stelle somit nochmal danke an Alle für den konstruktiven Input. Schön, dass es noch funktionierende Foren ohne Trolls gibt! Schönes Wochenende
Moritz E. schrieb: > Schön, dass es noch funktionierende Foren ohne Trolls gibt! ROTFL Echt. Wie heisst das ?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.