在 SocketCAN 中,can_bittiming_const
結構體用于表示 CAN 總線的定時參數,包括位率(bitrate)的計算。can_bittiming_const
包含了許多與位率相關的參數,其中一些參數用于計算實際的位率。
下面是一些與位率計算相關的字段:
-
brp
(Baud Rate Prescaler):這是一個分頻因子,用于確定位時間。brp
的值由can_bittiming_const
結構體的成員brp_min
和brp_max
決定。 -
prop_seg
(Propagation Segment):傳播時間段,表示信號在網絡上傳播的時間。 -
phase_seg1
(Phase Buffer Segment 1):相位緩沖段 1,表示位時間的第一個時間段。 -
phase_seg2
(Phase Buffer Segment 2):相位緩沖段 2,表示位時間的第二個時間段。 -
sjw
(Synchronization Jump Width):同步跳變寬度,用于同步。
在 SocketCAN 中,實際的位率(bitrate)可以通過以下公式計算:
其中,
Tbit=Propagation?Segment+Phase?Buffer?Segment?1+Phase?Buffer?Segment?2Tbit=Propagation?Segment+Phase?Buffer?Segment?1+Phase?Buffer?Segment?2
這里是一個簡化的例子,演示了如何使用 can_bittiming_const
結構體計算位率:
#include <linux/can.h>void calculate_bitrate(const struct can_bittiming_const *btc) {double Tbit = btc->prop_seg + btc->phase_seg1 + btc->phase_seg2;double bitrate = 1.0 / (btc->brp * Tbit);printf("Bitrate: %f bps\n", bitrate);
}int main() {struct can_bittiming_const btc;// 初始化 btc 結構體的各個字段// ...calculate_bitrate(&btc);return 0;
}
在實際使用中,你需要根據 CAN 控制器和網絡的具體參數來初始化 can_bittiming_const
結構體,然后使用上述公式計算位率。
因為SocketCAN driver自身架構的原因,我們的driver并不會直接計算通訊速率相關的參數,而是由協議層根據我們driver提供的相關參數(時鐘頻率,TSEG 最大最小值等)的信息,以及APP 需要的baudrate,計算出最終的通訊參數(BRP,TSEG1,TSEG2,SJW)并設置這些標準通訊參數到driver。因此我們無法在driver層進行速率校驗,因為driver看到的就不是baudrate,而是BRP,TSEG1,TSEG2,SJW 這些參數。
另外,如果簡單的從上面的原因分析,貌似我們可以通過調整driver 提供給協議層的相關參數常量的最大/最小值來達成baudrate的限制。是的,我們確實可以通過這種方式來限制baudrate的最大值,但是當我們仔細研究了CAN 協議層關于通訊參數的算法后會發現這種方法得不償失,它會導致在一些通訊頻率上誤差偏大。
CAN 協議層通訊參數計算的算法請參考:
calc_bittiming.c - drivers/net/can/dev/calc_bittiming.c - Linux source code (v6.6.2) - Bootlin