can的波特率计算: stm32的配置参数 CAN1_Mode_Init(CAN_SJW_1tq, CAN_BS2_6tq, CAN_BS1_7tq, 3, CAN_Mode_Normal);
其中 CAN_SJW_1tq是同步段,习惯上默认配置成1. 可以调节的节拍数. (范围1-4) CAN_BS2_6tq是相位缓冲段2. (范围1-8) CAN_BS1_7tq是传播段+相位缓冲段1. (范围1-16) 3,这里是预分频值. (范围1-1024) 函数原型: /*******************************************************************************
* 函数名称 : CAN1_Mode_Init
* 描述 : can1的初始化,对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/((tbs1+1+tbs2+1+1)*brp);
* mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
* Fpclk1的时钟在初始化的时候设置为42M,如果设置CAN1_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,CAN_Mode_LoopBack);
* 则波特率为:42M/((6+7+1)*6)=500Kbps
* 输出 : 得到的字节数量DataCnt
* 返回 : 0,初始化成功; 其他,初始化失败
*******************************************************************************/
u8 CAN1_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 CAN1_RX0_INT_ENABLE
NVIC_InitTypeDef NVIC_InitStructure;
#endif
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);//使能PORTA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); //使能CAN1时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0| GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //100MHz GPIO_Speed_100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOD, &GPIO_InitStructure); //初始化PA11,PA12
GPIO_PinAFConfig(GPIOD,GPIO_PinSource0,GPIO_AF_CAN1); //GPIOA11复用为CAN1
GPIO_PinAFConfig(GPIOD,GPIO_PinSource1,GPIO_AF_CAN1); //GPIOA12复用为CAN1
CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式
CAN_InitStructure.CAN_ABOM=DISABLE; //软件自动离线管理 ,用于去除故障端点.
CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
CAN_InitStructure.CAN_NART=DISABLE; //禁止报文自动传送, 这里是用来补发的.enable代表不补发
CAN_InitStructure.CAN_RFLM=ENABLE; //接受的报文不锁定,溢出后新的覆盖旧的
CAN_InitStructure.CAN_TXFP=ENABLE; //ENABLE; //ENABLE优先级,优先级,先进入,先发送;不由报文标识符决定
CAN_InitStructure.CAN_Mode= mode; //模式设置
CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq
CAN_InitStructure.CAN_BS1=tbs1; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
CAN_InitStructure.CAN_BS2=tbs2; //Tbs2范围CAN_BS2_1tq ~ CAN_BS2_8tq
CAN_InitStructure.CAN_Prescaler=brp;//分频系数(Fdiv)为brp+1 ,运行频率为APB的Fdiv分之一,即四分之一
CAN_Init(CAN1, &CAN_InitStructure); // 初始化CAN1
CAN1->MCR|=(1<<6); // 通信自动恢复功能.
//配置过滤器0
CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0 0~13
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //掩码模式
//目的所有的ID数据通过
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000; //32位MASK 如果是1则代表掩码处要检查,如果是0,代表不检查.
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; //32位ID
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
//激活过滤器
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0,选择使用哪个fifo
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
CAN_FilterInit(&CAN_FilterInitStructure); //滤波器初始化
// //配置过滤器0
// CAN_FilterInitStructure.CAN_FilterNumber = 14; //过滤器0 0~13
// CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //掩码模式
// //目的所有的ID数据通过
// CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位
// CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000; //32位MASK 如果是1则代表掩码处要检查,如果是0,代表不检查.
// CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
// CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; //32位ID
// CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
// //激活过滤器
// CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0; //过滤器0关联到FIFO0,选择使用哪个fifo
// CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
// CAN_FilterInit(&CAN_FilterInitStructure);
#if CAN1_RX0_INT_ENABLE
CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE); //FIFO0消息挂号中断允许.
NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 主优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
return 0;
}
先按照波特率定义中的各个参数,进行计算: 计算出各个变量. 然后再选出最优的变量组合. 然后再用选好的变量,推算出stm32的寄存器赋值. ![](http://image109.360doc.com/DownloadImg/2023/09/0811/271951674_1_202309081120127.png) 第一个参数: Q,一个位切分成的份数.(范围 3-25 越大越好) BRP是用于将APB的时钟分频到CAN时钟. BRP=APB/(Q*Baudrate) , 根据上面公式 APB,已知=42M Baudrate,已知=1000000Kbps=1M 那么,Q和BRP就可以计算出来. (这里会有很多组满足条件的,然后Q范围限制在3-25,且越大越好,所以选出最优的一组) (最终定下 Q=14 ) (最终定下 BRP=3) 举例: 42M/(14*3)=1000Kbps=1M的波特率 Q的参数就是越大越好. Q就是一个bit,一个位所被分成的节拍数. Q是总的节拍数,要分给各个段. Q=Tss+Tps+Tpbs1+Tpbs2=14 那么1M波特率就是1us传输1位数据. Q等于14,就是把1us分成了14份,每份约0.07142us (次值就是时间节拍Tq). 然后,下面计算Tss,Tps,Tpbs1,Tpbs2各占多少份 第二个参数: Tss 按照习惯,通常占一拍. 即Tss=1 第三个参数: Tps 其物理意义是传播段时间长度. 信号在总线上来回传输所消耗的时间. 设一次单向传输的延时为包括: 1.发送节点从生产信号到把信号发送到总线上,T1. 2.信号在总线上传输的时间T2. 3.接收节点从总线获取信号的时间T3. 因为是来回传输,所以要乘以2. Tps>=2*(T1+T2+T3) 举例: Tps是由设备性能和总线长度决定的.通常总线延时可按5.5ns/米计.单个节点收 发延迟可按75ns计.假如有线长12m,则Tps=2*(12*5.5+75)=141ns.根据上一步的Q值 (想要的波特率和时钟分频得到),计算出节拍时间Tq 这个已知约0.07142us=71.42ns 在上面计算过. Tps=141/71.42=1.974约为2 即Tps=2 第四个参数,第五个参数 Tpbs1,Tpbs2 根据Q值-1-Tps(Tss一般默认为1),就得到Tpbs1和Tpbs2两数之和, Q-Tss-Tps=Tpbs1+Tpbs2 由于上面计算 Q已知=14 Tss已知=1 Tps已知=2 那么Tpbs1和Tpbs2就能计算出来. Tpbs1+Tpbs2=11 然后除以2,就得到了分别的值.如果是奇数则Tpbs2比Tpbs1多1个. Tpbs2=6 Tpbs1=5 至此,上面的所有参数都得到了. 然后,开始根据上面的参数,计算stm32的参数. 根据表格:
![](http://image109.360doc.com/DownloadImg/2023/09/0811/271951674_2_2023090811201238) 1,stm32单片机中的第一个参数:即:CAN_SJW_1tq CAN_SJW_1tq 就是1 2,stm32单片机中的第二个参数:即:CAN_BS2_6tq=6 Tpbs2是stm32单片机中的Ts2; stm32_Ts2=Tpbs2=6 3,stm32单片机中的第三个参数:即:CAN_BS1_7tq=7 Tps和Tpbs1相加构成stm32单片机中的Ts1; stm32_Ts1=Tps+Tpbs1=2+5=7 4,stm32单片机中的第四个参数:3 BRP=3 总结: 其实,CAN的波特率实际是多个参数决定的. 这样更加确定了采样点的位置. ![](http://image109.360doc.com/DownloadImg/2023/09/0811/271951674_1_202309081120127.png) 还可以通过一些软件进行配置波特率
|