嵌入式开发--CAN总线参数详解及可变波特率

需求

CAN总线的波特率一般在5K~1M之间,典型值为5K,10K,20K,50K,125K,250K,500K,1M。要求是做一个函数,根据输入值可以调整CAN的波特率,以适配至少满足典型值的波特率。

CAN基本知识

本来不想说这个的,但不说的话后面的东西没法讲。如果已熟悉的同学,请跳过这一段。
这张图中的数字单位是TQ,也就是CAN总线时钟分频后的时间长度。关于分频后面会讲。
TQ是CAN总线的最小时间单位,若干个TQ组成一个数据段,下图中的数字就是TQ的数量。
在这里插入图片描述
那么芯片如何知道这一个TQ是高电平还是低电平呢?是在采样点判断的,在这一时刻如果是高电平就判断为1,低电平则判断为低。
准确的讲是显性电平,还是隐性电平,不过那样又讲麻烦了,简单理解就好。
采样点的位置是可以设置的,下图中TQ总时间是9个时钟节拍,采样点在66.66%,不过建议值是85%,所以下图并不是最优设置。但这个85%吧,可先的范围相当大,从50%到95%问题都不大,所以差不多就好了。我的采样点设置在85%最优点。
另外说一个知识点,在STM32中,将下图合计为2段,PTS+PSB合为Seg1,PSB2为Seg2,SS始终为1,所以一个TQ的时钟节拍为Seg1+Seg2+1,这个后面会讲到。
下图来自正点原子,展示的是一个TQ的宽度,下图中的Tq应为时钟节拍,特此注明
在这里插入图片描述

配置

FDCAN外设的基础时钟为40MHz,也就是说当不分频时,一个时钟节拍为25ns。当一个TQ等于40个节拍时,总线的波特率就是1MHz,达到CAN总线的最高波特率。其他典型的波特率都可以在其基础上分频实现。
在这里插入图片描述

一般来说,将仲裁段与数据段的速率,采样点配置为相同会比较合理。
下面就以STM32H750为例,本配置FDCAN外设。将其配置为标准CAN设备,而不是FDCAN,以便和其他设备兼容。

首先使能FDCAN1和FDCAN2
在这里插入图片描述
在这里插入图片描述

上图是基本参数的设置
Frame Format 帧格式,将其配置为传统模式,这时仲裁段与数据段用相同的波特率。如果配置为FD模式的话,则二者允许不同的波特率。
Mode 工作模式 常规模式,静默模式,环回,静默环回啥的,配置为常规就好了。
Auto Retransmission 自动重传 当发生错误时,会自动重传,根据需要自行决定是否开启。
Transmit Pause 传输暂停,一般设置为禁止,也就是把一帧数据一次性传输完。
Protocol Exception 异常协议的处理,禁止。即不处理异常协议。
Nominal Sync Jump Width 采样点的偏移 2 为什么是2,下文有说明。
Data Prescaler 数据段的时钟分频 1,也就是时钟频率除以1,那么一个节拍就是25ns
Data Time Seg1 数据段的Seg1 31节拍
Data Time Seg2 数据段的Seg2 8节拍


波特率计算
所以数据段的时间长度为1+31+8=40节拍,每个节拍的时间是25ns(前面配置),所以1TQ=25*40=1000ns=1us,总线时钟频率就是1MHz。
采样点的偏移是2,所以采样点在1+31+2=34。 34/40=0.85,所以采样点刚好落在85%处(此处是个人理解,如有误请指正)


Message Ram Offset 接收到的消息在内存中的起始点偏移,设为0,不偏移。
Std Filters Nbr 标准帧过滤器 1
Ext Filters Nbr 扩展帧过滤器 11
Rx Fifo0 Elmts Nbr 接收的Fifo0编号 1
Rx Fifo0 Elmt Size 接收的Fifo0数据长度 8字节
Rx Fifo1 Elmts Nbr 接收的Fifo1编号 11
Rx Fifo1 Elmt Size 接收的Fifo1数据长度 8字节
Rx Buffers Nbr 接收缓冲区编号 1
Rx Buffer Size 接收缓冲区长度 8字节
Tx Events Nbr 发送事件编号 0 不用事件发送,所以这个值无所谓
Tx Buffers Nbr 发送缓冲区编号 11
Tx Fifo Queue Elmts Nbr 发送Fifo队列编号
Tx Fifo Queue Mode 发送模式 Fifo模式,即先入先出
Tx Elmt Size 发送长度 8字节

在这里插入图片描述
Clock Calibration 时钟校准,使用外部晶振时,这个可有可无,因为外部晶振已经很准了。用内部RC晶振才需要用到这个,而且温漂很大,不建议用内部晶振。
Bit Timings Parameters 位时序参数设置 个人理解这是仲裁段的时序设置,与前面保持一致就好。
Nominal Prescaler 分频值1 不分频
Nominal Time Seg1 Seg1的长度,单位是时钟节拍
Nominal Time Seg2 Seg2的长度,单位是时钟节拍
再说一遍,1 + Seg1 + Seg2 的数字乘以时钟节拍,就是1TQ的时间长度=1+31+8=40个时钟节拍。
灰字的25ns就是当前时钟频率下,一个时钟节拍的时间。所以1TQ = 25ns * 40时钟节拍 = 1000ns = 1us,即1MHz波特率。
这里是设置仲裁段的采样点,与前面保持一致。
发灰的文字可以看到你设置的节拍值,位时长,波特率。

