Forum: Mikrocontroller und Digitale Elektronik CAN Baudrate - Erfahrungswerte


von Oliver B. (irq)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

> 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))

von Oliver B. (irq)


Lesenswert?

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...

von (prx) A. K. (prx)


Lesenswert?

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.

von Oliver B. (irq)


Lesenswert?

> 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...

von (prx) A. K. (prx)


Lesenswert?

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.

von Oliver B. (irq)


Lesenswert?

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
Noch kein Account? Hier anmelden.