STM32配置FDCAN通讯
由于总线上有设备不支持FDCAN,为了保持兼容性,将本机FDCAN配置为传统CAN运行。
CubeMX配置
开启SW调试接口
开启FDCAN2
开启外部时钟
外部晶振为12M,主频480M,FDCAN时钟来自PLL1Q
FDCAN2参数设置,参数设置的说明,在代码中有注释,
在此强调2点:
1 配置为传统CAN模式时要关闭自动重传,原子哥建议,不知为何,有待测试,CAN标准是支持自动重传的。
2 FDCAN支持仲裁段与数据段波特率不同,而传统模式二者相同,所以若配置为传统CAN时(如本例),数据段可以不配,即Data开始的4个参数可以采用默认值
波特率说明: 前面配置的FDCAN时钟频率为20MHz,Seg1+Seg2+1=40,20MHz/40=500KHz,为保持一致性,Data段配置也和仲裁段(Nominal)配成一样了。
开启中断
最后点Generate,生成工程
Keil代码
首先是定义变量
FDCAN_RxHeaderTypeDef RxHeader;
FDCAN_TxHeaderTypeDef TxHeader;
u8 RxData[8];
u8 TxData[8] = {'L', 'a', 'o', 'L', 'i', '1', '2', '3'};
下面这一段是CubeMX生成的CAN配置参数,我做了备注
void MX_FDCAN2_Init(void)
{
/* USER CODE BEGIN FDCAN2_Init 0 */
/* USER CODE END FDCAN2_Init 0 */
/* USER CODE BEGIN FDCAN2_Init 1 */
hfdcan2.Instance = FDCAN2; //用FDCAN2
hfdcan2.Init.FrameFormat = FDCAN_FRAME_CLASSIC; //配置为传统模式
hfdcan2.Init.Mode = FDCAN_MODE_NORMAL; //正常工作状态
hfdcan2.Init.AutoRetransmission = DISABLE; //关闭自动重传, 传统模式下需关闭
hfdcan2.Init.TransmitPause = DISABLE; //关闭传输暂停
hfdcan2.Init.ProtocolException = DISABLE; //关闭协议异常处理
hfdcan2.Init.NominalPrescaler = 1; //仲裁段时钟分频 FDCAN时钟基准为20MHz 传统CAN模式时只设置这一段即可
hfdcan2.Init.NominalSyncJumpWidth = 8; //同步跳转段的宽度 8
//时钟频率20M / (1 + TSG1 + TSG2) = CAN波特率
hfdcan2.Init.NominalTimeSeg1 = 31; //时间段1 31
hfdcan2.Init.NominalTimeSeg2 = 8; //时间段2 8
hfdcan2.Init.DataPrescaler = 1; //数据段时钟分频,若工作于传统模式,不需要设置数据段参数
// 若工作于FDCAN模式,允许数据段与仲裁段波特率不同
hfdcan2.Init.DataSyncJumpWidth = 8; //8
hfdcan2.Init.DataTimeSeg1 = 31; //31
hfdcan2.Init.DataTimeSeg2 = 8; //8
hfdcan2.Init.MessageRAMOffset = 0; //消息偏移
hfdcan2.Init.StdFiltersNbr = 1; //标准帧使用滤波器1
hfdcan2.Init.ExtFiltersNbr = 1; //扩展帧使用滤波器1
hfdcan2.Init.RxFifo0ElmtsNbr = 1; //接收FIFO0的元素编号1
hfdcan2.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8; //接收FIFO0的元素长度8
hfdcan2.Init.RxFifo1ElmtsNbr = 1; //接收FIFO1的元素编号1
hfdcan2.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8; //接收FIFO1的元素长度8
hfdcan2.Init.RxBuffersNbr = 1; //接收缓冲区编号1
hfdcan2.Init.RxBufferSize = FDCAN_DATA_BYTES_8; //接收缓冲区长度
hfdcan2.Init.TxEventsNbr = 2; //发送事件编号
hfdcan2.Init.TxBuffersNbr = 1; //发送缓冲区编号
hfdcan2.Init.TxFifoQueueElmtsNbr = 2; //发送FIFO队列元素编号
hfdcan2.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; //发送模式 先入先出
hfdcan2.Init.TxElmtSize = FDCAN_DATA_BYTES_8; //发送元素长度8
if (HAL_FDCAN_Init(&hfdcan2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN FDCAN2_Init 2 */
/* USER CODE END FDCAN2_Init 2 */
}
CAN滤波器的设置,本函数要自己写,然后放到自己的初始化代码中,在CubeMX生成的初始化代码的后面。
void FDCAN2_Config(void)
{
FDCAN_FilterTypeDef sFilterConfig;
HAL_FDCAN_ActivateNotification(&hfdcan2, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
sFilterConfig.IdType = FDCAN_STANDARD_ID; // 配置为过滤标准帧
sFilterConfig.FilterIndex = 0; // 过滤器的索引号
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(&hfdcan2, &sFilterConfig) != HAL_OK)
Error_Handler();
sFilterConfig.IdType = FDCAN_EXTENDED_ID; // 配置为过滤扩展帧
sFilterConfig.FilterIndex = 0; // 过滤器的索引号
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(&hfdcan2, &sFilterConfig);
TxHeader.Identifier = 0x123;
TxHeader.IdType = FDCAN_STANDARD_ID;
TxHeader.TxFrameType = FDCAN_DATA_FRAME;
TxHeader.DataLength = FDCAN_DLC_BYTES_8;
TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxHeader.MessageMarker = 0x52;
HAL_FDCAN_Start(&hfdcan2);
}
然后是发送代码,这个简单,即每延时200ms,发送一次数据
while (1)
{
HAL_Delay(200);
HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan2, &TxHeader, TxData);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
接收采用中断的方式,在FDCAN2_IT0中断内写入一句
void FDCAN2_IT0_IRQHandler(void)
{
/* USER CODE BEGIN FDCAN2_IT0_IRQn 0 */
/* USER CODE END FDCAN2_IT0_IRQn 0 */
HAL_FDCAN_IRQHandler(&hfdcan2);
/* USER CODE BEGIN FDCAN2_IT0_IRQn 1 */
HAL_FDCAN_GetRxMessage(&hfdcan2, FDCAN_RX_FIFO0, &RxHeader, RxData);
/* USER CODE END FDCAN2_IT0_IRQn 1 */
}
代码验证
打开CAN分析仪的界面,可以看到接收到的数据帧
在CAN分析仪发送数据后,可以在中断内接收到发来的数据
文章来源:https://www.toymoban.com/news/detail-401126.html
完整代码下载
https://download.csdn.net/download/13011803189/85054662文章来源地址https://www.toymoban.com/news/detail-401126.html
到了这里,关于STM32配置FDCAN通讯的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!