Hallo Ich bin gerade dabei mich in die CAN Schnittstelle einzuarbeiten. Dazu habe ich beim STM32F0 uC das Manual mehrmals gelesen. Irgendwie komme ich nicht drauf, wie das Ganze mit den Identifiern und den Filtern funktionieren soll. Angenommen ich habe 2 Geräte, die gewisse Nachrichten erhalten sollen. Im Manual heisst es ja, dass die Identifier zum einen dazu dienen, die Nachricht zu filtern und gleichzeitig aber die Priorität definieren. Je niedriger der Wert, desto höher die Prio. Wieso habe ich aber im Protokoll ID0-ID10? Für meine 2 Geräte könnte ich doch nun zB die IDs 1 für Gerät 1 und 0 für Gerät 2 definieren. Dazu muss ich mir das CAN receive FIFO mailbox identifier register (CAN_RIxR) ansehen. Klar ist mir, dass ich die Daten direkt aus dem Datenregister herauslese. Die DAtenlänge sofern ich die benötige, lese ich aus den DLC bits. Aber wo genau definiere ich nun welche IDs wirklich durch den Filter kommen und im FIFO abgelegt werden sollen. Mache ich das im FMI[7:0]: Filter match index? Was ich nicht verstehe auch warum das im Receive Frame steht, das müsste doch für die beiden Geräte im Filter fest definiert sein. Ich bitte um Hilfe, ich sehe den Wald vor lauter Bäume nicht mehr.
Markus schrieb: > Aber wo genau definiere ich nun welche IDs wirklich durch den Filter > kommen und im FIFO abgelegt werden sollen. Ich meinte natürlich, wo ich die IDs fest definiere, sodass die entsprechenden Nachrichten entsprechend versehenen IDs durch den Filter kommen.
Hey Markus, ich bin auch gerade dabei, mich damit zu beschäftigen, aber noch weit von deinem Stand entfernt. In einem Post, den ich die Tage gestartet hatte, wurden mir diese Links gegeben. Vieleicht lösen sie dein Problem bzw erklären dein Anliegen. https://www.electronicshub.org/arduino-mcp2515-can-bus-tutorial/ http://media3.ev-tv.me/CAN%20Due2.2%20User%20Manual.pdf http://www.grifo.com/PRESS/DOC/Temic/CAN_TUT.PDF lg
hier mal etwas Beispielcode:
1 | enum eCanFilterMode |
2 | {
|
3 | CF_LISTMODE_FIFO0_STD=0x0, |
4 | CF_LISTMODE_FIFO1_STD=0x1, |
5 | CF_MASKMODE_FIFO0_STD=0x2, |
6 | CF_MASKMODE_FIFO1_STD=0x3, |
7 | CF_LISTMODE_FIFO0_EXT=0x4, |
8 | CF_LISTMODE_FIFO1_EXT=0x5, |
9 | CF_MASKMODE_FIFO0_EXT=0x6, |
10 | CF_MASKMODE_FIFO1_EXT=0x7 |
11 | };
|
12 | |
13 | void Can::SetFilter32(int idx, uint32_t id1, uint32_t id2, eCanFilterMode eMode) |
14 | {
|
15 | uint32_t CAN_msgId1 = 0; |
16 | uint32_t CAN_msgId2 = 0; |
17 | |
18 | if (idx<0 || idx>13) |
19 | return; |
20 | |
21 | // std or ext message
|
22 | if ((eMode & 0b100) == 0) |
23 | { // Standard ID |
24 | CAN_msgId1 |= (uint32_t)(id1 << 21); |
25 | CAN_msgId2 |= (uint32_t)(id2 << 21); |
26 | }
|
27 | else
|
28 | { // Extended ID |
29 | CAN_msgId1 |= (uint32_t)(id1 << 3) | CAN_TI0R_IDE; |
30 | CAN_msgId2 |= (uint32_t)(id2 << 3) | CAN_TI0R_IDE; |
31 | }
|
32 | |
33 | CAN1->FMR |= CAN_FMR_FINIT; // set Initialisation mode for filter banks |
34 | CAN1->FA1R &= ~(uint32_t)(1 << idx); // deactivate filter |
35 | |
36 | // initialize filter
|
37 | CAN1->FS1R |= (uint32_t)(1 << idx); // set 32-bit scale configuration |
38 | // list or mask Mode ?
|
39 | if ((eMode & 0b010) == 0) |
40 | CAN1->FM1R |= (uint32_t)(1 << idx); // set 2 32-bit identifier list mode |
41 | else
|
42 | CAN1->FM1R &= ~((uint32_t)(1 << idx)); // set 2 32-bit identifier mask mode |
43 | |
44 | CAN1->sFilterRegister[idx].FR1 = CAN_msgId1; // 32-bit identifier |
45 | CAN1->sFilterRegister[idx].FR2 = CAN_msgId2; // 32-bit identifier |
46 | |
47 | if ((eMode & 0b001) == 0) |
48 | CAN1->FFA1R &= ~(uint32_t)(1 << idx); // assign filter to FIFO 0 |
49 | else
|
50 | CAN1->FFA1R |= (uint32_t)(1 << idx); // assign filter to FIFO 1 |
51 | |
52 | CAN1->FA1R |= (uint32_t)(1 << idx); // activate filter |
53 | CAN1->FMR &= ~CAN_FMR_FINIT; // reset Initialisation mode for filter banks |
54 | }
|
55 | |
56 | void Can::SetFilter16(int idx, uint32_t id1, uint32_t id2, uint32_t id3, uint32_t id4, eCanFilterMode eMode) |
57 | {
|
58 | uint32_t CAN_msgId1 = 0; |
59 | uint32_t CAN_msgId2 = 0; |
60 | |
61 | if (idx<0 || idx>13) |
62 | return; |
63 | // Setup identifier information
|
64 | // std or ext message
|
65 | if ((eMode & 0b100) == 0) |
66 | { // Standard ID |
67 | CAN_msgId1=(uint32_t)(id1 << 5) | (id2<<21); |
68 | CAN_msgId2=(uint32_t)(id3 << 5) | (id4<<21); |
69 | }
|
70 | else
|
71 | { // Extended ID |
72 | uint32_t r1=(uint32_t)((id1>>13) & 0xffffffe0) | ((id1>>15) & 0x1f) | (1<<3); |
73 | uint32_t r2=(uint32_t)((id2>>13) & 0xffffffe0) | ((id2>>15) & 0x1f) | (1<<3); |
74 | CAN_msgId1=(r2 & 0xffff)<<16 | (r1 & 0xffff); |
75 | |
76 | r1=(uint32_t)((id3>>13) & 0xffffffe0) | ((id3>>15) & 0x1f) | (1<<3); |
77 | r2=(uint32_t)((id4>>13) & 0xffffffe0) | ((id4>>15) & 0x1f) | (1<<3); |
78 | CAN_msgId2=(r2 & 0xffff)<<16 | (r1 & 0xffff); |
79 | }
|
80 | |
81 | CAN1->FMR |= CAN_FMR_FINIT; // set Initialisation mode for filter banks |
82 | CAN1->FA1R &= ~(uint32_t)(1 << idx); // deactivate filter |
83 | |
84 | // initialize filter
|
85 | CAN1->FS1R &= ~(uint32_t)(1 << idx); // set 16-bit scale configuration |
86 | // list or mask Mode ?
|
87 | if ((eMode & 0b010) == 0) |
88 | CAN1->FM1R |= (uint32_t)(1 << idx); |
89 | else
|
90 | CAN1->FM1R &= ~((uint32_t)(1 << idx)); |
91 | |
92 | CAN1->sFilterRegister[idx].FR1 = CAN_msgId1; |
93 | CAN1->sFilterRegister[idx].FR2 = CAN_msgId2; |
94 | |
95 | if ((eMode & 0b001) == 0) |
96 | CAN1->FFA1R &= ~(uint32_t)(1 << idx); // assign filter to FIFO 0 |
97 | else
|
98 | CAN1->FFA1R |= (uint32_t)(1 << idx); // assign filter to FIFO 1 |
99 | CAN1->FA1R |= (uint32_t)(1 << idx); // activate filter |
100 | |
101 | CAN1->FMR &= ~CAN_FMR_FINIT; // reset Initialisation mode for filter banks |
102 | }
|
Ich benutze das dann so:
1 | // Filter odometer? and handgas 0x05242500
|
2 | aCan.SetFilter32(0, 0x05841600, 0x05841600, CF_LISTMODE_FIFO0_EXT); |
3 | |
4 | // alle Msg die vom Akku im g2-Protokoll beantwortet werden muessen
|
5 | aCan.SetFilter32(1, 0x010, 0x051, CF_LISTMODE_FIFO1_STD); |
6 | aCan.SetFilter32(2, 0x048, 0x058, CF_LISTMODE_FIFO1_STD); |
7 | |
8 | // aus der Antwort 008 00 11 die der Motor der Console sendet brauche ich die RPM für den Idle Timer
|
9 | aCan.SetFilter32(3, 0x008, 0x008, CF_LISTMODE_FIFO1_STD); |
10 | |
11 | // Filter for xxx0200? and xxx0300 an Serialnumber
|
12 | aCan.SetFilter32(4, 0x0300, 0xfeff, CF_MASKMODE_FIFO0_EXT); |
13 | |
14 | // change clock from console, toggle light
|
15 | aCan.SetFilter32(5, 0x05282200, 0x05241800, CF_LISTMODE_FIFO0_EXT); |
16 | |
17 | // BIB2 idle msg 05640100 0
|
18 | aCan.SetFilter32(6, 0x05640100, 0x05640100, CF_LISTMODE_FIFO0_EXT); |
19 | |
20 | // RC3 key press and release msg
|
21 | aCan.SetFilter32(7, 0x05240000, 0xffff0000, CF_MASKMODE_FIFO0_EXT); |
Jedes der Filter kann in unterschiedlichen Modes betrieben werden. Entweder 4 einzelene STD-Ids oder jeweils 2 STD-Ids mit Maske. Oder 2 einzelen EXT-Ids oder eine EXT-Id mit Maske. Ausserdem gibt es noch die Unterscheidung auf welches der 2 FIFO's das Filter angewendet wird. Der Code ist Teil einer C++ Klasse, sollte aber auch unter reinen C funktionieren. Bitte nur als Beispiel ansehen. Da die meisten sicher HAL verwenden, erspare ich mir das hier weiter aus zuführen.
D. Z. schrieb: > Hey Markus, ich bin auch gerade dabei, mich damit zu beschäftigen, > aber > noch > weit von deinem Stand entfernt. In einem Post, den ich die Tage > gestartet hatte, wurden mir diese Links gegeben. Vieleicht lösen sie > dein Problem bzw erklären dein Anliegen. > > https://www.electronicshub.org/arduino-mcp2515-can-bus-tutorial/ > http://media3.ev-tv.me/CAN%20Due2.2%20User%20Manual.pdf > http://www.grifo.com/PRESS/DOC/Temic/CAN_TUT.PDF > > lg Danke, aber das ist leider auf Arduino bezogen. Ich habe Verständnisprobleme, wie das nun genau mit den Identifiern und den Daten funktioniert. Es heisst ja, ich könne mehrere Identifier pro Nachricht vergeben. Nur weiss ich nicht, wie das gemeint ist. Ich habe ja eine Datenlänge von 8 Bytes pro Frame. Damit könnte ich nun eine Temperatur, einen Druck und zB eine Geschwindigkeit schicken. Also zB rxMeg.Data[0] = Temperatur; rxMeg.Data[1] = Druck; rxMeg.Data[2] = Geschwindigkeit; Jetzt sollte die zu sendende Nachricht mit einem 9 bit Identifier versehen werden. Ich verwende den Standard Identifier und nutze den DataFrame. Somit ist das Bit IDE=0 und RTR=0. Damit ist mein Ich wähle hier ID = 0. Das entsprechende Register Tx Mailbox fülle ich dann entsprechend dem Bild oben aus. Es gibt sagen wir mal 2 Nodes. Angenommen CanNode0 findet gerade die Msg mit dem Identifier 0 interessant, also lässt der Filter die Nachricht mit dem entsprechenden Identifier durch und speichert sie im FIFO 0 oder 1, je nach dem welcher FIFO gewählt wurde. Dann könnte ich die Nachricht mit CAN_Receive auslesen und wieder den Puffer releasen. So weit so gut. Was ist aber, wenn nun CanNode1 die Nachricht zwar auch interessant findet, aber nur die Temperatur benötigt. CanNode1 müsste demnach aber einen anderen Identifier als 0 haben, weil 0 schon vergeben ist, in diesem Fall dann eben ID=1, sprich der Registerbereich STID[31:21] müsste folgend gesetzt werden -> 000 000 000 01 Dann müsste ich die obige Nachricht mit den 3 Daten aber mit einem zusätzlichen Identifier 1 versehen. Und genau da hört mein Verständnis auf: 1. Wenn ich an beliebige Identifier denke, hätte ich 2^11 Identfizier zu vergeben. 2. Wenn ich aber an mehrere Identifier pro Nachricht denke, was ja laut wikipedia auch möglich sein sollte, müsste ich aber die Postionen im Register 31:21 (Arbitration Field) einzeln ansehen und nicht als eine Zahl. Bei Pkt. 1 kann ich aber keine verschiedenen Identifier vergeben und bei Pkt. 2 kann ich aber keine beliebige Anzahl an Identifier vergeben, sondern maximal 11 gleichzeitig. Ich wäre euch wirklich sehr dankbar, wenn mir jemand das kurz erklären könnte.
Hallo, ich glaube, Du hast da die Wikipedia etwas falsch verstanden. Bei CAN hat jede Nachricht einen Identifier und ein Datenfeld. Ein Gerät kann verschiedene Nachrichten mit (deswegen) verschiedenen Identifiern versenden, Du kannst aber auch in eine Nachricht verschiedene Informationen hineinpacken (bis das Datenfeld voll ist). Das ursprüngliche CAN hatte einen 11 Bit breiten Identifier, es konnten also 2048 verschiedene Nachrichten auf einem physikalischen Bus versendet werden. Da das in manchen Netzwerken zu wenig war, wurde der Identifier in einer späteren Protokollversion auf alternativ 29 Bit erhöht, wobei aber Abwärtskompatibilität gewährleistet wurde, weswegen der Identifier im Protokoll in zwei Hälften (11 und 18 Bit) gesendet wird. In dem Frame werden die (ersten) 11 Bit des Identifiers nun zuerst gesendet. Da jeder CAN-Controller während des Sendens auch gleichzeitig zurückliest, kann er bei einem 1-Bit erkennen, wenn ein anderer Controller gleichzeitig eine 0 sendet (da 0 dominant ist). Tritt nun eine solche Kollision währen der ersten 12 Bit auf (Identifier + Remote send request), so hört der Controller, der eine "1" gesendet, aber eine "0" empfangen hat auf zu senden, weswegen der Controller mit dem "niedrigeren" Identifier gewinnt. Tritt die Kollision später auf, hören beide auf zu senden und erzeugen einen Error-Frame (und versuchen es später dann noch einmal). Durch diese Methode wird eine Priorisierung der Nachrichten möglich, d.h. Nachrichten mit einem niedrigen Identifier haben Vorrang vor Nachrichten mit einem hohen Identifier. Dies führt bei hohen Buslasten dazu, dass wichtige Nachrichten (mit niedrigem Identifier) eher duchkommen. Und zu deinen anderen Fragen: In Deinem Fall mit den drei Messwerten hast Du zwei Möglichkeiten: Entweder Du packst Deine drei Messwerte in eine Nachricht mit der ID 0. Dann müssen alle Controller, die Interesse an einer der drei Messwerte haben die ID 0 empfangen (das Filter entsprechend setzen) und danach entscheiden, ob er nur den einen Messwert verwendet (höhere Belastung beim Empfänger). Oder Du sendest die drei Messwerte in drei verschiedenen Nachrichten (ID0,ID1,ID2), dann kannst Du auf einen der drei Messwerte filtern (hast aber eine höhere Buslast und bei Empfängern die mehr als einen Messwert haben möchten mehr Filter belegt). Daher werden in der Regel Messwerte, die einen logischen Zusammenhang haben, in eine Nachricht gepackt, und alle anderen Geräte, die Interesse an einem der Messwerte haben, empfangen die ganze Nachricht und werten nur die interessanten Datenfelder aus. Schöne Grüße, Martin
Martin L. schrieb: > Hallo, > > Schöne Grüße, > Martin Hallo Martin super, vielen Dank für die schöne Erklärung. Jetzt ist mir dank dir schon Einiges klarer geworden. Darf ich dich nun auch noch fragen, wie das nun konkret ist mit dem identifier register? Wenn ich den standard identifier benutze und nicht den extended. Dann ignoriere ich einfach die EXID Bits im register CAN_TIxR. Aber angenommen ich würde nun doch den extended identifier benutzen. Weshalb werden dann die LSBs of the extended identifier EXID[17:0] und MSBs EXID [28:18] angegeben und nicht gleich die ID, die man möchte. Ich verstehe gerade nicht, warum LSBs und MSBs, wenn es doch nur einen Identifier pro Nachricht gibt und es dadurch nur ein LSB und ein MSB gibt, wenn man schon diese Werte angeben muss.
Markus schrieb: > Wenn ich den standard identifier benutze und nicht den extended. > Dann ignoriere ich einfach die EXID Bits im register CAN_TIxR. Genau. Dann nutzt du nur die Bits 21 bis 31. > Aber angenommen ich würde nun doch den extended identifier benutzen. Dann benutzt du Bit 3 bis 31. > Weshalb werden dann die LSBs of the extended identifier EXID[17:0] und > MSBs EXID [28:18] angegeben und nicht gleich die ID, die man möchte. Vergiss das mit den LSB und MSB. Halte dich einfach an die Bitnummern. Umständlich ist nur dass bei 11-Bit ID diese "left-oriented" innerhalb der 29 reservierten Bits steht und nicht rechts. So muss man für 11 oder 29-Bit-ID unterschiedliche Bitschiebereien durchführen.
Thomas F. schrieb: > Markus schrieb: > Vergiss das mit den LSB und MSB. Halte dich einfach an die Bitnummern. > Umständlich ist nur dass bei 11-Bit ID diese "left-oriented" innerhalb > der 29 reservierten Bits steht und nicht rechts. So muss man für 11 oder > 29-Bit-ID unterschiedliche Bitschiebereien durchführen. Alles klar, danke Thomas
Guten Morgen zusammen Ich bin inzwischen bei den Filtern angelangt und habe wieder etwas gefunden, was ich auf Anhieb nicht verstehe. Es gibt 14 Filterbänke jeweils mit 2 32-Bit Registern (CAN_FxR1 und CAN_FxR2). Nun wird auf der Seite 825 vorgeschlagen folgende Konfigurationen durchzuführen, wie im bild filterbanks angedeutet. Ich habe mir nun schon einige Beispiele angesehen mitunter hier: http://www.diller-technologies.de/stm32_wide.html#can aber irgendwie fehlt mir das Verständnis, warum und wieso die Bits so verschoben werden, wie sie da zu sehen sind (<<3 | 4 etc). Ich möchte für mich vorerst einmal 2 Beispiele so durchführen, sodass ich das Konzept im Bild oben nicht verletze. Damit ist meinem Verständnis sicherlich geholfen. Beispiel 1: Ich möchte nur eine bestimmte Msg mit ID zB 0x0008 filtern Beispiel 2: Ich möchte Msgs IDs im Bereich von 8-32 nutzen Jetzt ist die Frage, wie ich da vorzugehen habe. Wenn es zuerst mein Ziel ist eine bestimmte ID zu filtern (0x0008 Bsp. 1), dann ergeben sich folgende Überlegungen. Es gibt 14 Filterbänke, jeweils mit 32-bit Registern. Da ich ja nur eine 11-bit ID habe reicht bei mir ein 16 bit Filter aus. Ich möchte auch direkt IDs miteinander vergleichen. Daher wähle ich den Filter im identifier list mode und setze den Scaler auf 16 bit. Jetzt habe ich aus den 2 32-bit Registern 4 16-bit Filter im Identifier list mode gemacht. Ich befinde mich nun im Bild unten in der letzten Konfiguration: Four 16-bit Filters - Identifier List Bin ich soweit richtig? Jetzt verstehe ich 1. nicht, was die Zahlen in den Klammern sollen, zb STID[10:3] Wenn ich nämlich in das Register sehe (Rx_mailbox), gebe ich die STID im Register von Bit 21 bis 31 an, EXID von bit 2 bis 20. 2. verstehe ich nicht, ob ich wie ich nun welche Bits zu verschieben habe. Aber dazu muss ich erst einmal Pkt. 1 verstehen.
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.