Wie programmiere ich 2 CAN-Knoten so, dass sie kontinuierlich nacheinander senden?

Angenommen, ich habe drei CAN-Knoten: A, B und C. Wir wissen, dass, wenn zwei Knoten gleichzeitig senden, der Knoten mit der geringsten SID den Bus überwiegt und der andere Knoten den Bus an den ersten abgeben muss Knoten. Was ich tun möchte, ist, dass Knoten B und C kontinuierlich nacheinander CAN-Frames an Knoten A senden (z. B. Knoten B -> Knoten A, Knoten C -> Knoten A, Knoten B -> Knoten A). Kann ich B einfach eine niedrigere SID als C zuweisen und einfach das folgende Code-Snippet ausführen?

Knoten B

while(1) sendCANmsg(data, NODE_A, sizeof(data), RTR_OFF);

Knoten C

while(1) sendCANmsg(data, NODE_A, sizeof(data), RTR_OFF);

Innerhalb von sendCANmsg ist hier das Snippet:

TXB0CONbits.TXREQ = 1;  // Request Message Transmission
while (TXB0CONbits.TXREQ); // Wait until message is sent.

Übrigens verwende ich PIC18F25k80, um dies zu implementieren. Ich dachte nur, nachdem Knoten B die Nachricht gesendet hat, wenn Knoten C im Begriff ist, seine Nachricht zu senden. Der Knoten B gewinnt erneut die Busarbitrierung, wodurch dem Knoten C keine Übertragungsmöglichkeit gegeben wird. Also kann ich Abhilfe schaffen, die mir nur einfällt, indem ich eine kleine Verzögerung einfüge wie:

while(1) {
    sendCANmsg(data, NODE_A, sizeof(data), RTR_OFF);
    delay_us(10);
}

Oder liege ich falsch? :)

Antworten (2)

Da diese Methode den Bus nahezu zu 100 % auslastet, gehen wir davon aus, dass diese 3 Knoten die einzigen im Bus sind. Basierend auf Ihrer Verzögerungszeit von 10 µs gehen wir auch davon aus, dass die Busgeschwindigkeit 500 kbps beträgt (dh 5 Bit Verzögerung oder 1 Bit weniger Wartezeit nach der Arbitrierung zwischen Nachrichten).

Ob die Methode funktioniert oder nicht, hängt weitgehend von den Implementierungsdetails Ihres CAN-Treibers ab. Ein zuverlässigerer Weg, dies zu erreichen, wäre, Knoten B und C vor dem Senden darauf warten zu lassen, die Nachricht des jeweils anderen zu lesen (wobei Knoten B zunächst ohne Wartezeit sendet). IE:

  1. Aufwachen
  2. Knoten C wartet auf Nachricht B
  3. Knoten B sendet
  4. Knoten B wartet auf Nachricht C
  5. Knoten C sendet
  6. Knoten C wartet auf Nachricht B
  7. Usw.

Um die Desynchronisation zu berücksichtigen, sollte jede Wartezeit eine Zeitüberschreitung haben, nach der der Knoten sendet, unabhängig davon, ob er die Nachricht des anderen Knotens empfangen hat.

Dadurch wird die Busauslastung ausgeglichen und jeder Controller kann andere Aufgaben erledigen, während er auf die Nachricht wartet (anstatt im Falle eines Arbitrierungsverlusts ständig zu versuchen, zu senden).

Beachten Sie, dass dies eine unkonventionelle Verwendung von CAN ist. Möglicherweise sind Sie mit einem einfacheren Protokoll wie SPI besser bedient (Knoten A müsste B und C abfragen, aber es müsste keine Arbitrierung geben, und alles könnte DMA- und / oder Interrupt-gesteuert sein).

