1.硬件连接
PB8作为CAN_RX,PB9作为CAN_TX,连接一个CAN收发器TJA1051T/3
2. CubeMX里配置CAN
设置连接FDCAN1的参数,使用1个标准过滤器,波特率位500K
使能FDCAN1的中断
3 自动生成代码
3.1 初始化
c
static void MX_FDCAN1_Init(void)
{
/* USER CODE BEGIN FDCAN1_Init 0 */
__HAL_RCC_FDCAN_CLK_ENABLE();
/* USER CODE END FDCAN1_Init 0 */
/* USER CODE BEGIN FDCAN1_Init 1 */
/* USER CODE END FDCAN1_Init 1 */
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV2;
hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan1.Init.AutoRetransmission = DISABLE;
hfdcan1.Init.TransmitPause = DISABLE;
hfdcan1.Init.ProtocolException = DISABLE;
hfdcan1.Init.NominalPrescaler = 2;
hfdcan1.Init.NominalSyncJumpWidth = 1;
hfdcan1.Init.NominalTimeSeg1 = 14;
hfdcan1.Init.NominalTimeSeg2 = 3;
hfdcan1.Init.DataPrescaler = 1;
hfdcan1.Init.DataSyncJumpWidth = 1;
hfdcan1.Init.DataTimeSeg1 = 1;
hfdcan1.Init.DataTimeSeg2 = 1;
hfdcan1.Init.StdFiltersNbr = 1;
hfdcan1.Init.ExtFiltersNbr = 0;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN FDCAN1_Init 2 */
CAN_SetFilter();
HAL_FDCAN_Start(&hfdcan1);
// Activate notifications
HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_TX_FIFO_EMPTY,0);
HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
/* USER CODE END FDCAN1_Init 2 */
}
手工增加:
- FDCAN时钟使能 __HAL_RCC_FDCAN_CLK_ENABLE();
- 过滤器设置 CAN_SetFilter();
- 激活中断信号,发送完成和FIFO0收到新消息
- 启动 HAL_FDCAN_Start(&hfdcan1);
3.2 过滤器设置
c
/* USER CODE BEGIN 4 */
void CAN_SetFilter()
{
FDCAN_FilterTypeDef sFilterConfig;
// 初始化过滤器配置结构
sFilterConfig.IdType=FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex=0;
sFilterConfig.FilterType=FDCAN_FILTER_DUAL;
sFilterConfig.FilterConfig=FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1=0x11;
sFilterConfig.FilterID2=0x22;
if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
{
// 处理错误
Error_Handler();
}
//全局过滤器设置,如果包含上述条件的帧则通过
HAL_FDCAN_ConfigGlobalFilter(&hfdcan1,FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE);
}
- 采用一个标准过滤器,过滤器号:0, 过滤类型FDCAN_FILTER_DUAL,就是把FilterID1和FilterID2当成2个CAN ID,过滤器配置为FDCAN_FILTER_TO_RXFIFO0,即把那两个CANID的消息存入RX FIFO0
- 记得进行全局过滤设置,其函数原型如下:
本例中拒绝不匹配的标准帧,拒绝不匹配的扩展帧,接收过滤后的标准远程帧,接收过滤后的扩展远程帧。
3.3 中断处理
c
void FDCAN1_IT0_IRQHandler(void)
{
/* USER CODE BEGIN FDCAN1_IT0_IRQn 0 */
CAN_Rcv_IR();
/* USER CODE END FDCAN1_IT0_IRQn 0 */
HAL_FDCAN_IRQHandler(&hfdcan1);
/* USER CODE BEGIN FDCAN1_IT0_IRQn 1 */
/* USER CODE END FDCAN1_IT0_IRQn 1 */
}
加入接收中断处理函数:CAN_Rcv_IR();
c
void CAN_Rcv_IR()
{
if (__HAL_FDCAN_GET_FLAG(&hfdcan1, FDCAN_FLAG_RX_FIFO0_NEW_MESSAGE))
{
FDCAN_RxHeaderTypeDef pHeader;
uint8_t pData[64];
// 循环处理新消息
while (HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1,FDCAN_RX_FIFO0 ) > 0)
{
// 从Rx FIFO 0中读取消�?
if(HAL_FDCAN_GetRxMessage(&hfdcan1,FDCAN_RX_FIFO0 ,&pHeader,pData)== HAL_OK)
{
TxData[4]=pHeader.RxTimestamp & 0xFF;
TxData[5]=pHeader.DataLength & 0xFF;
TxData[6]=pHeader.Identifier & 0xFF;
TxData[7]=pData[0];
counter++;
CAN_Send();
}
else
{
// 处理读取消息时的错误
Error_Handler();
}
}
// 清除Rx FIFO 0新消息标志
__HAL_FDCAN_CLEAR_FLAG(&hfdcan1, FDCAN_FLAG_RX_FIFO0_NEW_MESSAGE);
}
}
如果检测到FIFO0新消息标志:FDCAN_FLAG_RX_FIFO0_NEW_MESSAGE
则循环处理FIFO0中的消息