STM32 bxCAN Bit-Timings mit Python berechnen
Als ich einige STM32-Mikrocontroller mit nichtstandardmäßigen Taktraten konfigurieren musste, um die korrekten CAN-Bit-Timings zu verwenden.
Dieses Skript wurde für die STM32F413-Serie geschrieben, sollte aber auf nahezu alle STM32-MCUs mit bxCAN anwendbar sein – jedoch musst du die Details überprüfen, insbesondere von welchem Takt der CAN abgeleitet wird.
Du musst wissen:
- Die Frequenz des Takts, von dem der CAN-Takt abgeleitet wird (
PCLK1in meinem Beispiel:48 MHz) - Deine gewünschte Baudrate:
1 MBaudin meinem Beispiel
Mit einem iterativen Trial-and-Error-Ansatz bestimmen wir die geeigneten Werte für BRP, TS1 und TS2 (dies sind spezifische Bit-Sets im CAN):
#!/usr/bin/env python3
# Konfiguration. Hier ändern
master_clock = 48e6 # PCLK1, oder welcher CLK auch immer CAN abgeleitet ist von
desired_baudrate = 1e6 # 1e6 = 1 MBaud, 500e3 = 500 kBaud
# Registerwerte
brp = 5 # Baud rate prescaler
ts1 = 4 # (Länge von Time Segment 1) - 1
ts2 = 1 # (Länge von Time Segment 2) - 1
# Berechnung. Normalerweise musst du hier nichts ändern.
bs1_segments = ts1 +1
bs2_segments = ts2 + 1
total_segments = 1 + bs1_segments + bs2_segments
bittime = 1. / desired_baudrate
master_time = 1. / master_clock
tq = (brp + 1) * master_time
total_time = total_segments * tq
effective_rate = 1. / total_time
sample_point = 1 - (bs2_segments / total_segments)
# Ergebnisse ausgeben
print(f"Effective Baudrate: {effective_rate:.2f} Baud = {100. * effective_rate / desired_baudrate:.2f} % of desired baudrate")
print(f"Sample point: {100. * sample_point:.2f} %")Wenn du dieses Skript ausführst, siehst du eine Ausgabe wie diese:
Effective Baudrate: 1000000.00 Baud = 100.00 % of desired baudrate
Sample point: 75.00 %Natürlich musst du oben die Master-Taktfrequenz und die gewünschte Baudrate eintragen. Du kannst mit den vorkonfigurierten Werten für BRP, TS1 und TS2 beginnen.
Am Ende solltest du 100% der gewünschten Baudrate und einen Abtastpunkt von 87.5% erreichen (80% bis 90% ist normalerweise in Ordnung, 75% funktioniert möglicherweise nicht mit langen Kabeln. Es könnte ein spezifischer Wert vorgegeben sein durch deinen Kommunikationsstandard, z.B. CANOpen oder J1939).
Ändere die Werte für BRP, TS1 und TS2, führe das Skript erneut aus und beobachte die Ausgabe jedes Mal. Ich empfehle, zuerst BRP zu ändern, bis du nahe kommst, und dann mit diesem Algorithmus anzupassen:
- Wenn deine tatsächliche Baudrate zu langsam ist (d.h. < 100%), verringere
BRP(größerer Schritt) und/oder verringereTS1 + TS2 - Wenn deine tatsächliche Baudrate zu schnell ist (d.h. > 100%), erhöhe
BRP(größerer Schritt) und/oder erhöheTS1 + TS2 - Wenn dein Abtastpunkt-Prozentsatz zu klein ist, erhöhe das Verhältnis von
TS1zuTS2 - Wenn dein Abtastpunkt-Prozentsatz zu groß ist, verringere das Verhältnis von
TS1zuTS2
Beachte, dass es Master-Taktgeschwindigkeiten und Baudraten geben kann, für die es keine ideale Einstellung gibt. Stelle sicher zu überprüfen, ob eine leicht abweichende Baudrate in deiner Anwendung noch in Ordnung ist (normalerweise ist sie es nicht). Wenn nicht, musst du einen Weg finden, eine andere PCLK1-Geschwindigkeit zu verwenden.