上一篇文章介绍 PCAN View 安装与使用 的时候,留下了两个问题,CAN总线比特率该怎么计算?
下图里的这些 Prescaler、tseg1、tseg2、sync Jump Width是什么意思?
CAN2.0协议中定义标称位速率为一理想的发送器在没有重新同步的情况下,每秒发送的位数量,也就是我们说的比特率。位时间标称位时间 = 1 /标称位速率。
一、CAN 位时间(CAN Bit Timing)
1个位时间包含4个功能段,分别是:
- 同步段(SYNC_SEG)
- 传播段(PROP_SEG)
- 相位缓冲段 1(PHASE_SEG1)
- 相位缓冲段 2(PHASE_SEG2)
为了方便与编程,有些时候会把传播段
和相位缓冲段1
合并成一个时间段
。位时间的数值相当于 1/比特率。
相关参数定义如下:
-
Prescaler: 分频。控制器的时钟频率进行分频后会得到CAN的时钟,CAN时钟的一个时间周期就是之前提到的最小时间段tscl,也称作时间份额,代表的是CAN控制器工作时的最小时间单位。
-
SYNC_SEG: 同步段。用于同步总线上各个节点,固定长度为1个tscl。其中应该有一个跳变沿。
-
PROP_SEG: 传播段。用于补偿信号通过网络和节点传播的物理延迟,长度应能保证2倍的信号在总线的延迟,长度为1到8个tscl。
-
PHASE_SEG: 相位缓冲段。用于补偿跳变沿的相位误差,相位缓冲段1的结尾是采样点位置。相位缓冲段1和2长度均为1到8个tscl。
-
sample point: 采样点。为读总线电平并解释各位的值的一个时间点。采样点位于相位缓冲段 1(PHASE_SEG1)之后。
其中:
TSEG1 = PROP_SEG + PHASE_SEG1。
TSEG2 = PHASE_SEG2。
位时间 = SYNC_SEG + TSEG1 + TSEG2,长度为8到25个tscl。
采样点 = (SYNC_SEG + TSEG1)/ 位时间。 -
sync Jump Width: 同步跳转宽度 (SJW) 。定义了在重新同步时可以缩短或延长的最大时钟周期数。因为重新同步时,
相位缓冲段1
会延长或是相位缓冲段2
缩短。同步跳转宽度
取值为1到4,同时必须不大于PHASE_SEG1
的时间份额数。
二、计算公式
同步段,固定长度为1个tscl。
比特率 = 时钟(总线时钟/外设时钟) / (比特率分频器值)*(时间段1 + 时间段2 + 1) // 这里的1是同步段
到此,下图就好理解了。
位时间 = (时间段1 + 时间段2 + 1)
即:
位时间 = (tseg1 + tesg2 + 1)
- 1
- 2
- 3
位时间 = (12+3+1)= 16
比特率 = 时钟(总线时钟/外设时钟) / (比特率分频器值)*(时间段1 + 时间段2 + 1)
即:
比特率 = clock Frequency / (Prescaler)*(tseg1 + tesg2 + 1)
- 1
- 2
- 3
比特率 = (80Mhz)/(10*(12+3+1)) = 500 kbit/s
采样点 = (SYNC_SEG + TSEG1)/ 位时间。
即:
采样点= (1 + tseg1 )/ (tseg1 + tesg2 + 1)
- 1
- 2
- 3
采样点 = (1+ 12)/ (12+3+1) = 81.25%
三、比特率计算工具
第一步:
打开Bit Rate Calculation Tool.exe软件后,选择不同的硬件,主要分为三种:
- CAN bit Rate: 适用基于FPGA 的CAN 控制器硬件,比如 PCAN-miniPCIe。
- CAN FD Bit Rate:适用基于FPGA的 CAN FD控制器硬件,比如 PCANUSB FD、PCANUSB X6、PCI Express FD等等。
- SJA-1000 Bit Rate:适用于独立控制器SJA-1000的硬件,比如:PCANUSB。
第二步
设置目标比特率,以及是否“允许比特率偏差”。
如果选择了 “允许比特率偏差”,就会考虑指定的公差,结果中也会列出近似值。如果不选择,则只列出与给定值相匹配的无公差的比特率。
第三步
选择时钟频率,根据需求选择80Mhz-20Mhz。
可选特定范围的仲裁段采样点Norminal sample point,这个是一个比较实用的功能,因为汽车行业大部分采样点是在70%-87.5%之间。
第四步
可选数据段采样点的范围Data sample point,通常也会使能勾选。
Equal prescaler values表示只列出具有相同预分频器值的名义和数据比特率的结果。保持使能勾选。
第五步
计算结果显示与选择
从计算列表中选择需要的采样点配置,在下方分列具体显示仲裁段和数据段的比特率配置信息。
结果输出:选择某个计算结果后,鼠标右键copy to Clipboard,复制到剪贴板,结果可用于PCAN-Basic API二次开发的初始化设置。
f_clock=80000000,nom_brp=10,nom_tseg1=12,nom_tseg2=3,nom_sjw=3,data_brp=10,data_tseg1=2,data_tseg2=1,data_sjw=1
这个就是上图PCAN View里的配置。
第六步
生成的计算结果可用于PCANVIEW或者PCAN Explorer 6的比特率自定义功能使用。
四、程序验证
既然已经知道怎么计算CAN 总线的比特率了。那就看一下程序中是不是也是这么操作的。
CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_8tq,CAN_BS1_9tq,4,CAN_Mode_LoopBack);//CAN初始化环回模式,比特率500Kbps
//CAN初始化 //tsjw:重新同步跳跃时间单元.范围:CAN_SJW_1tq~ CAN_SJW_4tq //tbs2:时间段2的时间单元. 范围:CAN_BS2_1tq~CAN_BS2_8tq; //tbs1:时间段1的时间单元. 范围:CAN_BS1_1tq ~CAN_BS1_16tq //brp :比特率分频器.范围:1~1024; tq=(brp)*tpclk1 //比特率=Fpclk1/((tsjw+tbs1+tbs2)*brp); //mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式; //Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_8tq,CAN_BS1_9tq,4,CAN_Mode_LoopBack); //则比特率为:36M/((8+9+1)*4)=500Kbps //返回值:0,初始化OK; // 其他,初始化失败; u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode) { GPIO_InitTypeDef GPIO_InitStructure; CAN_InitTypeDef CAN_InitStructure; CAN_FilterInitTypeDef CAN_FilterInitStructure; #if CAN_RX0_INT_ENABLE NVIC_InitTypeDef NVIC_InitStructure; #endif RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PORTA时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟 //Configure CAN pin: TX GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化IO //Configure CAN pin: RX GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化IO //最好先禁止中断 //重新初始化默认值 CAN_DeInit( CAN1 ); CAN_StructInit( &CAN_InitStructure ); //CAN单元设置 CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式 CAN_InitStructure.CAN_ABOM=DISABLE; //软件自动离线管理 CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位) CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送 CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的 CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定 CAN_InitStructure.CAN_Mode= mode; //模式设置: mode:0,普通模式;1,回环模式; //设置比特率 CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq CAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq CAN_InitStructure.CAN_BS2=tbs2; //Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq CAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1 CAN_Init(CAN1, &CAN_InitStructure); //初始化CAN1 CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0 CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //屏蔽位模式 CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位宽 CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; //32位ID CAN_FilterInitStructure.CAN_FilterIdLow=0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000; CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0 CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//激活过滤器0 CAN_FilterInit(&CAN_FilterInitStructure); //滤波器初始化 #if CAN_RX0_INT_ENABLE CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE); //FIFO0消息挂号中断允许. NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); #endif return 0; }
AUV,这之前总结的已经很详细了。 这又总结了一遍,也算加深印象了。