0
# Bit Timing Configuration
1
2
CAN bit timing calculation and configuration utilities for both CAN 2.0 and CAN FD, supporting various calculation methods including sample point-based timing, register-based configuration, and bitrate-based parameter calculation.
3
4
## Capabilities
5
6
### CAN 2.0 Bit Timing
7
8
Configure bit timing parameters for standard CAN 2.0 communication.
9
10
```python { .api }
11
class BitTiming:
12
def __init__(self, f_clock: int, brp: int, tseg1: int, tseg2: int, sjw: int,
13
nof_samples: int = 1, strict: bool = False):
14
"""
15
Create CAN 2.0 bit timing configuration.
16
17
Parameters:
18
- f_clock: CAN system clock frequency in Hz
19
- brp: Bit rate prescaler (1-1024)
20
- tseg1: Time segment 1 (number of quanta from sync to sampling point)
21
- tseg2: Time segment 2 (number of quanta from sampling point to end)
22
- sjw: Synchronization jump width (1 to min(4, tseg1, tseg2))
23
- nof_samples: Number of samples (1 or 3)
24
- strict: If True, raise exceptions for invalid parameters
25
"""
26
27
@classmethod
28
def from_bitrate_and_segments(cls, f_clock: int, bitrate: int, tseg1: int,
29
tseg2: int, sjw: int, nof_samples: int = 1):
30
"""
31
Create bit timing from bitrate and time segments.
32
33
Parameters:
34
- f_clock: CAN system clock frequency in Hz
35
- bitrate: Desired bit rate in bits per second
36
- tseg1: Time segment 1 in quanta
37
- tseg2: Time segment 2 in quanta
38
- sjw: Synchronization jump width in quanta
39
- nof_samples: Number of samples per bit
40
41
Returns:
42
BitTiming instance with calculated prescaler
43
"""
44
45
@classmethod
46
def from_registers(cls, f_clock: int, btr0: int, btr1: int):
47
"""
48
Create bit timing from BTR register values.
49
50
Parameters:
51
- f_clock: CAN system clock frequency in Hz
52
- btr0: Bus Timing Register 0 value
53
- btr1: Bus Timing Register 1 value
54
55
Returns:
56
BitTiming instance decoded from register values
57
"""
58
59
@classmethod
60
def from_sample_point(cls, f_clock: int, bitrate: int, sample_point: float):
61
"""
62
Calculate bit timing for desired sample point percentage.
63
64
Parameters:
65
- f_clock: CAN system clock frequency in Hz
66
- bitrate: Desired bit rate in bits per second
67
- sample_point: Desired sample point as percentage (e.g., 75.0 for 75%)
68
69
Returns:
70
BitTiming instance with calculated parameters
71
"""
72
```
73
74
### CAN FD Bit Timing
75
76
Configure bit timing for CAN FD with separate arbitration and data phase parameters.
77
78
```python { .api }
79
class BitTimingFd:
80
def __init__(self, f_clock: int, nom_brp: int, nom_tseg1: int, nom_tseg2: int,
81
nom_sjw: int, data_brp: int, data_tseg1: int, data_tseg2: int,
82
data_sjw: int, nom_sam: bool = False):
83
"""
84
Create CAN FD bit timing configuration.
85
86
Parameters:
87
- f_clock: CAN system clock frequency in Hz
88
- nom_brp: Nominal (arbitration) bit rate prescaler
89
- nom_tseg1: Nominal time segment 1
90
- nom_tseg2: Nominal time segment 2
91
- nom_sjw: Nominal synchronization jump width
92
- data_brp: Data phase bit rate prescaler
93
- data_tseg1: Data phase time segment 1
94
- data_tseg2: Data phase time segment 2
95
- data_sjw: Data phase synchronization jump width
96
- nom_sam: Nominal phase sampling (False=1 sample, True=3 samples)
97
"""
98
99
@classmethod
100
def from_bitrates_and_sample_points(cls, f_clock: int, nom_bitrate: int,
101
data_bitrate: int, nom_sample_point: float,
102
data_sample_point: float):
103
"""
104
Calculate CAN FD timing from bitrates and sample points.
105
106
Parameters:
107
- f_clock: System clock frequency in Hz
108
- nom_bitrate: Nominal (arbitration) phase bitrate
109
- data_bitrate: Data phase bitrate
110
- nom_sample_point: Nominal phase sample point percentage
111
- data_sample_point: Data phase sample point percentage
112
113
Returns:
114
BitTimingFd instance with calculated parameters
115
"""
116
```
117
118
### Bit Timing Properties
119
120
Access calculated timing properties and register values.
121
122
```python { .api }
123
# BitTiming properties
124
@property
125
def bitrate(self) -> int:
126
"""Calculated bitrate in bits per second."""
127
128
@property
129
def sample_point(self) -> float:
130
"""Sample point as percentage of bit time."""
131
132
@property
133
def btr0(self) -> int:
134
"""Bus Timing Register 0 value."""
135
136
@property
137
def btr1(self) -> int:
138
"""Bus Timing Register 1 value."""
139
140
@property
141
def tseg(self) -> int:
142
"""Total time segments (tseg1 + tseg2)."""
143
144
# Dictionary-like access
145
def __getitem__(self, key: str):
146
"""Access timing parameters as dictionary keys."""
147
148
def keys(self):
149
"""Get available parameter keys."""
150
151
def values(self):
152
"""Get parameter values."""
153
154
def items(self):
155
"""Get parameter key-value pairs."""
156
```
157
158
## Usage Examples
159
160
### Basic Bit Timing Configuration
161
162
```python
163
import can
164
165
# Create bit timing for 500 kbps with 8 MHz clock
166
timing = can.BitTiming(
167
f_clock=8_000_000, # 8 MHz clock
168
brp=1, # Prescaler = 1
169
tseg1=13, # Time segment 1 = 13 quanta
170
tseg2=2, # Time segment 2 = 2 quanta
171
sjw=1 # SJW = 1 quantum
172
)
173
174
print(f"Configured bitrate: {timing.bitrate} bps")
175
print(f"Sample point: {timing.sample_point:.1f}%")
176
print(f"BTR registers: BTR0=0x{timing.btr0:02X}, BTR1=0x{timing.btr1:02X}")
177
```
178
179
### Calculate from Bitrate and Sample Point
180
181
```python
182
import can
183
184
# Calculate timing for 1 Mbps with 87.5% sample point
185
timing = can.BitTiming.from_sample_point(
186
f_clock=16_000_000, # 16 MHz clock
187
bitrate=1_000_000, # 1 Mbps
188
sample_point=87.5 # 87.5% sample point
189
)
190
191
print(f"Calculated parameters:")
192
print(f" BRP: {timing['brp']}")
193
print(f" TSEG1: {timing['tseg1']}")
194
print(f" TSEG2: {timing['tseg2']}")
195
print(f" SJW: {timing['sjw']}")
196
print(f"Actual bitrate: {timing.bitrate} bps")
197
print(f"Actual sample point: {timing.sample_point:.1f}%")
198
```
199
200
### CAN FD Bit Timing
201
202
```python
203
import can
204
205
# CAN FD with 500 kbps arbitration, 2 Mbps data phase
206
fd_timing = can.BitTimingFd(
207
f_clock=40_000_000, # 40 MHz clock
208
# Nominal (arbitration) phase - 500 kbps
209
nom_brp=5,
210
nom_tseg1=13,
211
nom_tseg2=2,
212
nom_sjw=1,
213
# Data phase - 2 Mbps
214
data_brp=1,
215
data_tseg1=15,
216
data_tseg2=4,
217
data_sjw=1
218
)
219
220
print(f"Arbitration phase: {fd_timing.nom_bitrate} bps")
221
print(f"Data phase: {fd_timing.data_bitrate} bps")
222
print(f"Speed improvement: {fd_timing.data_bitrate / fd_timing.nom_bitrate:.1f}x")
223
```
224
225
### Multiple Standard Bitrates
226
227
```python
228
import can
229
230
# Common CAN bitrates with 8 MHz clock
231
standard_configs = {
232
'125k': can.BitTiming(f_clock=8_000_000, brp=4, tseg1=13, tseg2=2, sjw=1),
233
'250k': can.BitTiming(f_clock=8_000_000, brp=2, tseg1=13, tseg2=2, sjw=1),
234
'500k': can.BitTiming(f_clock=8_000_000, brp=1, tseg1=13, tseg2=2, sjw=1),
235
'1M': can.BitTiming(f_clock=8_000_000, brp=1, tseg1=5, tseg2=2, sjw=1)
236
}
237
238
print("Standard CAN bitrate configurations:")
239
for name, timing in standard_configs.items():
240
print(f"{name:>4}: {timing.bitrate:>7} bps, "
241
f"SP={timing.sample_point:4.1f}%, "
242
f"BTR0=0x{timing.btr0:02X}, BTR1=0x{timing.btr1:02X}")
243
```
244
245
### Bit Timing Validation
246
247
```python
248
import can
249
250
def validate_timing(timing, target_bitrate, tolerance=0.01):
251
"""Validate bit timing against target bitrate."""
252
actual_rate = timing.bitrate
253
error = abs(actual_rate - target_bitrate) / target_bitrate
254
255
print(f"Target: {target_bitrate} bps")
256
print(f"Actual: {actual_rate} bps")
257
print(f"Error: {error * 100:.3f}%")
258
259
if error <= tolerance:
260
print("✓ Timing within tolerance")
261
return True
262
else:
263
print("✗ Timing exceeds tolerance")
264
return False
265
266
# Test different configurations
267
configs_to_test = [
268
(8_000_000, 500_000, {'brp': 1, 'tseg1': 13, 'tseg2': 2, 'sjw': 1}),
269
(10_000_000, 250_000, {'brp': 5, 'tseg1': 6, 'tseg2': 1, 'sjw': 1}),
270
(16_000_000, 1_000_000, {'brp': 1, 'tseg1': 13, 'tseg2': 2, 'sjw': 1})
271
]
272
273
for f_clock, target_rate, params in configs_to_test:
274
print(f"\nTesting {f_clock/1e6:.0f} MHz clock, {target_rate/1000:.0f} kbps:")
275
timing = can.BitTiming(f_clock=f_clock, **params)
276
validate_timing(timing, target_rate)
277
```
278
279
### Using Bit Timing with Bus
280
281
```python
282
import can
283
284
# Calculate optimal timing for hardware
285
timing = can.BitTiming.from_sample_point(
286
f_clock=16_000_000,
287
bitrate=500_000,
288
sample_point=80.0
289
)
290
291
# Use timing parameters with bus (example for socketcan)
292
bus = can.Bus(
293
channel='can0',
294
interface='socketcan',
295
# Note: Most interfaces handle timing automatically
296
# This is conceptual - actual parameter names vary by interface
297
bitrate=timing.bitrate
298
)
299
300
print(f"Bus configured for {timing.bitrate} bps")
301
bus.shutdown()
302
```
303
304
### Register-Based Configuration
305
306
```python
307
import can
308
309
# Create timing from existing BTR register values
310
# (e.g., read from hardware or configuration file)
311
timing_from_regs = can.BitTiming.from_registers(
312
f_clock=8_000_000,
313
btr0=0x00, # BRP-1 in lower 6 bits, SJW-1 in upper 2 bits
314
btr1=0xDE # TSEG1-1 in lower 4 bits, TSEG2-1 in upper 3 bits, SAM in bit 7
315
)
316
317
print(f"Decoded from registers:")
318
print(f" Bitrate: {timing_from_regs.bitrate} bps")
319
print(f" BRP: {timing_from_regs['brp']}")
320
print(f" TSEG1: {timing_from_regs['tseg1']}")
321
print(f" TSEG2: {timing_from_regs['tseg2']}")
322
```
323
324
## Types
325
326
```python { .api }
327
from typing import Union, Dict, Any
328
from collections.abc import Mapping
329
330
class BitTiming(Mapping[str, int]):
331
"""CAN 2.0 bit timing configuration with dictionary-like access."""
332
333
def __init__(self, f_clock: int, brp: int, tseg1: int, tseg2: int,
334
sjw: int, nof_samples: int = 1, strict: bool = False): ...
335
336
# Properties
337
f_clock: int
338
brp: int
339
tseg1: int
340
tseg2: int
341
sjw: int
342
nof_samples: int
343
344
@property
345
def bitrate(self) -> int: ...
346
@property
347
def sample_point(self) -> float: ...
348
@property
349
def btr0(self) -> int: ...
350
@property
351
def btr1(self) -> int: ...
352
353
class BitTimingFd:
354
"""CAN FD bit timing configuration with dual-phase parameters."""
355
356
def __init__(self, f_clock: int, nom_brp: int, nom_tseg1: int,
357
nom_tseg2: int, nom_sjw: int, data_brp: int,
358
data_tseg1: int, data_tseg2: int, data_sjw: int,
359
nom_sam: bool = False): ...
360
361
# Properties for both phases
362
@property
363
def nom_bitrate(self) -> int: ...
364
@property
365
def data_bitrate(self) -> int: ...
366
@property
367
def nom_sample_point(self) -> float: ...
368
@property
369
def data_sample_point(self) -> float: ...
370
```