# How to calculate STM32 bxCAN bit timings using Python

When I needed to configure some STM32 microcontrollers with nonstandard clock speeds to use the correct CAN bit timings.

While this script has been written for the STM32F413 series, it should be applicable to pretty much all STM32 MCUs with bxCAN - however, you need to check the details, especially from which clock the CAN is derived.

You need to know:

• The frequency of the clock from which the CAN clock is derived (`PCLK1` in my example: `48 MHz`)
• Your desired Baudrate: `1 MBaud` in my example

Using an iterative trial and error approach, we will determine the appropriate values for `BRP`, `TS1` and `TS2` (these are specific sets of bits in the CAN):

``````#!/usr/bin/env python3
# Configuration. Change here
master_clock = 48e6 # PCLK1, or whatever CLK CAN is derived from
desired_baudrate = 1e6 # 1e6 = 1 MBaud, 500e3 = 500 kBaud
# Register values
brp = 5 # Baud rate prescaler
ts1 = 4 # (Length of time segment 1) - 1
ts2 = 1 # (Length of time segment 2) - 1

# Calculation. You usually don't need to change this.
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)

# Print results
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}  %")
``````

When you run this script, you will see an output like this:

``````Effective Baudrate: 1000000.00 Baud = 100.00 % of desired baudrate
Sample point: 75.00  %
``````

Of course you need to fill the master clock frequency and the desired baudrate at the top. You can start with the pre-configured values for `BRP`, `TS1` and `TS2`.

In the end, you should achieve 100% of desired baudrate and a sample point that is `87.5%` (`80%` to `90%` is usually OK, 75% might not work with long cables. There might be a specific value dictated by your comms standard, e.g. `CANOpen` or `J1939`).

Change the values of for `BRP`, `TS1` and `TS2`., re-running the script and observing the output each time. I recommend first changing BRP until you get close and then adjusting using this algorithm:

• If your actual baudrate is too slow (i.e. < 100%), decrease `BRP` (larger step) and/or decrease `TS1 + TS2`
• If your actual baudrate is too fast (i.e. > 100%), increase `BRP` (larger step) and/or increase `TS1 + TS2`
• If your sample point percentage is too small, increase the ratio of `TS1` to `TS2`
• If your sample point percentage is too large, decrease the ratio of `TS1` to `TS2`

Note that there might be master clock speeds and baudrates for which there is no ideal setting. Be sure to check whether a slightly different baudrate is still OK in your application (usually it’s not). If it is not, you need to find a way to use a different PCLK1 speed.