为了掌握如何设置STM8/32 CAN的波特率,首先我们得先了解一下位时间特性。
位时间特性逻辑通过采样来监视串行的CAN总线,并且通过跟帧起始位的边沿进行同步,及通过跟后面的边沿进行重新同步,来调整其采样点。
它的操作可以简单解释为,如下所述把名义上的每位的时间分为3段:
● 同步段(SYNC_SEG):通常期望位的变化发生在该时间段内。其值固定为1个时间单元(1 x tCAN)。
● 时间段1(BS1):定义采样点的位置。它包含CAN标准里的PROP_SEG和PHASE_SEG1。其值可以编程为1到16个时间单元,但也可以被自动延长,以补偿因为网络中不同节点的频率差异所造成的相位的正向漂移。
● 时间段2(BS2):定义发送点的位置。它代表CAN标准里的PHASE_SEG2。其值可以编程为1到8个时间单元,但也可以被自动缩短以补偿相位的负向漂移。
● 重新同步跳跃宽度(SJW):定义了在每位中可以延长或缩短多少个时间单元的上限。其值可以编程为1到4个时间单元。
● 有效跳变:被定义为,当bxCAN自己没有发送隐性位时,从显性位到隐性位的第1次转变。
如果在时间段1(BS1)而不是在同步段(SYNC_SEG)检测到有效跳变,那么BS1的时间就被延长最多SJW那么长,从而采样点被延迟了。相反如果在时间段2(BS2)而不是在SYNC_SEG检测到有效跳变,那么BS2的时间就被缩短最多SJW那么长,从而采样点被提前了。为了避免软件的编程错误,对位时间特性寄存器(CAN_BTR)的设置,只能在bxCAN处于初始化状态下进行。
注: 关于CAN位时间特性和重同步机制的详细信息,请参考ISO11898标准。
简而言之,就是:
CAN波特率=APB1总线频率/(BRP分频器系数*(1+tBS1+tBS2))
该公式用代码中的变量来表示,就是
CAN总线的波特率=PCLK1/((CAN_SJW +CAN_BS1 + CAN_BS2)*CAN_Prescaler)
比如外部晶振为8MHz,使用外部晶振的话,一般PCLK1也就是8MHz,设CAN_SJW=1,CAN_BS1=5,CAN_BS2=4,CAN_Prescaler=1,则设置的波特率即为8000/((1+4+5)*1)kbps=800kbps。
CAN位时间特性寄存器 (CAN_BTR)
地址偏移量: 0x1C 复位值: 0x0123 0000 注: 当CAN处于初始化模式时,该寄存器只能由软件访问。
图2
位31 | SILM: 静默模式(用于调试) 0: 正常状态; 1: 静默模式。 |
位30 | LBKM: 环回模式(用于调试) 0: 禁止环回模式; 1: 允许环回模式。 |
位29:26 | 保留位,硬件强制为0。 |
位25:24 | SJW[1:0]: 重新同步跳跃宽度为了重新同步,该位域定义了CAN硬件在每位中可以延长或缩短多少个时间单元的上限。 tRJW = tCAN x (SJW[1:0] + 1)。 |
位23 | 保留位,硬件强制为0。 |
位22:20 | TS2[2:0]: 时间段2 该位域定义了时间段2占用了多少个时间单元 tBS2 = tCAN x (TS2[2:0] + 1)。 |
位19:16 | TS1[3:0]: 时间段1 该位域定义了时间段1占用了多少个时间单元 tBS1 = tCAN x (TS1[3:0] + 1) |
位15:10 | 保留位,硬件强制其值为0。 |
位9:0 | BRP[9:0]: 波特率分频器该位域定义了时间单元(tq)的时间长度 tq = (BRP[9:0]+1) x tPCLK |
配置波特率是在CAN模块初始化时配置,代码示例如下:
uint8_t CAN_Configuration(uint8_t can_prescaler)
{
CAN_InitTypeDef CAN_InitStructure;
CAN_Filter_Type CAN_Filter_Structure;
CLK_PeripheralClockConfig(CLK_PERIPHERAL_CAN, ENABLE);
CAN_DeInit();
CAN_InitStructure.CAN_MasterCtrl = CAN_MasterCtrl_AllDisabled;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
//CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack;
CAN_InitStructure.CAN_SJW = CAN_SynJumpWidth_1TimeQuantum;//tSJW=1个tCAN时钟周期
CAN_InitStructure.CAN_BS1 = CAN_BitSeg1_5TimeQuantum;//tBS1=5个tCAN时钟周期
CAN_InitStructure.CAN_BS2 = CAN_BitSeg2_4TimeQuantum;//tBS2=4个tCAN时钟周期
CAN_InitStructure.CAN_Prescaler = can_prescaler;
uint8_t ret = CAN_Init_Set(&CAN_InitStructure);//总体配置保持tBS1>=tBS2 tBS2>=1个CAN时钟周期 tBS2>=2tSJW
if(ret == FAIL)
return 1;
CAN_Filter_Structure.FilterNumber = CAN_FilterNumber_0;
CAN_Filter_Structure.FilterActivation = ENABLE;
CAN_Filter_Structure.FilterMode = CAN_FilterMode_IdMask;
CAN_Filter_Structure.FilterScale = CAN_FilterScale_32Bit;
CAN_Filter_Structure.FilterID1=0;
CAN_Filter_Structure.FilterID2=0;
CAN_Filter_Structure.FilterID3=0;
CAN_Filter_Structure.FilterID4=0;
CAN_Filter_Structure.FilterIDMask1=0;
CAN_Filter_Structure.FilterIDMask2=0;
CAN_Filter_Structure.FilterIDMask3=0;
CAN_Filter_Structure.FilterIDMask4=0;
CAN_Filter_Init(&CAN_Filter_Structure);
CAN_ITConfig(CAN_IT_FMP, ENABLE);
return 0;
}
CAN_Configuration(2);
则PCLK1也就是16MHz,CAN_SJW=1,CAN_BS1=5,CAN_BS2=4,CAN_Prescaler=2,则设置的波特率即为16000/((1+4+5)*2)kbps=800kbps。