2025-02-24 5: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.
Solved! Go to Solution.
2025-02-24 11:11 PM
Sorry I didn't make it clear. The X and Y I mentioned are actually channels 1 and 2. When testing, since my CAN cable did not lead out GND, I simply connected CANH to channel 1 and CANL to channel 2. The oscilloscope probe was not connected to anything else.
Speaking of this, I do think the signal returned by my oscilloscope is a bit strange. I think the CAN bus should be a differential signal, but the actual signal is very strange...
2025-02-24 11:14 PM
2025-02-24 11:22 PM - edited 2025-02-24 11:26 PM
Hello @most1ma ,
The main doesn't contain the CAN code just only can_receive_msg() call and this doesn't help.
In order to avoid unnecessary ping pongs:
1- Probe the Rx pin from SIT1042.
2- Check if you have the VIO pin version of the transceiver:
Not related directly to the reception but it will be a problem to send the acknowledgement bit after reception.
3- Please clarify this statement:
" I did consider it was an issue with the initialization or the filter, but after I tested it, I became even more confused."
Did you succeed the loopback mode or not?
2025-02-24 11:26 PM - edited 2025-02-24 11:28 PM
@most1ma wrote:Sorry I didn't make it clear. The X and Y I mentioned are actually channels 1 and 2. When testing, since my CAN cable did not lead out GND, I simply connected CANH to channel 1 and CANL to channel 2. The oscilloscope probe was not connected to anything else.
Speaking of this, I do think the signal returned by my oscilloscope is a bit strange. I think the CAN bus should be a differential signal, but the actual signal is very strange...
You don't have a signal on channel 2. So it's a hardware/wiring issue. Without both differential signals present, you won't get any signal going to the CAN Rx of the STM32.
Also, other than the PC and STM32, are there any other CAN nodes connected?
2025-02-25 12:07 AM
1. Oscilloscope results of Rx pin:
2. It has the VIO pin
3. Loopback mode is ok. Both transmit and receive works fine in loopback mode.
2025-02-25 12:17 AM
Rx signal should not go below ground reference. Do you have a ground reference between the PC and the STM32? What are you using on the PC side to communicate?
2025-02-25 12:20 AM - edited 2025-02-25 12:21 AM
@most1ma wrote:
These are weird signals. It should be a hardware issue.
And according to your CAN_H and CAN_L signals they are weird too. CAN_H and CAN_L are not supposed to reach the GND. Also your CAN_L is always 0!
This is what you need to see on CAN_H and CAN_L.
Check again your connections, especially the jumpers related to the USB. Check CAN_H and CAN_L connections using the continuity in the multimeter. Not obvious to tell what is going on.
2025-02-25 8:42 AM
Thanks for your reply. I ran a series of tests again:
1. When the STM32 board is not powered on, the oscilloscope detects the correct differential signal on the CAN bus, and the time interval between the two levels is 2us, indicating that the baud rate is the correct 500kbps. (I detected the wrong CANL level before because the probe was faulty. After I changed a probe, it became normal.)
2. When the STM32 board is powered on, the signal looks normal for a while at the beginning, but compared with the waveform measured in item 1, its period seems to be a little unstable, especially in the last few levels of a frame. After working for a while (every time exactly at the 7th second), the CAN bus signal disappears. Only when I restart the host computer will the signal reappear, and then repeat what I mentioned above.
I guess, is this because there is something on the stm32 board after powering on that interferes with the CAN bus, causing the software to automatically shut down the bus after detecting an error? I used single-step debugging to observe the various registers of CAN, especially the error register (ESR), but I didn't seem to find any abnormalities. Is this because STM32 is not the sender of CAN but the receiver, and ESR only reflects the sender's problems?
My host computer is actually a semi-physical simulation machine used for scientific research simulation. Could this be a problem with the host computer? Should I ask the manufacturer of the host computer for more debugging information?
The attached are the waveforms of two data frames I took, one when the STM32 board is not powered on, and the other when the STM32 board is powered on.
Sincerely thank you
2025-02-25 8:44 AM
I use a DB9 cable to connect my host computer and STM32 board, so there is no direct connection between the GND.
My host computer is actually a semi-physical simulation machine used for scientific research simulation.I'm not sure what's used in the host computer to generate the CAN signals (I guess it's probably an FPGA). Maybe I should consult the host computer manufacturer for more information? Is it possible that the CAN controller in the host computer detects some errors on the bus and automatically closes the bus after the error counter overflows?
2025-02-25 9:34 AM
The DB9 cable should have a ground terminal. Connect that ground to the STM32 board's ground.
What is this simulation device? Datasheet?
The PC host needs at least 1 device to communicate with because it needs to see ACK from other device(s).
If there are communication errors for n amount of times, the CAN controller will go into bus off state. When you start getting n amount of good CAN messages, then the device should go back to normal state. But this could depend on what the PC is using for the CAN controller.
How did you set up your CAN configuration? STM32CubeIDE/MX? If so, upload your IOC file.
I have a feeling your time segment, SJW and prescaler are not correct.