讲得比较细的文章但可能有问题自行判定
前言
CAN2.0 协议中数据段波特率和仲裁段波特率默认是一致,因此只需要关注传输波特率即可
CANFD 协议是向下兼容 CAN2.0 的数据通讯,因此实际使用中需要配置
STM32H7 系列支持的标准是 Compliant with CAN protocol version 2.0 part A, B and ISO 11898-1: 2015, -4
协议结构说明
要点一:仲裁段,数据段 速率可以根据自己的需求设定,其中 仲裁段最大 1Mb/s,数据段最大8Mb/s(实际工况基本都是 2Mb/s左右)
要点二:CAN-FD 长度表示如图2,超过8字节内容需要按照规定设置发送长度
模拟 CAN2.0 部分
1. CubeMX 配置
参数说明自行检索即可
其中 FrameFormat 和 Mode 这两个部分按标准模式类型,这种情况下仲裁段和数据段波特率会保持一致,主要配置【Bit Timings Parameters】部分的内容
CAN 时钟频率是 120M
计算公式 120/24/(1+7+2) = 500Kb/s
2. RX 过滤 & FDCAN 启用
c
// 指定ID过滤范例,还有很多模式自行探索
static void can_set_filter(void)
{
FDCAN_FilterTypeDef sFilterConfig;
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex = 0;
sFilterConfig.FilterType = FDCAN_FILTER_DUAL;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1 = CAN_SYNC_TIME_INFO_ID;
sFilterConfig.FilterID2 = CAN_IMU_CTRL_ID;
if(HAL_FDCAN_ConfigFilter(&NOR_CAN, &sFilterConfig) != HAL_OK)
{
Error_Handler();
}
sFilterConfig.FilterIndex = 1;
sFilterConfig.FilterID1 = CAN_IMU_UPDATE;
if(HAL_FDCAN_ConfigFilter(&NOR_CAN, &sFilterConfig) != HAL_OK)
{
Error_Handler();
}
HAL_FDCAN_ConfigGlobalFilter(&NOR_CAN, FDCAN_REJECT, FDCAN_REJECT, DISABLE, DISABLE);
}
// 启用范例
/// 设置过滤函数
can_set_filter();
/// 设置中断使能
///< 断线自动恢复 默认功能
HAL_FDCAN_ActivateNotification(&NOR_CAN, FDCAN_IT_BUS_OFF | FDCAN_IT_RX_FIFO0_NEW_MESSAGE | FDCAN_IT_RX_FIFO0_FULL, 0);
/// 启动 CAN
HAL_FDCAN_Start(&NOR_CAN);
CAN-FD 部分
1. CubeMX 配置 (未启用自动重发)
仲裁段参数名
Nominal Sync Jump With
Nominal Prescaler
Nominal Time Seg1
Nominal Time Seg2
数据段参数名Data Prescalr
Data Sync Jump With
Data Time Seg1
Data Time Seg2
- 收发双方确保这三项一致比较合理,1. 仲裁波特率 2. 数据波特率 3. 采样点比例
- 截图是 120M 时钟,仲裁 500Kb/s 数据段 2Mb/s 采样点 0.8
- Sync Jump With 这个主要是动态调整通讯长度的不能比 Seg1和 Seg2 大一般默认跟最小的一致
计算(数据中的1,实际上是 Sync_Seg 默认就是 1)
波特率计算 时钟/Pre/(1+Seg1+Seg2) 采样点 (1+Seg1) / (1 + Seg1 + Seg2)
仲裁段 120M/24/(1+7+2) = 500Kb/s, 采样点 (1+7) / (1 + 7 + 2) = 0.8 (80%)
数据段 120M/6/(1+7+2) = 2Mb/s 采样点 (1+7)/(1+7+2) = 0.8 (80%)
2. Tx 发送 & FDCAN 启用
// 发送 64 字节
{
static FDCAN_TxHeaderTypeDef Tx_Header;
static uint32_t _id;
va_list args;
va_start(args, size);
_id = va_arg(args, uint32_t);
Tx_Header.Identifier = _id;
Tx_Header.IdType = FDCAN_STANDARD_ID;
Tx_Header.TxFrameType = FDCAN_DATA_FRAME;
Tx_Header.DataLength = FDCAN_DLC_BYTES_64;
Tx_Header.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
Tx_Header.BitRateSwitch = FDCAN_BRS_ON;
Tx_Header.FDFormat = FDCAN_FD_CAN;
Tx_Header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
Tx_Header.MessageMarker = 0;
if (HAL_FDCAN_AddMessageToTxFifoQ(&FDCAN, &Tx_Header, buff) == HAL_OK) {
return;
}
}
3. 是否异常查看寄存器 IR
PEA 仲裁段协议异常
PED 数据段协议异常