网易首页 > 网易号 > 正文 申请入驻

CAN总线位定时与同步:深度解析与代码实现

0
分享至


一、位时间的基本概念 1.1 核心时间单位

如您所述,CAN位时间由多个时间份额(Time Quantum, TQ)构成。关键公式:

TQ = BRP × Tclk

其中:

  • Tclk:CAN控制器外设时钟周期(通常来自系统时钟分频)

  • BRP:波特率预分频器值(寄存器值,通常为5~10位宽)

关于BRP+1的说明:不同芯片厂商的实现有差异。例如: STM32的BTR寄存器中 BRP 字段值为0~1023,实际分频 = BRP+1 某些老式独立CAN控制器(如SJA1000)的 BRP 寄存器直接等于分频值 本文后续代码采用实际分频值 = BRP寄存器值 + 1的方式(最通用)。
1.2 位时间的四段结构

一个标准CAN位时间分为四个连续段:

段名称

长度(TQ)

作用

同步段(SS)

1

固定,用于检测边沿

传播段(PROP)

1~8

补偿物理延迟

相位缓冲段1(PBS1)

1~8

采样点前缓冲,可延长

相位缓冲段2(PBS2)

1~8

采样点后缓冲,可缩短

采样点位置 = (SS + PROP + PBS1) / 总TQ数。推荐范围为70%~80%。

总位时间TQ数= 1 + PROP + PBS1 + PBS2,典型值8~25。

二、同步机制深度解析 2.1 硬同步(Hard Synchronization)

  • 触发时机:仅在帧起始(SOF)的隐性→显性跳变沿

  • 动作:接收节点将自己的SS段对齐到这个边沿

  • 调整幅度:无限制(可以大幅移动)

2.2 重同步(Resynchronization)
  • 触发时机:SOF之后的任何隐性→显性跳变沿(需满足跳变沿在PBS1或PBS2内)

  • 动作:通过延长PBS1缩短PBS2来补偿相位误差

  • 限制:调整量不超过SJW(同步跳转宽度)

重同步规则

  • 若边沿发生在PBS1内→ 相位误差e > 0(接收端慢),延长PBS1

  • 若边沿发生在PBS2内→ 相位误差e < 0(接收端快),缩短PBS2

  • 调整量 = min(|e|, SJW)

2.3 为什么SJW取值范围通常为1~4 TQ?(解答您的疑惑)

这是CAN控制器硬件实现的限制,根源在于:

  1. 采样点稳定性要求:SJW过大(如≥5)会导致采样点在位时间内过度漂移,降低噪声容限。

  2. 振荡器容差计算:CAN协议标准(ISO 11898-1)根据最大允许振荡器误差推导出SJW上限为4。公式如下:

    振荡器容差 ≤ SJW / (20 × NBT)
    其中NBT为一个位时间的TQ总数。当SJW=4时,可支持±1.58%的晶振误差(常见晶振为±0.5%~±1.5%)。
  3. 主流控制器事实标准:Bosch CAN 2.0规范建议SJW为1~4,所有主流芯片(STM32、SJA1000、MCP2515)均遵循此范围。

如果您看到某些文献中SJW取值可到8,那通常是指CAN FD(可变速率模式)下的扩展配置,经典CAN仅支持1~4。
三、代码实现示例 3.1 位定时参数计算器(C语言)

以下代码根据目标波特率、时钟频率自动计算BRP和段长度。

#include  

#include
#include

typedef struct {
uint16_t brp; // 波特率分频器 (实际分频 = brp+1)
uint8_t prop_seg; // 传播段长度 (1~8 TQ)
uint8_t pbs1_seg; // 相位缓冲段1 (1~8 TQ)
uint8_t pbs2_seg; // 相位缓冲段2 (1~8 TQ)
uint8_t sjw; // 同步跳转宽度 (1~4 TQ)
uint8_t sample_point_percent; // 采样点百分比
} CAN_BitTiming_TypeDef;