在这里插入图片描述
开启中断0

可变波特率

在设置好最高1MHz的波特率后,其他典型波特率如500K就设置分频为2,200K就设置分频为5,125K就设置分频为8,其他以此类推。
分频数就是用1MHz除以你要的波特率(can_rate),再写入这里就行了。
也可以自己写一个函数,来实现,以实现可变的波特率。
在红圈处用表达式代替原来的数字即可。
但是要注意,需要先点击箭头所指的小齿轮,将其修改为No check,否则无法使用表达式。
在这里插入图片描述

CubeMX的Bug

当我添加好表达式之后,却发现CubeMX进入要死机的状态,这在以前是不会的。
强行保存并退出之后,却发现无法再打开该工程文件了。
我用了6.13和最新的6.14版本,均有此问题。
已向ST发邮件报告这个Bug,等ST工程师的回复,后续版本应该能解决这个问题,至少现在不能这样搞。
得自己写一个函数,内容就复制MX_FDCAN1_Init()就好,将相关的2行改成如下
在这里插入图片描述
can_rate就是你的目标波特率

软件编写

添加初始化代码

void FDCAN_Config(void)
{
//--------------------------------------------------------------
//  FDCAN1 初始化
//--------------------------------------------------------------
  FDCAN_FilterTypeDef sFilterConfig;
  
  HAL_FDCAN_ActivateNotification(&hfdcan_out, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
  
  sFilterConfig.IdType = FDCAN_STANDARD_ID;   //  配置为过滤标准帧
  sFilterConfig.FilterIndex = 1;              //  过滤器的索引号
  sFilterConfig.FilterType = FDCAN_FILTER_RANGE;  //  过滤方式为范围,即从FilterID1~FilterID2之间的值
  sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
  sFilterConfig.FilterID1 = 0x0000;
  sFilterConfig.FilterID2 = 0x07ff;           //  标准帧为11位ID,即0x7ff,本例配置为接收所有帧
  if(HAL_FDCAN_ConfigFilter(&hfdcan_out, &sFilterConfig) != HAL_OK)
    Error_Handler();
  
  sFilterConfig.IdType = FDCAN_EXTENDED_ID;   //  配置为过滤扩展帧
  sFilterConfig.FilterIndex = 1;              //  过滤器的索引号
  sFilterConfig.FilterType = FDCAN_FILTER_RANGE_NO_EIDM;  //  过滤方式为范围,即从FilterID1~FilterID2之间的值
  sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
  sFilterConfig.FilterID1 = 0x00000000;
  sFilterConfig.FilterID2 = 0x01ffffff;       //  扩展帧为29位ID,即0x1fffffff,本例配置为接收所有帧
  HAL_FDCAN_ConfigFilter(&hfdcan_out, &sFilterConfig);
  
  outcanTxHeader.Identifier = 0x222;    //FDCAN1,编号为222
  outcanTxHeader.IdType = FDCAN_STANDARD_ID;
  outcanTxHeader.TxFrameType = FDCAN_DATA_FRAME;
  outcanTxHeader.DataLength = FDCAN_DLC_BYTES_8;
  outcanTxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
  outcanTxHeader.BitRateSwitch = FDCAN_BRS_OFF;
  outcanTxHeader.FDFormat = FDCAN_CLASSIC_CAN;
  outcanTxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
  outcanTxHeader.MessageMarker = 0x52;

  HAL_FDCAN_Start(&hfdcan_out);   //fdcan1

中断内添加数据接收

void FDCAN1_IT0_IRQHandler(void)
{
  /* USER CODE BEGIN FDCAN1_IT0_IRQn 0 */

  /* USER CODE END FDCAN1_IT0_IRQn 0 */
  HAL_FDCAN_IRQHandler(&hfdcan1);
  /* USER CODE BEGIN FDCAN1_IT0_IRQn 1 */
  HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, &outcanRxHeader, outcan_rxdata); //数据接收

  /* USER CODE END FDCAN1_IT0_IRQn 1 */
}

数据收发
在这里插入图片描述

码字不易,都看到这里了,点赞收藏一下吧 ^_^

调试上位机Cangaroo

这个软件用起来很方便,个人感觉比Busmaster更方便,主要是他可以集成多个CAN调试器的一体化显示,用Channel栏标识出不同调试器的ID号,这样多个设备联调时,就再也不用开多个窗口了。
Cangaroo也有一个极为不便的麻烦,它不能像Busmaster那样有多条备选的发送消息,只能有一条。如果要发送不同的消息也早要搞死人。
而Busmaster虽然也很强大,但不支持多个设备,即使开多个窗口也没用,目前只能这两个软件混用。

在这里插入图片描述
Cangaroo也有一个毛病,就是字体太小,在我的4K显示器上,字小得几乎看不清。
解决办法是生成一个快捷方式,右击,属性,在兼容性中选择“更高的DPI设置”,按下图操作即可,还不够就调节Windows的缩放。
在这里插入图片描述
操作完成后,界面大了很多,看着很舒服了。

Cangaroo下载地址:https://gitcode.com/gh_mirrors/ca/cangaroo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老李的森林

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值