2024-05-06 02:58 AM - last edited on 2024-07-05 03:05 AM by SofLit
Hello everyone,
I'm a beginner in the FDCAN field with STM32. I'm trying to establish communication between two custom boards equipped with the same CAN transceiver. The mode is normal FDCAN. Here's the configuration of the FDCAN module for completeness:
static void MX_FDCAN1_Init(void)
{
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1;
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 = 16;
hfdcan1.Init.NominalSyncJumpWidth = 1;
hfdcan1.Init.NominalTimeSeg1 = 2;
hfdcan1.Init.NominalTimeSeg2 = 2;
hfdcan1.Init.DataPrescaler = 1;
hfdcan1.Init.DataSyncJumpWidth = 1;
hfdcan1.Init.DataTimeSeg1 = 1;
hfdcan1.Init.DataTimeSeg2 = 1;
hfdcan1.Init.StdFiltersNbr = 0;
hfdcan1.Init.ExtFiltersNbr = 0;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
}
The subsequent configuration FDCAN_Config is as follows:
static void FDCAN_Config(void)
{
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 = 0x000;
sFilterConfig.FilterID2 = 0x7FF;
if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_ACCEPT_IN_RX_FIFO0, FDCAN_ACCEPT_IN_RX_FIFO0, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
{
Error_Handler();
}
if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
{
Error_Handler();
}
/* Prepare Tx Header */
TxHeader.Identifier = 0x321;
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 = 0;
}
For reception, I need an interrupt mechanism, so it's configured as follows:
void TIM16_FDCAN_IT0_IRQHandler(void)
{
/* USER CODE BEGIN TIM16_FDCAN_IT0_IRQn 0 */
HAL_FDCAN_RxFifo0Callback(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE);
/* USER CODE END TIM16_FDCAN_IT0_IRQn 0 */
HAL_FDCAN_IRQHandler(&hfdcan1);
/* USER CODE BEGIN TIM16_FDCAN_IT0_IRQn 1 */
/* USER CODE END TIM16_FDCAN_IT0_IRQn 1 */
}
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET)
{
/* Retrieve Rx messages from RX FIFO0 */
if (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
{
Error_Handler();
}
}
}
Here there is instead the main of interest:
FDCAN_RxHeaderTypeDef RxHeader;
uint8_t RxData[8];
FDCAN_TxHeaderTypeDef TxHeader;
uint8_t TxData[8];
...
static void MX_FDCAN1_Init(void);
static void FDCAN_Config(void);
...
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_FDCAN1_Init();
...
FDCAN_Config();
...
while (1) {
/* Set the data to be transmitted */
TxData[0] = 0x0A;
TxData[1] = 0x11;
TxData[2] = 0x22;
TxData[3] = 0x33;
TxData[4] = 0x44;
TxData[5] = 0x55;
TxData[6] = 0x66;
TxData[7] = 0x77;
/* Start the Transmission process */
if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData) != HAL_OK)
{
/* Transmission request Error */
Error_Handler();
}
HAL_Delay(5000);
}
}
I uploaded the same code to both boards, but the reception interrupt doesn't trigger on either of them.
Can anyone help me?
Solved! Go to Solution.
2024-07-05 03:13 AM
Hello,
First, you need to use </> button to share your code. (I've already edited your post to follow our recommendations on thread posting).
Second, my first recommendation is to avoid a such parameters for CAN bit timing (low SEG1 and SEG2 values):
hfdcan1.Init.NominalPrescaler = 16;
hfdcan1.Init.NominalTimeSeg1 = 2;
hfdcan1.Init.NominalTimeSeg2 = 2;
--> need to increase as much as possible NominalTimeSeg1 and NominalTimeSeg2 and decrease as much as possible NominalPrescaler with NominalTimeSeg1 =~(75% to 85%)(NominalTimeSeg1 + NominalTimeSeg2).
(75% to 85%) is the sample point position.
My second recommendation and as you didn't provide the ioc file, is to avoid the usage of HSI or any other internal RC clock sources. Use HSE with an external crystal instead.
2024-07-05 03:13 AM
Hello,
First, you need to use </> button to share your code. (I've already edited your post to follow our recommendations on thread posting).
Second, my first recommendation is to avoid a such parameters for CAN bit timing (low SEG1 and SEG2 values):
hfdcan1.Init.NominalPrescaler = 16;
hfdcan1.Init.NominalTimeSeg1 = 2;
hfdcan1.Init.NominalTimeSeg2 = 2;
--> need to increase as much as possible NominalTimeSeg1 and NominalTimeSeg2 and decrease as much as possible NominalPrescaler with NominalTimeSeg1 =~(75% to 85%)(NominalTimeSeg1 + NominalTimeSeg2).
(75% to 85%) is the sample point position.
My second recommendation and as you didn't provide the ioc file, is to avoid the usage of HSI or any other internal RC clock sources. Use HSE with an external crystal instead.