/**
* @brief 计算CAN位定时参数
* @param clk_khz CAN控制器时钟频率 (kHz)
* @param baud_kbps 目标波特率 (kbps)
* @param target_sp 目标采样点百分比 (例如 75 表示75%)
* @param timing 输出参数结构体
* @return 1:成功, 0:失败
*/
uint8_t CAN_ComputeBitTiming(uint32_t clk_khz, uint32_t baud_kbps,
uint8_t target_sp, CAN_BitTiming_TypeDef *timing)
{
uint32_t best_error = 0xFFFFFFFF;
uint8_t best_brp = 0, best_prop = 1, best_pbs1 = 2, best_pbs2 = 1;
uint32_t actual_baud;
int32_t error;
// 总TQ数范围: 8~25
for (uint8_t tq_num = 8; tq_num <= 25; tq_num++)
{
// 计算理论TQ时间 (us)
double tq_us = 1000.0 / (baud_kbps * tq_num);
double clk_t_us = 1.0 / clk_khz;
// 计算所需BRP (取整)
uint16_t brp_calc = (uint16_t)(tq_us / clk_t_us + 0.5) - 1;
if (brp_calc < 0 || brp_calc > 1023) continue;
// 实际波特率
actual_baud = clk_khz * 1000 / ((brp_calc+1) * tq_num);
error = (int32_t)actual_baud - (int32_t)(baud_kbps * 1000);
if (error < 0) error = -error;
// 误差小于0.5%才考虑
if (error * 1000 <= (int32_t)(baud_kbps * 1000 * 5))
{
// 分配段长度: SS=1固定, PROP=1~8, PBS1=1~8, PBS2=1~8
for (uint8_t prop = 1; prop <= 8 && (1+prop+2+1) <= tq_num; prop++)
{
for (uint8_t pbs1 = 1; pbs1 <= 8; pbs1++)
{
uint8_t pbs2 = tq_num - 1 - prop - pbs1;
if (pbs2 < 1 || pbs2 > 8) continue;
if (pbs1 < pbs2) continue; // 要求PBS1 >= PBS2
uint8_t sp = (1 + prop + pbs1) * 100 / tq_num;
if (abs(sp - target_sp) > 5) continue; // 采样点偏差±5%
// 选择最优组合 (优先采样点准确,次选误差小)
uint32_t current_error = abs(sp - target_sp) * 1000 + error;
if (current_error < best_error) {
best_error = current_error;
best_brp = brp_calc;
best_prop = prop;
best_pbs1 = pbs1;
best_pbs2 = pbs2;
}
}
}
}
}
if (best_error == 0xFFFFFFFF) return 0;
timing->brp = best_brp;
timing->prop_seg = best_prop;
timing->pbs1_seg = best_pbs1;
timing->pbs2_seg = best_pbs2;
timing->sjw = (best_pbs1 < 4) ? best_pbs1 : 4; // SJW不超过PBS1和4
timing->sample_point_percent = (1 + best_prop + best_pbs1) * 100 /
(1 + best_prop + best_pbs1 + best_pbs2);
return 1;
}

// 使用示例
int main(void)
{
CAN_BitTiming_TypeDef timing;
// 假设CAN外设时钟40MHz,目标波特率500kbps,采样点75%
if (CAN_ComputeBitTiming(40000, 500, 75, &timing)) {
printf("BRP = %d (实际分频 %d)\n", timing.brp, timing.brp+1);
printf("PROP_SEG = %d TQ\n", timing.prop_seg);
printf("PBS1 = %d TQ\n", timing.pbs1_seg);
printf("PBS2 = %d TQ\n", timing.pbs2_seg);
printf("SJW = %d TQ\n", timing.sjw);
printf("采样点 = %d%%\n", timing.sample_point_percent);
printf("总TQ数 = %d\n", 1+timing.prop_seg+timing.pbs1_seg+timing.pbs2_seg);
} else {
printf("未找到合适的位定时参数\n");
}
return 0;
}
3.2 STM32 HAL库配置示例

#include "stm32f4xx_hal.h"

CAN_HandleTypeDef hcan1;

void CAN1_Config(void)
{
hcan1.Instance = CAN1;
hcan1.Init.Mode = CAN_MODE_NORMAL;
// 手动计算好的参数 (假设APB1=42MHz, 波特率500k, 采样点75%)
// 总TQ=16, BRP=5 (实际分频6), 则TQ=6/42M≈142.86ns, 位时间=16*142.86ns≈2.2857us -> 437.5kbps
// 调整为BRP=4 (分频5), TQ=5/42M≈119ns, 位时间=16*119ns=1.904us -> 525kbps
// 实际更精确的配置:BRP=3(分频4), TQ=4/42M≈95.24ns, 位时间=20*95.24ns=1.9048us -> 525kbps
// 为了500kbps,需要位时间=2us,TQ=100ns,BRP分频=42M*100ns=4.2->取4,BRP=3
// 总TQ=20,SS=1,PROP=7,PBS1=6,PBS2=6,采样点=(1+7+6)/20=70%
hcan1.Init.TimeTriggeredMode = DISABLE;
hcan1.Init.AutoBusOff = DISABLE;
hcan1.Init.AutoWakeUp = DISABLE;
hcan1.Init.AutoRetransmission = ENABLE;
hcan1.Init.ReceiveFifoLocked = DISABLE;
hcan1.Init.TransmitFifoPriority = DISABLE;
// 位定时寄存器 BTR 配置
// STM32的BS1 = PROP + PBS1, BS2 = PBS2, 且BS1/BS2长度=位长-3
// 这里需要根据芯片手册转换
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ; // SJW=1
hcan1.Init.TimeSeg1 = CAN_BS1_13TQ; // 13TQ (包含SS)
hcan1.Init.TimeSeg2 = CAN_BS2_6TQ; // 6TQ
hcan1.Init.Prescaler = 4; // BRP=4 (实际分频=4+1=5)
if (HAL_CAN_Init(&hcan1) != HAL_OK) {
Error_Handler();
}
}
3.3 同步过程模拟(伪代码)