Danke für Ihre Antwort. :) Ich habe gerade festgestellt, dass ich die Akzeptanzfilter nur für diese Implementierung verwenden kann (z. B. erkennen, ob der andere Knoten eine CAN-Nachricht gesendet hat). Allerdings gibt es in PICf25k80 nur 6 Akzeptanzfilter und 2 Akzeptanzmasken. Wenn das CAN-Netzwerk größer wird, irgendwo kleiner als, aber nahe 2^11 - 1, werden die Akzeptanzfilter und Masken ausreichen? Ich würde gerne die herkömmliche Verwendung von CAN hören. :)
Ich bin mir nicht sicher, was Sie meinen, wenn Sie "weniger als, aber nahe 2 ^ 11-1" sagen. Aufgrund der kapazitiven Belastung gibt es eine praktische Grenze für die Anzahl der Knoten, die an einen einzelnen CAN-Bus angeschlossen werden können – normalerweise sind es etwas mehr als 100 Knoten. Eine konventionellere Verwendung von CAN wäre eine ereignisgesteuerte Umgebung (mit Optionen zum Abfragen und einigen seltenen Heartbeat-Nachrichten). Die Idee ist, die Busauslastung so gering wie möglich zu halten, obwohl dies schwieriger wird, wenn mehr Knoten zum Bus hinzugefügt werden. Ihr Szenario ist eher wie ein Getränk aus dem Feuerwehrschlauch, mit kontinuierlichen Maschinengewehraktualisierungen.
Mein Fehler. Ich hätte irgendwo zwischen 0 und 2^11-1 sagen sollen. Da die SID 11 Bit lang ist, denke ich, dass das Limit des CAN-Netzwerks 2 ^ 11-1 ist. Vielen Dank für den Hinweis. Ich möchte nur wissen, was passiert, wenn es kontinuierlich feuern würde. Meine wirkliche Implementierung ist, dass ich 6 Knoten habe, aber nur ein Knoten die Daten von den anderen 5 Knoten sammelt. Mein Plan ist also, die anderen 5 Knoten alle n Millisekunden nacheinander an den Collector-Knoten zu senden. Was denken Sie? Ist RTR die bessere Wahl?
Die Frage ist wirklich, ob Sie so häufig Updates benötigen. In dem Fall, in dem der "Master" (datensammelnder Knoten) nur sporadische Aktualisierungen benötigt und eine kleine Verzögerung akzeptabel ist, ist RTR sinnvoll. Wenn der Master sofortigen Zugriff auf den aktuellen Wert benötigt, sich die Werte jedoch nur langsam ändern, könnten die anderen Knoten bei jeder Änderung einfach Nachrichten abfeuern. Wenn sich die Werte schnell genug ändern, erhöhen sie die Busauslastung, und es kann sinnvoll sein, sie im Round-Robin-Stil senden zu lassen, wie Sie vorgeschlagen haben. Beachten Sie nur, dass Round-Robin nicht das Szenario ist, für das CAN entwickelt wurde.
Es macht jetzt absolut Sinn. Ich habe vergessen, dass jeder Knoten unterschiedliche Prozesse hat, bevor er seine Daten an den Collector-Knoten überträgt. Es ist sinnvoll, nur bei einer Änderung zu senden. Danke mein Herr :)

Erstens haben Knoten keine IDs, Nachrichten schon.

Das ist knifflig und ist nicht das, wofür CAN entwickelt wurde. Es sollte funktionieren, wenn jeder Knoten nach jeder erfolgreichen Übertragung absichtlich ein wenig verzögert. Ich kann mich nicht erinnern, ob die PIC 18F25K80-Hardware Sie wissen lässt, wann ein Frame tatsächlich gesendet wird, aber wahrscheinlich tut es das. Der andere Knoten benötigt nur ein kurzes Fenster, um das Ende des Rahmens zu sehen und mit der Übertragung zu beginnen. Sobald dieser zweite Knoten mit der Übertragung beginnt, verzögert der erste seine Nachricht sowieso automatisch bis zum nächsten Frame-Ende.

Dies klingt jedoch nach einem Missbrauch des CAN-Busses, und eine bessere Antwort könnte ein Überdenken der Gesamtarchitektur sein.

Danke für Ihre Antwort. Ich stehe korrigiert. Ich habe einen Fehler gemacht, als ich feststellte, dass Knoten IDs haben. Das tut mir leid. Wie auch immer, was wäre diese Architektur? :)
Übrigens, in Bezug auf das, was Sie gesagt haben, dass es funktionieren sollte, wenn jeder Knoten nach jeder erfolgreichen Übertragung absichtlich ein wenig verzögert, und sobald dieser zweite Knoten mit der Übertragung beginnt, verzögert der erste seine Nachricht sowieso automatisch bis zum nächsten Frame-Ende. Bedeutet dies, dass es funktionieren würde, wenn ich nur eine kleine Verzögerung in Knoten B einfügen würde, da Knoten B nach dem Senden der CAN-Nachricht von Knoten C sowieso die Schlichtung gewinnen wird?
@Xegara: Ja, Sie müssen nicht zögern, wenn Sie versuchen, die Nachricht mit der niedrigsten Priorität zu senden.
Oh schön. Sie haben erwähnt, dass diese Art der Implementierung nicht für CAN entwickelt wurde. Ich würde gerne mehr über die richtige Implementierung von CAN erfahren. Wo soll ich anfangen? :)
CAN ist gut für eine Reihe von Knoten ausgelegt, von denen jeder relativ geringe Anforderungen an die Bandbreite (im Vergleich zu Ethernet beispielsweise) hat. Viele Nachrichten können herumfliegen, und jeder Knoten hört nur auf das, was ihn interessiert. Sie scheinen einen Controller und zwei dedizierte Datenknoten zu haben. Dies könnte besser mit etwas wie SPI bedient werden, bei dem der Master direkt steuert, wann jeder Knoten Daten sendet. Warum denken Sie, dass CAN für Ihren Fall geeignet ist?
Ich habe nur ein Szenario zitiert, um auf meine Frage einzugehen. Meine wirkliche Implementierung ist, dass ich 6 Knoten habe, aber nur ein Knoten die Daten von den anderen 5 Knoten sammelt. Mein Plan ist also, die anderen 5 Knoten alle n Millisekunden nacheinander an den Collector-Knoten zu senden. Das Merkmal von CAN ist auch, dass ich einfach einen weiteren Knoten hinzufügen kann, ohne das CAN der anderen Knoten neu zu programmieren, was es sehr flexibel macht. Was denken Sie?