Hallo zusammen, falls im falschen Forum gepostet, bitte verschieben. es geht um eine aus 8 Bytes (Byte 0 bis 7) bestehende CAN Botschaft des Datenbereich. In einer Auswerteinheit muss neben der CAN-ID das Startbit, die Länge und die Byte-Order (Intel oder Motorola) engegeben werden. Es soll nun Byte 2 mit einer Länge von 16 Bit ausgewertet werden, demnach belegt die Datenbotschaft zwei Bytes = 16 Bit Länge. Meiner Meinung nach wäre - bei Motorola (Big Endian) das Startbit (beginnend mit 0) das Bit Nr. 16 - bei Intel (little Endian) das Startbit (beginnend mit 0) das Bit Nr. 23 Liege ich richtig? lg Frank
Du musst bei der Auswerte-Einheit konfigurieren, wo das Startbit ist? Schaue in deren Dokumentation, wie sie diese Angabe interpretiert. Wahrscheinlich ist beides mal Bit 0 das Startbit, weil eben die Bits ab Position 0 ausgewertet werden, wenn auch in unterschiedlicher Reihenfolge. Aber Achtung, falls du mit Vector DBC-Dateien arbeitest - hier ist das Startbit immer die Position des niederwertigsten Bits, und die ist bei Big Endian mitten in den Daten, 8 Bits vor Ende... Das ist unüblich und verwirrend und selbst der Vector-eigene CANdb++ Editor bekommt das nicht richtig hin.
Wie die Datenbytes zugegriffen werden, steht im Manual des jeweiligen CAN-Controllers. Sie sind in der Regel nicht als Word zugreifbar und auch nicht bitweise. Oft ist das Datenregister auch mit Autoincrement zugreifbar, d.h. nacheinander werden von der selben Adresse Byte 0..7 gelesen.
Über die Interpretation des Startbits schweigt sich die Doku leider aus, es kann 0 bis 63 angegeben werden und ja, Du hast den Finger drauf, es handelt sich um einen Datensatz aus einer Vector DB, welche mal die Bytes von 1 bis 8 und mal von 0 bis 7 benennt. Ähnlich bei den Bits. Hier ist eben aufgefallen, dass der gelesene Wert abnormal springt, weil es hätte heißen müssen Byte 1 und nicht Byte 2. Also würde Big Endian (Motorola) dann Byte 0 und 1 wie folgt zählen: 7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8 dagegen Intel: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Zeig doch mal einen Ausschnitt aus der Doku, die Konfiguration und einen Screenshot aus CANdb++ der fraglichen Signale... Man vertut sich bei sowas zu schnell als dass man das vernünftig in Textform wiedergeben könnte.
Ich durfte leider nur einen Blick in die DB werfen, da die offiziell nicht existiert und habe mir die ID, das Byte, die Länge und dass es Motorola / Big Endian ist herausgeschrieben, ebenfalls Offset und Scalierung zu PHYS Wert. Im datenstrom selbst ist mir dann aufgefallen, dass Byte 2 den Wert 0x00 hat und Byte 3 0xF0. Das kann aber nicht sein, denn dieses byte müßte auch für diesen Zustand 0x00 sein, also beide Bytes zusammen 0 ergeben. Das Byte 1 ist aber 0x00, darum habe ich das Startbit um 8 Stellen verringert und siehe da, es geht, die Wert stimmen. Jetzt hat mich persönlich interessiert, wie ich selbst für einen Datenpunkt das Startbit errechnen kann. z.B. folgende CAN Datenbytes mit der Konvention das Bits und Bytes von 0 an gezählt werden: 12 34 1F 00 00 34 76 22 Ich weiß, dass die die beiden Bytes 00 00 einen Wert beinhalten, der 16 Bit belegt, nämlich genau über diese zwei Bytes 3 und 4 geht. In dem Auswerte Programm gebe ich als Länge 16 Bit ein. Wenn nun die Byteorder bekannt ist, wie errechne ich dann das Startbit?
Frank K. schrieb: > Wenn nun die Byteorder bekannt ist, wie errechne ich dann das Startbit? Hängt halt von der Konvention ab... In den meisten Fällen ist das Startbit komplett unabhängig von der Byte-Reihenfolge immer das 0. Bit welches verarbeitet wird, egal welchen Wert man ihm beimisst. Das wäre hier dann immer 24, denn die Bytes 12 34 1F belegen 24 Bits, also ist das Bit danach das 24. ... Welches der beiden 0-Bytes jetzt die höherwertigen Bits enthält ist dabei unerheblich. Dies ist wahrscheinlich bei deinem Gerät das, was du angeben musst. Nur in den DBC-Dateien ist das so seltsam gemacht: Was dort fälschlicherweise "Startbit" genannt wird ist gar nicht das Startbit, sondern das niederwertigste Bit, also das Bit welches die 1er enthält. Das ist bei Big Endian hier 32, bei Little Endian 24. Das lässt sich so umrechnen: Big Endian: Niederwertigstes Bit = Startbit + Anzahl Bits - 8 Little Endian Niederwertigstes Bit = Startbit Die ganze Logik funktioniert natürlich nur, wenn man von ganzen Bytes redet, und das Signal nicht 12 Bits oder so ist.
Beim Auslesen eines CAN-Objekts muß man auch immer die Länge beachten. Wenn die Länge 3 ist, dann darf man auch nur 3 Bytes auslesen. Liest man aber 8 Bytes aus, dann stammen eben die überzähligen 5 Bytes noch von einer älteren Nachricht und das ergibt Unsinn. Was nun die 0..8 Datenbytes im einzelnen bedeuten, legt das übergeordnete Protokoll fest und nicht Motorola oder Intel. Da sich einfach irgendne Order auszudenken, bis es passen könnte, ist er falsche Ansatz. Man muß die Protokollbeschreibung lesen.
Ok, danke. Sehr gut erklärt und verstanden. Dann freu ich mich mal auf das nächste Objekt, was ich vorgesetzt bekommen ;-) lg und schönes WE, Frank
Peter D. schrieb: > Beim Auslesen eines CAN-Objekts muß man auch immer die Länge beachten. > Wenn die Länge 3 ist, dann darf man auch nur 3 Bytes auslesen. Liest man > aber 8 Bytes aus, dann stammen eben die überzähligen 5 Bytes noch von > einer älteren Nachricht und das ergibt Unsinn. > > Was nun die 0..8 Datenbytes im einzelnen bedeuten, legt das > übergeordnete Protokoll fest und nicht Motorola oder Intel. Du hast noch nicht viel mit Automotive CAN gemacht, oder? Da gibt's für den überwiegenden Teil der Botschaften kein übergeordnetes Protokoll, sondern eine so genannte Datenbasis. Das ist eine Datei, in der für jede Botschaft exakt drin steht, wo welcher Wert steht (und das ist fix - er steht immer exakt in dieser Botschaft, exakt an dieser Stelle). Also so in der Art: Temperatur ist in Botschaft 0x123 ab Bit-Position 14 und ist 11 Bits groß. Dazu wird auch eine Byteorder angegeben für Signale, die sich über mehr als ein Byte der Botschaft erstrecken. Diese Byteordern werden mit "Intel" und "Motorola" bezeichnet. Um also die Temperatur da wieder rauszuextrahieren, muss man wissen, welche Bits da nun dazugehören, und das hängt auch davon ab, ob Intel- oder Motorola-Byteoder. > Da sich einfach irgendne Order auszudenken, bis es passen könnte, ist er > falsche Ansatz. Man muß die Protokollbeschreibung lesen. Das wäre in dem Fall: Frank K. schrieb: > Ich durfte leider nur einen Blick in die DB werfen, da die offiziell > nicht existiert und habe mir die ID, das Byte, die Länge und dass es > Motorola / Big Endian ist herausgeschrieben, ebenfalls Offset und > Scalierung zu PHYS Wert.
Doch, ich mache sehr viel mit Automtive CAN, sogar mit KBA und ECE Zulassung. Ist aber ein anderer Bereich, da es hier nicht um Automative geht. CAN Bus ist aber CAN Bus und entsprechend spezifiziert. Der Fall wurde im ersten Post dargestellt. Das was Du geschrieben hast ist auch völlig klar. Das Problem war, dass es nur die Info gab: Botschaft 0x123, DLC 8, Byte zwei mit 16 Bit Länge, Motorola. Was mich beschäftigte: Wie berechnet man das Startbit bei Motorola und was wenn es Intel wäre? Die Antwort hat Niclas G. gegeben: Big Endian (Motorola) Niederwertigstes Bit = Startbit + Anzahl Bits - 8 Little Endian (Intel) Niederwertigstes Bit = Startbit Was von beiden funktioniert, kann man durch zwei Versuche "probieren". Hier kam aber erschwerend hinzu, dass die Angabe Byte 2 falsch war, da man von Byte 1 bis 8 gezählt hat, demnach war Byte 1 richtig, wenn man von 0 bis 7 zählt, was die Auswert Sofware auch macht. lg Frank
Frank K. schrieb: > Doch, ich mache sehr viel mit Automtive CAN, Meine Aussagen gingen nicht an dich, sondern an Peter. Frank K. schrieb: > Das Problem war, dass es nur die Info gab: Botschaft 0x123, DLC 8, Byte > zwei mit 16 Bit Länge, Motorola. > > Was mich beschäftigte: Wie berechnet man das Startbit bei Motorola und > was wenn es Intel wäre? Wenn du CANalyzer oder CANoe hast, ist da der CANdb++-Editor dabei. Geht angeblich auch mit der Demo-Version. Da kannst du dir ein Signal basteln, das diesen Werten entspricht und dir dann die Belegung der Bytes ansehen.
Rolf M. schrieb: > Du hast noch nicht viel mit Automotive CAN gemacht Stimmt. Aber warum kann man es nicht eindeutig und klar definieren. Man kann doch ganz einfach sagen, z.B. Datenbyte 0 ist das LSB und Datenbyte 1 das MSB des 16Bit Wertes. Warum muß man alles immer maximal umständlich definieren? Bei Intel und Motorola müßte ich erst nachschlagen, was damit gemeint sein könnte. Protokolle sollten immer Architektur unabhängig sein, z.B. Network Byte Order. Wir sind bei unserem CAN-Protokoll dazu übergegangen, alles als String zu übertragen. Das macht es maximal einfach zu debuggen und minimal mißverständlich.
Peter D. schrieb: > Rolf M. schrieb: >> Du hast noch nicht viel mit Automotive CAN gemacht > > Stimmt. Aber warum kann man es nicht eindeutig und klar definieren. > Man kann doch ganz einfach sagen, z.B. Datenbyte 0 ist das LSB und > Datenbyte 1 das MSB des 16Bit Wertes. Es kann nicht nur Vielfache von 8 geben. Im Prinzip kann der Wert an beliebiger Stelle anfangen und beliebig lang sein. > Warum muß man alles immer maximal umständlich definieren? Weil es hier darum geht, dass die Botschaften auch von sehr kleinen µCs gelesen werden, und das ggf. in großer Anzahl und Häufigkeit. Man will es daher dort möglichst effizient haben und jede Umrechnung einsparen. Das mag heute nicht mehr ganz so wichtig sein, aber zu Anfangszeiten des CAN musste man sehr sparsam sein. > Wir sind bei unserem CAN-Protokoll dazu übergegangen, alles als String > zu übertragen. Das macht es maximal einfach zu debuggen und minimal > mißverständlich. Das wäre im Automotive-Bereich viel zu viel Overhead, sowohl im Bezug auf die Datenmenge, als auch im Bezug auf den Code zum Auswerten der Daten.
Peter D. schrieb: > Bei Intel und Motorola müßte ich erst nachschlagen, was damit gemeint > sein könnte. ... wer das nachschlagen muß, hat entweder keine Ahnung von Computertechnik oder ist beneidenswert jung (und in dem Fall entlastet) ;)
Peter D. schrieb: > Das macht es maximal einfach zu debuggen und minimal > mißverständlich. Da mach ich doch mal Eigenwerbung :)
1 | #include <cstdint> |
2 | #include <iostream> |
3 | #include <uSer.hh> |
4 | |
5 | struct MyMessage { |
6 | USER_STRUCT(MyMessage, uSer::ByteOrder::BE) |
7 | |
8 | USER_MEM(std::uint32_t, voltage, uSer::Width<24>) |
9 | USER_MEM(std::uint16_t, rpm) |
10 | USER_MEM(std::uint16_t, torque) |
11 | USER_MEM(std::uint8_t, state) |
12 | |
13 | USER_ENUM_MEM(voltage, rpm, torque, state) |
14 | };
|
15 | |
16 | int main () { |
17 | std::uint8_t canMsg [8] { 0x12, 0x34, 0x1F, 0x00, 0x00, 0x34, 0x76, 0x22 }; |
18 | |
19 | MyMessage msg; |
20 | uSer::deserialize (canMsg, msg); |
21 | |
22 | std::cout << std::hex << "voltage = 0x" << msg.voltage << "\n" |
23 | << "rpm = 0x" << msg.rpm << "\n" |
24 | << "torque = 0x" << msg.torque << "\n" |
25 | << "state = 0x" << (int) msg.state << "\n"; |
26 | }
|
Ausgabe:
1 | voltage = 0x12341f |
2 | rpm = 0x0 |
3 | torque = 0x3476 |
4 | state = 0x22 |
Mit µSer ( https://github.com/Erlkoenig90/uSer ) kann man solche CAN-Nachrichten portabel en/de-kodieren; um z.B. zwischen Big Endian und Little Endian umzuschalten muss man nur das "BE" durch "LE" tauschen. Die Definition des structs könnte man sich automatisch aus einer DBC-Datei generieren lassen. So ist das leicht anpassbar ohne dass man den Code ändern müsste.
Frank K. schrieb: > Big Endian (Motorola) > Niederwertigstes Bit = Startbit + Anzahl Bits - 8 Vorsicht, diese Formel stimmt nicht!
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.