Question
H7 CAN hot-plug problem
void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes)
{
extern FDCAN_HandleTypeDef hfdcan1;
if(hfdcan == &hfdcan1)
{
// printf("tx cplt = %d\n",BufferIndexes);
can_tx_cplt = 1;
}
}
void HAL_FDCAN_ErrorCallback(FDCAN_HandleTypeDef *hfdcan)
{
// 错误处理
//printf("FDCAN Error Callback: ErrorCode=%lu\n", (unsigned long)(hfdcan->ErrorCode));
uint32_t error;
error = HAL_FDCAN_GetError(hfdcan);
if(error == 4)
{
can_init();
}
printf("FDCAN Error = %d\n",error);
}
void can_send_msg(uint32_t id, uint8_t *data)
{
can_send_msg_len(id,data,3);
}
#if 1
void can_send_msg_len(uint32_t id, uint8_t *data,uint8_t len)
{
FDCAN_TxHeaderTypeDef FDCAN_Tx;
static uint32_t can_tx_time_out_count = 0;
extern FDCAN_HandleTypeDef hfdcan1;
uint8_t retry_count = 0;
bool flag = 0;
FDCAN_Tx.TxFrameType = FDCAN_DATA_FRAME;
FDCAN_Tx.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
FDCAN_Tx.MessageMarker = 0x00;
FDCAN_Tx.Identifier = id; // 使用输入的ID
FDCAN_Tx.IdType = FDCAN_STANDARD_ID;
FDCAN_Tx.FDFormat = FDCAN_CLASSIC_CAN;
FDCAN_Tx.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
FDCAN_Tx.DataLength = len;
FDCAN_Tx.BitRateSwitch = FDCAN_BRS_OFF;
can_tx_cplt = 0;
HAL_StatusTypeDef state = HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &FDCAN_Tx, data);
if (state != HAL_OK)
{
#if (CAN_DEBUG_INFO == 1)
typedef struct {
const char *string;
uint32_t error_val;
} CAN_ERROR_TYPE;
const CAN_ERROR_TYPE can_error_string[] = {
{"HAL_FDCAN_ERROR_NONE", ((uint32_t)0x00000000U)},
{"HAL_FDCAN_ERROR_TIMEOUT", ((uint32_t)0x00000001U)},
{"HAL_FDCAN_ERROR_NOT_INITIALIZED",((uint32_t)0x00000002U)},
{"HAL_FDCAN_ERROR_NOT_READY", ((uint32_t)0x00000004U)},
{"HAL_FDCAN_ERROR_NOT_STARTED", ((uint32_t)0x00000008U)},
{"HAL_FDCAN_ERROR_NOT_SUPPORTED", ((uint32_t)0x00000010U)},
{"HAL_FDCAN_ERROR_PARAM", ((uint32_t)0x00000020U)},
{"HAL_FDCAN_ERROR_PENDING", ((uint32_t)0x00000040U)},
{"HAL_FDCAN_ERROR_RAM_ACCESS", ((uint32_t)0x00000080U)},
{"HAL_FDCAN_ERROR_FIFO_EMPTY", ((uint32_t)0x00000100U)},
{"HAL_FDCAN_ERROR_FIFO_FULL", ((uint32_t)0x00000200U)}
};
uint8_t index = 0;
uint32_t error_code = hfdcan1.ErrorCode;
for (int i = 0; i < sizeof(can_error_string) / sizeof(CAN_ERROR_TYPE); i++) {
if (error_code & can_error_string[i].error_val) {
index = i;
break;
}
}
// 重新初始化和启动CAN
printf("重新初始化\n");
__HAL_RCC_FDCAN_FORCE_RESET();
__HAL_RCC_FDCAN_RELEASE_RESET();
can_init();
printf("%s\n", can_error_string[index].string);
printf("can_error_val = 0x%08x\n", error_code);
#endif
}
else
{
uint32_t start_time = HAL_GetTick(); // 获取当前的系统时间
while ((can_tx_cplt == 0) && ((HAL_GetTick() - start_time) < 10)) // 超时 500ms
{
// 等待发送完成
}
uint32_t time = HAL_GetTick() - start_time;
if (time >= 10)
{
printf("CAN[0x%0x] Send Time Out = %d\n", id,time);
can_tx_cplt = 0;
can_init();
}
else
{
//printf("XAN=%d\n",time);
}
// can_tx_cplt = 0;
}
}I am currently testing the hot plug of CAN. When I unplug the external CAN device, I continue to send data, but the transmission fails. When I reconnect the external CAN device, my code will report an error.

void MX_FDCAN1_Init(void)
{
/* USER CODE BEGIN FDCAN1_Init 0 */
/* USER CODE END FDCAN1_Init 0 */
/* USER CODE BEGIN FDCAN1_Init 1 */
/* USER CODE END FDCAN1_Init 1 */
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan1.Init.AutoRetransmission = ENABLE;
hfdcan1.Init.TransmitPause = DISABLE;
hfdcan1.Init.ProtocolException = ENABLE;
hfdcan1.Init.NominalPrescaler = 96;
hfdcan1.Init.NominalSyncJumpWidth = 1;
hfdcan1.Init.NominalTimeSeg1 = 7;
hfdcan1.Init.NominalTimeSeg2 = 2;
hfdcan1.Init.DataPrescaler = 12;
hfdcan1.Init.DataSyncJumpWidth = 2;
hfdcan1.Init.DataTimeSeg1 = 7;
hfdcan1.Init.DataTimeSeg2 = 2;
hfdcan1.Init.MessageRAMOffset = 0;
hfdcan1.Init.StdFiltersNbr = 1;
hfdcan1.Init.ExtFiltersNbr = 0;
hfdcan1.Init.RxFifo0ElmtsNbr = 1;
hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.RxFifo1ElmtsNbr = 0;
hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.RxBuffersNbr = 0;
hfdcan1.Init.RxBufferSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.TxEventsNbr = 0;
hfdcan1.Init.TxBuffersNbr = 0;
hfdcan1.Init.TxFifoQueueElmtsNbr = 1;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_64;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN FDCAN1_Init 2 */
FDCAN_FilterTypeDef sFilterConfig;
/* Configure Rx filter */
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex = 0;
sFilterConfig.FilterType = FDCAN_FILTER_MASK;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1 = 0x500; // 基准ID,最小ID
sFilterConfig.FilterID2 = 0x700; // 掩码为0x3F,匹配0x5A0到0x5B3范围
if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
{
/* Filter configuration Error */
Error_Handler();
}
/* Configure global filter to reject all non-matching frames */
HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_REJECT_REMOTE, FDCAN_REJECT_REMOTE);
HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_TX_COMPLETE , FDCAN_TX_BUFFER0);
if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
{
/* Notification Error */
Error_Handler();
}
/* USER CODE END FDCAN1_Init 2 */
}void can_init(void)
{
// 停止外设
HAL_FDCAN_Stop(&hfdcan1);
// 复位错误状态
hfdcan1.State = HAL_FDCAN_STATE_RESET;
HAL_FDCAN_DeInit(&hfdcan1);
// 重新初始化并启动
HAL_FDCAN_Init(&hfdcan1);
MX_FDCAN1_Init();
HAL_FDCAN_Start(&hfdcan1);
}