2025-02-24 05:26 AM
I am trying to use my STM32F429IGT6 CAN to receive some data from the host computer. The data is basically 4 16-bit unsigned integers (8 bytes in total), the message ID is 0x16 and uses the 11-bit standard ID format. The host computer sends messages to the bus in a 2ms cycle.
On the STM32 part, I enabled CAN1 and used the interrupt function to receive and process the data. However, most of the time, the STM32 does not show any CAN messages coming, and the HAL_CAN_GetRxFifoFillLevel() function always returns 0. This makes me really confused.
Below is the initialization code in my can.c file. My CAN1 is mounted on the APB1 bus with a frequency of 45Mhz, and the CAN transmission rate of the host computer and STM32 is 500kbps.
void MX_CAN1_Init(void)
{
/* USER CODE BEGIN CAN1_Init 0 */
/* USER CODE END CAN1_Init 0 */
/* USER CODE BEGIN CAN1_Init 1 */
/* USER CODE END CAN1_Init 1 */
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 6;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_8TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_6TQ;
hcan1.Init.TimeTriggeredMode = DISABLE;
hcan1.Init.AutoBusOff = DISABLE;
hcan1.Init.AutoWakeUp = ENABLE;
hcan1.Init.AutoRetransmission = ENABLE;
hcan1.Init.ReceiveFifoLocked = DISABLE;
hcan1.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN CAN1_Init 2 */
CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterBank = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterIdHigh = 0x0000;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.SlaveStartFilterBank = 14;
if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_CAN_Start(&hcan1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE END CAN1_Init 2 */
}
void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(canHandle->Instance==CAN1)
{
/* USER CODE BEGIN CAN1_MspInit 0 */
/* USER CODE END CAN1_MspInit 0 */
/* CAN1 clock enable */
__HAL_RCC_CAN1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**CAN1 GPIO Configuration
PA11 ------> CAN1_RX
PA12 ------> CAN1_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* CAN1 interrupt Init */
HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
HAL_NVIC_SetPriority(CAN1_RX1_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(CAN1_RX1_IRQn);
HAL_NVIC_SetPriority(CAN1_SCE_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(CAN1_SCE_IRQn);
/* USER CODE BEGIN CAN1_MspInit 1 */
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
/* USER CODE END CAN1_MspInit 1 */
}
}
and this is my interrupt funciton:
CAN_RxHeaderTypeDef RxHeader;
uint16_t RxData[4];
uint16_t canbuf[4]; /* CAN rx dest */
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, (uint8_t *)RxData) == HAL_OK)
{
for (int i = 0; i < RxHeader.DLC / 2; i++)
{
canbuf[i] = RxData[i];
}
}
}
So far, I have tried the following steps:
1. Confirm that the 120 ohm terminal resistors on both sides of the CAN have been added. The CAN cable is a standard twisted pair with a DB9 interface and is well connected.
2. The CAN configuration of the host computer is in send mode, using the standard 11-bit ID mode, the ID value is 18 (0x12), the data segment is 8 bytes, the baud rate is 500kbps (consistent with STM32), and the message transmission rate is 2ms once.
3. I tried to monitor the ESR register (error register) of CAN1 in real time through debug mode, but no abnormalities were found. All flag bits look normal (all 0).
4. I confirmed that I have called the HAL_CAN_Start() and HAL_CAN_ActivateNotification() functions normally.
The one thing I have left to do is to test the CAN message levels sent by the host computer through a logic analyzer (the analyzer is on the way), but I think the possibility of an error in the host computer is low.
Looking forward to responses from people who have had similar problems or professionals.
2025-02-24 06:40 AM
Hello,
1- Could you please share your ioc file and your main.c?
2- Could you please share the schematics part showing the STM32 and the CAN transceiver?
2025-02-24 06:43 AM - edited 2025-02-24 06:43 AM
What now, can or cannot ?
;) Couldn't resist, sorry...
So here's some serious and hopefully helpful advice:
Once upon a time the HAL examples were missing some global filter enable, maybe that's it?
Here's what I found in my notes - but that's for H7 FDCAN:
/* LISTENING:
* if global reject is NOT turned on with HAL_FDCAN_ConfigGlobalFilter(),
* then all messages are received in
* RX FIFO 0
*/
// after all the inits, before CAN start:
/* Configure global filter to reject all non-matching frames */
HAL_FDCAN_ConfigGlobalFilter(phCan, FDCAN_REJECT, FDCAN_REJECT, FDCAN_REJECT_REMOTE, FDCAN_REJECT_REMOTE);
I recommend the following:
- use a STM32 UART and printf some debug info to a terminal
- reduce the host transmit rate for easier debugging
- connect an oscilloscope, check the incoming messages, look for the ACKNOWLEDGE bit by the STM32
- transmit some messages from STM32, just to check bit timings (trigger that by UART input)
2025-02-24 06:50 AM
@LCE wrote:
Here's what I found in my notes - but that's for H7 FDCAN:
/* LISTENING: * if global reject is NOT turned on with HAL_FDCAN_ConfigGlobalFilter(), * then all messages are received in * RX FIFO 0 */ // after all the inits, before CAN start: /* Configure global filter to reject all non-matching frames */ HAL_FDCAN_ConfigGlobalFilter(phCan, FDCAN_REJECT, FDCAN_REJECT, FDCAN_REJECT_REMOTE, FDCAN_REJECT_REMOTE);
@LCE unfortunately, bxCAN and FDCAN have no similar implementation and there is no similar rejection mechanism on STM32F4 (bxCAN) ;)