以下演示接收节点如何根据边沿误差调整PBS1/PBS2:

// 接收节点位流处理状态机
typedef enum {
IDLE,
WAITING_SOF,
RECEIVING_BITS
} CAN_RxState;

CAN_RxState rx_state = WAITING_SOF;
int16_t tq_counter = 0; // 当前位内的TQ计数
int16_t phase_error = 0; // 相位误差 (TQ单位)

void CAN_Rx_Tick(void) // 每个TQ调用一次
{
if (detect_falling_edge()) { // 隐性->显性跳变
if (rx_state == WAITING_SOF) {
// 硬同步:直接对齐到SS起点
tq_counter = 0;
rx_state = RECEIVING_BITS;
}
else if (rx_state == RECEIVING_BITS && tq_counter > 0) {
// 重同步:计算相位误差
if (tq_counter < (ss_len + prop_len + pbs1_len)) {
// 边沿在PBS1内 -> 节点慢,需要延长PBS1
phase_error = tq_counter - (ss_len + prop_len);
if (phase_error > sjw) phase_error = sjw;
pbs1_extend = phase_error;
pbs2_shorten = 0;
}
else if (tq_counter < total_tq) {
// 边沿在PBS2内 -> 节点快,需要缩短PBS2
phase_error = (total_tq - tq_counter);
if (phase_error > sjw) phase_error = sjw;
pbs2_shorten = phase_error;
pbs1_extend = 0;
}
}
}
// 采样点判断 (位于PBS1结束时刻)
if (tq_counter == (ss_len + prop_len + pbs1_len - 1 + pbs1_extend)) {
sample_bit(); // 读取总线电平
}
// 位结束,准备下一个位
if (tq_counter >= (total_tq + pbs1_extend - pbs2_shorten - 1)) {
tq_counter = 0;
pbs1_extend = 0;
pbs2_shorten = 0;
} else {
tq_counter++;
}
}
四、总结与最佳实践

参数

推荐值/范围

总TQ数

16~20

平衡同步精度与开销

采样点

70%~80%

经典CAN常用75%

SJW

1~3

晶振精度高时可取1~2

PROP

根据总线长度

每米总线约需5~10ns,转换为TQ

BRP

尽可能小

提高采样分辨率,但注意寄存器范围

同步设计要点

  • 整个网络应采用相同的位定时参数

  • 长总线(>40m)需增加PROP段

  • 高波特率(>500k)应减少总TQ数,提高采样点精度

希望这篇补充了代码实例和SJW深度解析的文章能对您有所帮助。如果您需要特定MCU(如NXP S32K、Infineon AURIX)的寄存器级配置代码,我可以进一步提供。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
仅跑一圈退赛!张雪机车车手德比斯赛车故障,退出匈牙利站比赛

仅跑一圈退赛!张雪机车车手德比斯赛车故障,退出匈牙利站比赛

全景体育V
2026-05-03 20:11:48
没时间了,中方通牒送进东京,断高市后路,日本人流泪向中国道歉

没时间了,中方通牒送进东京,断高市后路,日本人流泪向中国道歉

近史博览
2026-05-03 03:46:47
央视曝光“减肥针”地下交易乱象后,警方摧毁特大制售医美黑针剂犯罪网络,涉案金额1.5亿;有女子打针后送进抢救室,“没有脉搏了”

央视曝光“减肥针”地下交易乱象后,警方摧毁特大制售医美黑针剂犯罪网络,涉案金额1.5亿;有女子打针后送进抢救室,“没有脉搏了”

北青网-北京青年报
2026-05-03 14:57:07
一夜之间大跳水!最低不到2折!网友直呼“2000多元凭空蒸发”

一夜之间大跳水!最低不到2折!网友直呼“2000多元凭空蒸发”

鲁中晨报
2026-05-03 08:34:29
多NBA内部人士暗示戴维斯可能在未出战一场比赛情况下,就被交易

多NBA内部人士暗示戴维斯可能在未出战一场比赛情况下,就被交易

