Guten morgen,
ich soll für ein Projekt Debug-Nachrichten über CAN verschicken.
Das funktioniert auch schon (Die Funktion zum senden ist ja schon
vorgegeben).
Diese werwartet die Adresse (an wem ich verschicke, uint8 array (mit den
Daten) und die Anzahl der Daten.
Aber wie kann ich Jetzt habe ich hier aber werte, welche sint16 sind.
Wie kann man diese denn am besten verschicken? Für die Anderen
Nachrichten habe ich ein Array welches uint16 Werte erwartet (das sind
nämlich die meisten werte), welches ich dann beim Funktionsaufruf auf
uint8* caste.
Sebastian schrieb:> Diese werwartet die Adresse ... und die Anzahl der Daten.> Aber wie kann ich Jetzt habe ich hier aber werte, welche sint16 sind.
Wie soll man das verstehen?
> Wie kann man diese denn am besten verschicken?
Indem man die Bits auf mehrere Datenbytes verteilt:
https://images3.programmersought.com/555/31/311da57148fbf07dcf259f58cfdb17fb.JPEG
Sender und Empfänger müssen sich nur über die Reihenfolge einig sein:
Lo-Byte oder High-Byte zuerst. In fertiger CAN-Software wird das Intel-
und Motorola-Byte-Order genannt.
Du schreibst deinen sint16 Wert in das Array. Wenn ich deinen Text
richtig
interpretiere, müsste das Schreiben ausserhalb der Sendefunktion
erfolgen.
Du müsstest allerdings folgendes wissen:
An welche Stelle im uint8 Array soll der Wert geschrieben werden?
In welcher Byteoder (LSB oder MSB) wird auf dem Bus gesendet?
Mal ein Beispiel:
uint8 txData[8] = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
sint16 dbgValue;
txData[0] = uint8((dbgValue&0xFF00)>>8);
txData[1] = uint8(dbgValue&0x00FF);
SendeCAN(txData, 8);
Dieses Beispiel geht von Byteorder MSB aus und legt den dbg-Wert auf
Byte 0 und 1 im CAN Frame.
Sebastian schrieb:> Nachrichten habe ich ein Array welches uint16 Werte erwartet (das sind> nämlich die meisten werte), welches ich dann beim Funktionsaufruf auf> uint8* caste.
dann nimm halt ein sint16 Array und caste es auf uint8*
Martin schrieb:> dann nimm halt ein sint16 Array und caste es auf uint8*
Das habe ich jetzt auch mal getestet und den zu sendenden wert
festgelegt
1
tmp_16=-200;
2
debug_au16[0]=tmp_16;
3
debug_au16[1]=200;
4
debug_au16[2]=0xFF;
5
debug_au16[3]=0xFF;
6
canSend(0x111,(uint8*)debug_au16[0],8);
jetzt sehe ich im CAN-Trace, dass byte[0]=0x38, byte[1]=0xFF,
byte[2]=C8, byte[3]=0x00, byte[4]-byte[7]=0xFF
wie kann ich denn von diesem Wert (0x38 und 0xFF) auf die -200
schließen?
Der Empfänger muß feststellen können, welches Byte im Paket welche
Bedutung hat, d.h. Du brauchst ein Protokoll, was man parsen kann.
Man kann sich ein Protokoll selber ausdenken oder irgendein
Standardprotokoll nehmen.
Gerne werden Strings genommen, da man die in einem Terminal direkt lesen
kann. Da Stringnachrichten oft >8 Byte sind, braucht einen Pakettyp, der
aus mehreren CAN-Nachrichten besteht.
Peter D. schrieb:> Gerne werden Strings genommen, da man die in einem Terminal direkt lesen> kann. Da Stringnachrichten oft >8 Byte sind, braucht einen Pakettyp, der> aus mehreren CAN-Nachrichten besteht.
Über ein Transportprotokoll?
Ich würde den einfacheren Weg gehen, die sint16 im CANdb-Tool in der
gewollten CAN-Message zu definieren, damit das dann im CAN-Trace oder im
CAN-Graphen korrekt skaliert angezeigt wird. Dann in der ECU bzw. PLC
entsprechend dieser Definition befüllen. Den Rest erledigt
INCA/CANoe/CANape/... dann von selbst.
Wenn der TO einen XCP-Server auf dem Steuergerät/Industriegerät zum
laufen bringt, geht es mit einem XCP-client wie z.B. eben INCA oder
CANape noch einfacher. Über ein generiertes A2L bzw. aus ELF generiertem
A2L kann dann Wahlfrei jede Variable angesehen und ggf. Manipuliert
werden. Wie ein Debugger eben :)
mfg mf
Sebastian schrieb:> canSend(0x111, (uint8*)debug_au16[0], 8);
Damit castest du den Inhalt vom Arrayeintag 0.
Wenn du die Adresse vom Array haben möchtest, nimmst du nur den Namen
(oder den Adressoperator für Index 0)
Sebastian schrieb:> wie kann ich denn von diesem Wert (0x38 und 0xFF) auf die -200> schließen?
Gar nicht, sind ja die falschen Werte.
Mach dich mal über Zweierkomplement und Endianess schlau.
Dazu gibt es Wikipediabeiträge.
Sebastian schrieb:> wie kann ich denn von diesem Wert (0x38 und 0xFF) auf die -200> schließen?
Du könntest dich mal ein bissl bemühen, und dir aneignen wie Zahlen in
der Digitalen Welt gespeichert werden. Stichwort Binärzahlen. Dazu gibt
es viel in der Literatur und im Internet zu lesen.
http://www.scalingbits.com/book/export/html/46
0xff38 hex = -200 dec
0x0000 - 1 = 0xffff
0x0000 - 2 = 0xfffe
Sebastian schrieb:> wie kann ich denn von diesem Wert (0x38 und 0xFF) auf die -200> schließen?
Mach dich mal über Zweierkomplement und Endianess schlau.
Dazu gibt es Wikipediabeiträge.
Serialisierung
Die dort vorgestellte µSer-Bibliothek kann signed Integer in
verschiedenen Formaten kodieren/dekodieren.
Peter D. schrieb:> Da Stringnachrichten oft >8 Byte sind, braucht einen Pakettyp, der> aus mehreren CAN-Nachrichten besteht.
Zahlen als Strings über CAN verschicken ist nicht sehr zweckmäßig.
Niklas G. schrieb:> Zahlen als Strings über CAN verschicken ist nicht sehr zweckmäßig.
Es sind ja nicht nur reine Zahlen.
Meine Nachrichten sind so aufgebaut:
"Befehl Parametername Wert1 [Wert2] [...]\n"
Ich brauche also nur einen allgemeinen Sniffer, der CAN-Pakete zu einer
Stringnachricht aneinander reiht und anzeigt.
Das Aneinanderreihen geht ganz einfach. Das erste Byte kennzeichnet den
Stringtyp bzw. ist die fortlaufende Nummer der zu einer Nachricht
gehörenden CAN-Pakete (max 16).
Ich kann dann Befehle beliebig hinzufügen oder ändern, ohne das ich
jedesmal einen neuen Interpreter brauche.
Wir hatten früher auch binär benutzt, aber das war fürs Debuggen ein
Graus. Alles nur kryptische Hex-Bytes.
Peter D. schrieb:> Wir hatten früher auch binär benutzt, aber das war fürs Debuggen ein> Graus. Alles nur kryptische Hex-Bytes.
Schon mal CANoe mit DBC-Daten benutzt? Das dekodiert alles automatisch
und stellt es lesbar dar. Wenn man eine Nachricht ändert klickt man das
in CANdb++ fix zusammen, da muss man keinen neuen Interpreter bauen. Im
Idealfall generiert man sowieso den Code aus den DBC-Dateien, sodass man
die Definition der Nachricht nur 1x machen muss.
CAN ist sowieso schon langsam, das dann noch mit String-Kodierung noch
weiter auszubremsen... Dann auch noch die Fehlerbehandlung, wenn
einzelne Nachrichten in der Folge fehlen...
Und wenn für CANoe das nötige Kleingeld fehlt: Einfach den selben Code
für den Controller wie für die Analyse auf dem PC nutzen, z.B. eben in
der Form der Deklarationen der µSer-Library. Dann schreibt man es 1x im
Code hin und verwendet ihn für beide Seiten.
Peter D. schrieb:> "Befehl Parametername Wert1 [Wert2] [...]\n"
Das riecht nach dem "Inner Platform Antipattern". CAN hat bereits eine
Nachrichtenkennung ("Befehl"), die ID. Noch eine weitere ID zu
übertragen, die von der Hardware dann auch nicht gefiltert werden kann,
ist redundant. Parameter-Namen ständig erneut zu übertragen frisst
unnötig Bandbreite. CAN ist sowieso nicht Plug-And-Play, man muss
sowieso alle Teilnehmer explizit anpassen oder konfigurieren.
Niklas G. schrieb:> Wenn man eine Nachricht ändert klickt man das> in CANdb++ fix zusammen, da muss man keinen neuen Interpreter bauen.
Das geht bei uns nicht. Der CAN-Bus geht nicht direkt auf den PC,
sondern die Nachrichten werden per Ethernet an den PC übertragen. Daher
ist das Stringformat sehr bequem.
Niklas G. schrieb:> CAN ist sowieso schon langsam, das dann noch mit String-Kodierung noch> weiter auszubremsen...
Das muß man schon dem Anwender überlassen, ob da was bremst. Wir haben
natürlich vorher untersucht, ob das Stringformat für unsere Anwendungen
schnell genug ist und das ist es.
Peter D. schrieb:> Das geht bei uns nicht.
Warum? Dann baut halt einen Interpreter welcher mittels DBC-Dateien das
Binärformat interpretiert, was zuvor per Ethernet verschickt wurde.
Peter D. schrieb:> Wir haben> natürlich vorher untersucht, ob das Stringformat für unsere Anwendungen> schnell genug ist und das ist es.
Okay, aber das ist dann eine Lösung die nur in diesem Spezialfall
funktioniert. Viele Fahrzeuge und Anlagen haben sogar mehrere
CAN-Netzwerke, u.a. weil ein einzelnes nicht genug Bandbreite hat.
CAN-FD wurde auch deshalb erfunden. Für diese Anwendungen sollte man
also lieber eine Binärkodierung verwenden. Natürlich auch, weil
praktisch alle CAN-basierten Systeme auf dem Markt das eben so machen.
Peter D. schrieb:> Gerne werden Strings genommen, da man die in einem Terminal direkt lesen> kann.
Dafür ist CAN aber nicht gedacht. Es kann ja auch passieren das ein
anderer Client eine Nachricht dazwischen funkt und schon ist dein String
futsch. In deinem speziellen Fall mag das evtl. nicht möglich sein aber
das zu verallgemeinern ... hm? Ausserdem geht das ganz schön auf die
Datenübertragungsrate, also bei Zeitkritischen Anwendungen auch eher
nicht geeignet.
Die Jungend von heute ... tztztz. Früher konnten Programmierer noch
programmieren und konnten noch mit Hex und Bin umgehen. ;-)
Martin schrieb:> Die Jungend von heute ...
Nö, im Alter (ü60) will man es schön bequem haben.
Ich schreibe auch keine Windows-Anwendungen. Ein Kollege hat mal das
UDP-Terminal geschrieben und ich benutze es nur, um die CAN-Module
anzusprechen. Ich kann damit an der eigentlichen Steuerung vorbei mit
den Modulen sprechen, d.h. auch im Betrieb. Das funktioniert sogar im
Homeoffice.
>Sender und Empfänger müssen sich nur über die Reihenfolge einig sein:>Lo-Byte oder High-Byte zuerst. In fertiger CAN-Software wird das Intel->und Motorola-Byte-Order genannt.
Auch das wird im DBC File festgelegt, genauso wie die ID Nachrichten,
sowie die Zykluszeiten.
Ich bin der Meinung für dein anliegen empfiehlt es sich das TP-Protokoll
aufzusetzen, falls du mit dem Payload von 8 Byte nicht auskommst.
https://de.wikipedia.org/wiki/ISO_15765-2
Udo schrieb:> Du müsstest allerdings folgendes wissen:> ...> In welcher Byteoder (LSB oder MSB) wird auf dem Bus gesendet?
Was spielt das für eine Rolle?
Hauptsache Sender und Empfänger machen es gleich ;-)
Wolfgang schrieb:> Udo schrieb:>> Du müsstest allerdings folgendes wissen:>> ...>> In welcher Byteoder (LSB oder MSB) wird auf dem Bus gesendet?>> Was spielt das für eine Rolle?> Hauptsache Sender und Empfänger machen es gleich ;-)
Naja, wenn man die beiden entwickelt, sollte man das schon wissen. Wie
soll man sonst sicherstellen, dass sie es gleich machen?