英文:
FDCAN problems on STM32G4
问题
我正在为STM32G474处理器使用STM32G474E-EVAL1板开发新项目,但FDCAN存在问题。我有两个问题:
-
我配置了FDCAN并使用函数HAL_FDCAN_AddMessageToTxFifoQ,但队列很快就填满了,没有CAN传输发生。我已经验证了物理连接和电缆终端。
-
我设置了一个接受所有传入消息并将其发送到RX FIFO 0的接收过滤器,并使用HAL_FDCAN_ActivateNotification使用参数FDCAN_IT_RX_FIFO0_NEW_MESSAGE激活通知,但当从主机发送消息时,我从未收到CAN中断。我正在使用CAN分析仪来验证消息是否已发送。
我正在使用125Kbps的经典CAN。
这是由STM32CubeMX生成的代码和我设置的过滤器:
/**
* @brief FDCAN1 Initialization Function
* @param None
* @retval None
*/
static 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;
// ...
}
我随后调用以下函数:
void canfestival_CAN_Initialize(CO_Data* can_handle)
{
// ...
}
问题1:我使用函数HAL_FDCAN_AddMessageToTxFifoQ,但队列很快就填满了,没有CAN传输发生。
void canxmit_Task(void)
{
// ...
}
从调试中我看到HAL_FDCAN_AddMessageTxFifoQ被调用了3次,之后FDCAN_TXFQS_TFQF位被永久设置。我在CAN总线上没有看到任何输出。
问题2:当主机发送消息时,我从未收到CAN中断。
即使主机发送CAN数据,函数void FDCAN1_IT0_IRQHandler(void)也从未被调用。
我将代码加载到STM32G474E-EVAL1板上,连接了正确终端的CAN电缆到主机,连接了带有PCAN-View软件的PEAK PCAN-USB分析仪,然后上电。我从代码中看不到任何CAN活动,3级的发送队列填满,并且我从未收到任何CAN中断。
英文:
I am developing a new project for the STM32G474 processor using the STM32G474E-EVAL1 board but am having a problem with FDCAN. I have two issues:
-
I configure FDCAN and use the function HAL_FDCAN_AddMessageToTxFifoQ but the queue quickly fills up and no CAN transmission takes place. I have verified the physical connection and cable termination.
-
I set up a receive filter to accept all incoming messages and send them to RX FIFO 0, and I activate notifications with HAL_FDCAN_ActivateNotification using the argument FDCAN_IT_RX_FIFO0_NEW_MESSAGE, but I never get a CAN interrupt when messages are sent from the host. I am using a CAN analyzer to verify that the messages are sent.
I am using Classic CAN at 125Kbps.
Here is the STM32CubeMX generated code and the filter I set up:
/**
* @brief FDCAN1 Initialization Function
* @param None
* @retval None
*/
static 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.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 = 160;
hfdcan1.Init.NominalSyncJumpWidth = 1;
hfdcan1.Init.NominalTimeSeg1 = 2;
hfdcan1.Init.NominalTimeSeg2 = 2;
hfdcan1.Init.DataPrescaler = 1;
hfdcan1.Init.DataSyncJumpWidth = 16;
hfdcan1.Init.DataTimeSeg1 = 15;
hfdcan1.Init.DataTimeSeg2 = 5;
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 */
// Set up filters
FDCAN_FilterTypeDef sFilterConfig;
sFilterConfig.IdType = FDCAN_STANDARD_ID; // vs. Extended ID
sFilterConfig.FilterIndex = 0; // the number of the filter we are using
sFilterConfig.FilterType = FDCAN_FILTER_MASK;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; // what to do filter match
sFilterConfig.FilterID1 = 0; // filter
sFilterConfig.FilterID2 = 0; // mask: 0=>accept all messages
if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
{
// Filter configuration error
Error_Handler();
}
// There will be no remote messages
if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT,
FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
{
Error_Handler();
}
/* USER CODE END FDCAN1_Init 2 */
}
I subsequently call the following functions:
void canfestival_CAN_Initialize(CO_Data* can_handle)
{
// Set up the transmit header
TxHeader.IdType = FDCAN_STANDARD_ID;
TxHeader.TxFrameType = FDCAN_DATA_FRAME;
TxHeader.DataLength = FDCAN_DLC_BYTES_8;
TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; // Error State Indicator for Tx errors
TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxHeader.MessageMarker = 0;
// Start CAN timer for use by CANfestival
if (HAL_TIM_Base_Start_IT(&hCAN_FESTIVAL_TIMER) != HAL_OK)
{
Error_Handler();
}
// Start FDCAN module
if (HAL_FDCAN_Start(&hFDCAN_MODULE) != HAL_OK)
{
Error_Handler();
}
// Set up to interrupt when a new message arrives in the RX Fifo 0
if (HAL_FDCAN_ActivateNotification(&hFDCAN_MODULE, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
{
Error_Handler();
}
}
Issue 1: I use the function HAL_FDCAN_AddMessageToTxFifoQ but the queue quickly fills up and no CAN transmission takes place.
void canxmit_Task(void)
{
Message message;
osStatus_t status;
while(true)
{
// Check to see if the Tx FIFO is full.
if ((hFDCAN_MODULE.Instance->TXFQS & FDCAN_TXFQS_TFQF) != 0)
{
break; // Tx FIFO is full.
}
// Check for any messages in the RTOS queue.
status = osMessageQueueGet(CanXmitQueueHandle, &message, NULL, 0);
if (status == osErrorTimeout)
{
break; // No new messages to send.
}
if (status != osOK)
{
Error_Handler();
}
// Copy message from data structure used by CANfestival into that required for HAL.
TxHeader.Identifier = message.cob_id;
TxHeader.TxFrameType = (message.rtr != 0) ? FDCAN_REMOTE_FRAME : FDCAN_DATA_FRAME;
TxHeader.DataLength = message.len;
for (uint32_t i = 0; i < message.len; i++)
{
TxData[i] = message.data[i];
}
// Add message to CAN Fifo queue for transmission.
if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData) != HAL_OK)
{
Error_Handler();
}
}
}
From debug, I see that HAL_FDCAN_AddMessageTxFifoQ is called 3 times and after this the FDCAN_TXFQS_TFQF bit is permanently set. I don’t see any output on the CAN bus.
Issue 2: I never get a CAN interrupt when messages are sent from the host
Even with host transmitting CAN data, the function: void FDCAN1_IT0_IRQHandler(void) is never called.
I loaded the code on an STM32G474E-EVAL1 board, connected a properly terminated CAN cable to a host, connected a PEAK PCAN-USB analyzer with PCAN-View software, and power up the board. I never see any CAN activity from the code, the 3-deep transmit queue fills up, and I never get any CAN interrupts.
答案1
得分: 1
我认为您目前遇到了一些问题,但没有进行物理测试,只是猜测。尝试查看以下内容:
- 如果没有回环CAN外设来过滤与当前TX帧相同的传入帧以避免回声。
- 如果您的CAN外设在正常模式下运行,它期望有其他设备在线上接收它。它通过ACK位来判断。如果线上没有其他设备,就不会设置ACK位,CAN外设会将其视为错误并尝试重新发送帧。
- 如果我记得没错,PEAK-CAN有两种模式:透明监听器和节点。区别在于前面提到的ACK位。
如果我是您,我首先会在MCU本身的回环模式下进行测试(甚至可以使用FDCAN附带的新型外部回环,它还会发送TX线,以便您可以看到通信发生)。只有在您知道至少“某些东西”有效的情况下,才会连接外部设备。在那时,请确保您的时序设置是正确的,因为这可能是一个棘手的设置(在线上有很多计算器可以用于此)。此外,查看PEAK-CAN文档以获取关于ACK位行为的信息。如果没有帮助,尝试连接另一个监听器节点,例如带有CAN收发器的其他STM32 MCU。这样,您可以确保您正在正确地接收帧。
英文:
I think you are currently encountering a few issues, but without physical testing it is only speculation. Try to take a look at those:
- Without loop-back CAN peripherals filter out incoming frames that are identical to the current TX frame, to avoid echoes.
- If your CAN peripheral is operating in normal mode it expects it to be received by something on the line. It knows it thanks to the ACK bit. If there are no other devices on the line nothing will set the ACK bit, which CAN peripheral will treat as an error and will try to resend the frame.
- If I remember right, PEAK-CAN has 2 modes: a transparent listener and a node. Difference is in the ACK bit mentioned before.
If I were you I would first test this in a loop-back mode on the MCU itself (maybe even the fancy new external loop-back that comes with FDCAN, which also sends the TX line out, so you can see communication happening).
Only when you know that something works I would connect an external device. At that point make sure your timing settings are correct, as this can be a tricky thing to set up (there are bunch of calculators online for this). Also look at PEAK-CAN documentation to find information about the ACK bit behavior. If it doesn't help, try to connect a different listener node e.g. other STM32 MCU with a CAN transceiver. That way you can be sure that you are receiving frames properly.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论