好火子
2026-05-04 01:49:10
太扎心了!“火化不要灰”成热议话题,一组逝者名单多是30岁上下

太扎心了!“火化不要灰”成热议话题,一组逝者名单多是30岁上下

火山詩话
2026-05-03 12:43:57
52岁辛柏青丧妻11个月后被迫再婚,回应字字戳心

52岁辛柏青丧妻11个月后被迫再婚,回应字字戳心

日落于西
2026-05-03 22:18:25
痛心!安徽19岁失联小伙遗体找到,生前邀父吃最后晚餐 细节曝光

痛心!安徽19岁失联小伙遗体找到,生前邀父吃最后晚餐 细节曝光

社会日日鲜
2026-05-03 10:11:16
女抗议者闯入斯诺克世锦赛决赛,高喊:没有人该支付电视许可费

女抗议者闯入斯诺克世锦赛决赛,高喊:没有人该支付电视许可费

懂球帝
2026-05-03 22:59:53
伦敦世乒赛团体赛:中国男团2-3不敌瑞典队小组赛遭遇两连败,王楚钦拿2分赵心童现场观战

伦敦世乒赛团体赛:中国男团2-3不敌瑞典队小组赛遭遇两连败,王楚钦拿2分赵心童现场观战

扬子晚报
2026-05-03 23:06:47
2连败!王楚钦空砍2分!国乒大崩盘,王皓脸色铁青,温瑞博被热议

2连败!王楚钦空砍2分!国乒大崩盘,王皓脸色铁青,温瑞博被热议

大秦壁虎白话体育
2026-05-03 23:42:49
争议!墨菲未能进球,吴宜泽刚准备击球,一女子冲入球场大喊大叫

争议!墨菲未能进球,吴宜泽刚准备击球,一女子冲入球场大喊大叫

风过乡
2026-05-03 21:55:10
张雪回应53号车手遗憾退赛:赛车机械故障,初步排查是发动机机油压力下降

张雪回应53号车手遗憾退赛:赛车机械故障,初步排查是发动机机油压力下降

贝壳财经
2026-05-03 21:28:05
彻底没了,三星电子宣布退出中国市场!

彻底没了,三星电子宣布退出中国市场!

XCiOS俱乐部
2026-05-02 18:53:05
四川弑母案:法学女杀母分尸,指认现场,笑着说“肉好肥哦”

四川弑母案:法学女杀母分尸,指认现场,笑着说“肉好肥哦”

墨策史
2026-05-02 23:01:31
多位业主拒收房,质疑小区车位遭改建,数量“蒸发”约三分之一 相关部门:正推进解决

多位业主拒收房,质疑小区车位遭改建,数量“蒸发”约三分之一 相关部门:正推进解决

红星新闻
2026-05-03 21:03:14
糟了!嫌利润太低,车企集体宣布涨价

糟了!嫌利润太低,车企集体宣布涨价

说财猫
2026-05-03 14:43:38
破“1”!余额宝突发!

破“1”!余额宝突发!

证券时报
2026-05-03 14:52:09
网游圈换了一茬又一茬,唯有这个“异类”,却是越老越能打!

网游圈换了一茬又一茬,唯有这个“异类”,却是越老越能打!

17173游戏网
2026-05-03 01:00:06
赵祥松|14岁“神童”手搓涡喷发动机,一场漏洞百出的包装表演

赵祥松|14岁“神童”手搓涡喷发动机,一场漏洞百出的包装表演

祥松谈
2026-05-02 15:01:46
2026-05-04 03:08:49
新能源自动驾驶 incentive-icons
新能源自动驾驶
专注于半导体行业资讯
968文章数 347关注度
往期回顾 全部

科技要闻

库克罕见"拒答"!苹果正被AI供应链卡脖子

头条要闻

高端小区多位业主拒收房:小区车位数量“蒸发”约1/3

头条要闻

高端小区多位业主拒收房:小区车位数量“蒸发”约1/3

体育要闻

曼联3-2双杀利物浦!提前三轮锁定欧冠资格 梅努制胜

娱乐要闻

黄晓明五一带娃去游乐场 父子幸福同框

财经要闻

后巴菲特时代,首场股东会透露了啥

汽车要闻

同比大涨190% 方程豹4月销量29138台

态度原创

本地
旅游
时尚
手机
公开课

本地新闻

用青花瓷的方式,打开西溪湿地

旅游要闻

五一假期,全国最拥堵10个地方出炉:放眼望去一片黑压压的人头

春天别总傻傻穿一身黑,看看这些日常穿搭,高级舒适又优雅

手机要闻

华为多款新机销售表现曝光,畅享90 Pro Max激活百万台

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版