Hallo zusammen, ich möchte den CAN-Controller meines STM32 auf 500 kbit/s einstellen. Für 250 kbit/s habe ich es schon geschafft, mit folgenden Werten: CAN_InitStructure.CAN_Prescaler = 6; CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; CAN_InitStructure.CAN_BS1 = CAN_BS1_9tq; // BitSegment 1 CAN_InitStructure.CAN_BS2 = CAN_BS1_2tq; // BitSegment 2 Die Berechnung ist eigentlich im Handbuch auch ganz gut erklärt: CAN_Baudrate = 1 / BitTime BitTime = (1 + CAN_BS1 + CAN_BS2) * TimeQuantum TimeQuantum = CAN_Prescaler * (1 / f_clk) Taktrate f_clk des STM32 ist 72 MHz. Setze ich obige Werte ein erhalte ich BaudRate = 1000 kbit/s. Experimentell ;-) habe ich jedoch herausgefunden, dass ich im CAN-Viewer Messages empfange, wenn ich diesen auf 250 kbit/s stelle. Daher die Annahme, dass obige Konfig für eben diese Baudrate korrekt ist. Auf gut Glück mit dem Prescaler rumspielen hat nicht funktioniert und außerdem möchte ich wissen, wie man es korrekt macht. Mich interessieren folgende Dinge: - Wie wählt man die Zeiten für die beiden BitSegmente? - Was mache ich bei der Berechnung falsch? Falls jemand einen Blick ins Handbuch werfen möchte: Man findet die Berechnung im Reference Manual auf Seite 559. Viele Grüße, Oliver.
> TimeQuantum = CAN_Prescaler * (1 / f_clk)
TimeQuantum = CAN_Prescaler * Tpclk
PCLK entstammt dem APB1, also maximal 36MHz.
Ich kriege 125Kbps mit Fq=2MHz, Tbs1=11q, Tbs2=4q, also Sampling bei
75%. Ob das optimal ist weiss ich auch nicht.
Im Programm sieht das bei mir so aus:
1 | #define CAN_RATE 125000
|
2 | #define CAN_RATEDEF CAN_BTR(F_APB1 / (16 * CAN_RATE), 1, 11, 4)
|
mit
1 | #define CAN_BTR_BRPv(n) (((n) & 0xFF) << 0)
|
2 | #define CAN_BTR_TS1v(n) (((n) & 0x0F) << 16)
|
3 | #define CAN_BTR_TS2v(n) (((n) & 0x07) << 20)
|
4 | #define CAN_BTR_SJWv(n) (((n) & 0x03) << 24)
|
5 | #define CAN_BTR(brp,sjw,ts1,ts2) (CAN_BTR_BRPv(brp-1) | CAN_BTR_TS1v(ts1-1) | CAN_BTR_TS2v(ts2-1) | CAN_BTR_SJWv(sjw-1))
|
Vielen Dank für die Antwort. Ich habe mich etwas weiter eingelesen und glaube jetzt halbwegs zu verstehen, wie man die einzelnen Werte bestimmt. Hilfreich waren dabei folgende Dokumente: - CAN Bit Timing Requirements (Freescale AN1798) - The Configuration of the CAN Bit Timing (http://www.can.bosch.com) Aber: Problem noch nicht gelöst - Erreiche immer noch maximal 250 kBit/s Hier das konkrete Vorgehen zur Bestimmung der Werte an einem Beispiel. Links stehen immer die Annahmen / Gegebenheiten und rechts die Schlussfolgerung. ----- 1) Prescaler
1 | Baudrate := 500 kBit/s => t_Bit = 1 / Baudrate = 2e-6 s |
2 | Number of Time Quanta := 12 => t_TimeQ = t_Bit / TQ = 166,666e-9 s |
3 | CAN Controller Clk = 36 Mhz => T_clk = 27,7777e-9 s |
4 | |
5 | Prescaler = t_TimeQ / T_clk = 6,0 |
Der Trick hierbei ist die geeignete Wahl der Anzahl an Time Quanta eines Bits. Alle anderen Größen sind mehr oder minder vorgegeben. Durch eine geschickte Wahl erreicht man einen exakten Wert für den Prescaler. 2) Bit Segments
1 | Sampling rate = 66,6% => BS_1 = Sampling rate * (Number of Time Quanta - 1) = 7,333 ~ 7 |
2 | => BS_2 = (1 - Sampling rate) * (Number of Time Quanta - 1) = 3,666 ~ 4 |
Die Aufteilung der Bit Segments ist also durch die Sampling rate gegeben. Wodurch diese definiert ist, konnte ich nicht eindeutig herausfinden. Bei CANOpen ist sie z.B. ~85%, bei mir funktioniert nur 2/3 (habe als Gegenstelle am Rechner einen PEAK-USB Adapter von Peak-System). Ein Time Quantum muss man für das Syncronization Segment von der Number of Time Quanta immer abziehen. Ich teile das Bit neben dem Sync Seg. nur in zwei weitere Teile, beim CAN-Controller in den STM32 ist das "Propagation Segment" nämlich in Bit Segment 1 enthalten. Verwendet man einen anderen Controller, muss man dieses ggf. geeignet aufsplitten. Das BS2 bleibt dabei gleich. 3) Syncronization Jump Width Das Kapitel hat sich mir noch nicht ganz erschlossen. Die SJW hängt irgendwie mit der Güte der Oszillatoren und anderen Faktoren zusammen. Kann man in dem Bosch Artikel nachlesen. Bei mir funktioniert SJW=1. ----- Als Ergebnis kann ich festhalten, dass obige Einstellungen - Prescaler = 6 - BS1 = 7 - BS2 = 4 - SJW = 1 funktionieren, allerdings verrückterweise keine 5oo, sondern nur 250 kbit/s Baudrate erzeugen. Evtl. ist die APB1 Clock nur 18Mhz??? Wenn ich den Prescaler auf 12 stelle, habe ich rechnerisch 125 kBit/s und das funktioniert auch. Bei einem Prescaler von 3, was rechnerisch die gewünschten 500 ergibt, erhalte ich jedoch keine Messages. arg Woran kann das noch liegen? Anscheinend hat mein APB1 nur 18 Mhz, sonst würde ein Prescaler von 6 ja zu den 500k führen. Warum kriege ich dann aber bei einem Prescaler von 3 gar keine Messages mehr? Was bewirkt eigentlich APB2? Ich habe mal spaßeshalber die Taktfrequenz des STM32 anhand der system_stm32f10x.c von 72 Mhz auf 36 MHz gesetzt. Ergebnis: Systick ist nur noch halb so schnell (d.h. Taktrate beträgt wirklich die Hälfte), aber Baudrate blieb bei 250 kBit/s. Hätte nicht APB1 auch um die hälfte langsamer werden müssen? -> Baudrate = 125k ? Ich versteh's echt nicht...
Oliver Behr schrieb:
> Ich versteh's echt nicht...
Das ist der Blackbox-Effekt fertig mitgelieferter Funktionen ;-). Man
kommt trotzdem nicht darum herum, zu verstehen was passiert.
APB1 kann maximal 36MHz. Es kann sehr wohl sein, dass die
Taktinitialisierung bei Systemtakt 72MHz genauso wie bei Systemtakt
36MHz gleichermassen 36MHz für APB1 implementiert. Folglich das gleiche
rauskommt.
Es könnte sich also lohnen, diese Funktion mal unter die Lupe zu nehmen
um rauszukriegen, welche Takte wofür abhängig von was konfiguriert
werden.
Was andererseits dazu führt, dass ich so etwas oft gleich selbst
implementiere, denn dann weiss ich wenigstens was abgeht ;-). Aber das
muss jeder für sich entscheiden.
> Es könnte sich also lohnen, diese Funktion mal unter die Lupe zu nehmen > um rauszukriegen, welche Takte wofür abhängig von was konfiguriert > werden. Das war es natürlich, hätte nur etwas weiter nach unten scrollen müssen. Der BUS-Takt von APB1 ist ebenfalls auf 36MHz eingestellt. Ich hatte fälschlicher Weise im Kopf, dass es immer die Hälfte sein müsste. Allerdings hatte ich den Prescaler mit 36MHz für 500 kBit/s berechnet und bekam trotzdem nur 250k. Ich muss auch oben gemachte Behauptungen zur Sampling Rate teilweise revidieren: Es funktionieren auch andere Werte als 66,667% - allerdings nur bei niedrigeren Baudraten. Habe das vorhin mal getestet. Anscheinend ist das Verhalten gutmütiger je langsamer man den Bus fährt. Bei 125k gehen statt 7/4 auch 6/5 und bei 50k sogar 5/6. Ich habe daher auch bei einem Prescaler von 3 (angenommen für die 500k) mit den Werten für die Bit Segments herumgespielt (+/- 1, mehr macht ja keinen Sinn), hat aber nichts gebracht. Vielleicht gehe ich mit der Anzahl der Time Quanta nach oben, um feinere Abstimmungsmöglichkeiten zu haben. Das artet aber schon wieder in Trial & Error aus, mir fehlt da eine vernünftige analytische Vorgehensweise...
Oliver Behr schrieb: > Ich muss auch oben gemachte Behauptungen zur Sampling Rate teilweise > revidieren: Kleine Korrektur, weil du es nun schon zum zweiten Mal so verwendest: Eine Sampling Rate ist etwas anderes. Was du meist ist der Sample Point, also die Stelle im Bitframe, an der der Wert bestimmt wird.
Nach langer Fehlersuche nun endlich des Rätsels Lösung: Die Schaltung verweigerte bei Datenraten > 250kBit/s ihren Dienst, da auf dem Evaluation Board, das ich verwende, der Terminierungswiderstand von 120 Ohm nicht aufgelötet war. Im Schaltplan war dieser aber vorhanden, deswegen ist es mir nur durch Zufall aufgefallen. Ärgerlich. Folgende Settings verwende ich nun für 500kBit/s (in Verbindung mit der STM-Lib):
1 | CAN_InitStructure.CAN_Prescaler = 3; // 6->250k, 12->125k, 30->50k |
2 | CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; |
3 | CAN_InitStructure.CAN_BS1 = CAN_BS1_7tq; |
4 | CAN_InitStructure.CAN_BS2 = CAN_BS2_4tq; |
Ungelöst ist noch das Problem, dass der Prescaler eigentlich um den Faktor falsch ist. Also bei 3 sollte ich eigentlich 1Mbit/s erzielen, empirisch sind es aber nur 500kBit/s, bei 6 sind es 25kBit/s usw. Da würde ich das Problem jetzt beim STM32 suchen. Also entweder in den Libs oder in der Hardware-Doku... Was anderes fällt mir jetzt spontan nicht ein.
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.