2025-05-26 1:58 AM
Hi, I am trying to send classical CAN messages using FDCAN with STM32h723vgT6 - based board. I am however having difficulties sending any packets (and receiving).
Hardware setup:
- DM-MC02 board, based on STM32h723vg (https://gitee.com/kit-miao/dm-mc02)
- SIT1042 CAN controller, directly built-in the board. Thus, the respective CAN_H and CAN_L are directly accessible through the board's pin
- (Device) ZDT_Emm_V5.0 stepmotor controller. Anyway it is just the device I am trying to send data to (https://blog.csdn.net/zhangdatou666/article/details/132644047)
- CANable 2.0 - inspired USB device.
What I am trying to do:
I want to be able to send and receive classical CAN messages using the DM-MC02 board to drive my controller. Because of my controller's specs, I need to send classical CAN messages with extended IDs at a bitrate of 500 000, by configuring FDCAN (what's supported by STM32h723vg) in normal mode. I would prefer using the CAN1 port of my board.
I am using STM32CubeIDE.
What works:
I am able to drive the stepmotor controller with my computer by using python-can through the CAN USB device, which indicates that for the most part my wiring seems okay, and that I do have a somewhat working CAN network. I did check the termination resistor values, all my CAN_H and CAN_L cables are twisted together.
What does not work:
My setup is rather simple, the CAN network is made of the DMMC board, CAN USB drive and the Stepmotor controller. For now, I wanted to send data from the board to the CAN USB (and see the messages via python-can or Cangaroo). However, I have no signal from my board.
Basically I am unsure what is missing in my board's configuration or code. I have followed many guides to configure the .ioc, I even found some code by the manufacturer (not the settings I would like to use though, it is for FDCAN 1 250 000, which I am unsure what to think of by the way as, at least for python-can, 1 250 000 seem to be not a supported rate, thus I could not test with it much). For the timing configuration, I have used Kwaser's calculator for FDCAN, I found this configuration (from my understanding, the Data should not matter much with classical CAN) :
Please find attached my .ioc file and source code, and here is the core of the code.
if(HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
/* Configure Header */
uint8_t TxData[] = {0xF6, 0x00, 0x05, 0xDC, 0x0A, 0x00, 0x6B, 0x00};
TxHeader.Identifier = 0x0100;
TxHeader.IdType = FDCAN_EXTENDED_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 = 0x0; // Ignore because FDCAN_NO_TX_EVENTS
/*...*/
/* Add message to Tx buffer */
if(HAL_FDCAN_AddMessageToTxBuffer(&hfdcan1, &TxHeader, TxData, FDCAN_TX_BUFFER0) != HAL_OK)
{
Error_Handler();
}
/* Send Tx buffer message */
if(HAL_FDCAN_EnableTxBufferRequest(&hfdcan1, FDCAN_TX_BUFFER0) != HAL_OK)
{
Error_Handler();
}
/* Polling for transmission complete on buffer index 0 */
while(HAL_FDCAN_IsTxBufferMessagePending(&hfdcan1, FDCAN_TX_BUFFER0) == 1) {
__NOP();
}
Basically, I found that the code gets stuck in the while(HAL_FDCAN_IsTxBufferMessagePending(&hfdcan1, FDCAN_TX_BUFFER0) == 1) loop, indicating that the buffer has some difficulties getting processed and cleared.
When using "HAL_FDCAN_GetProtocolStatus(&hfdcan1, &status);", I can see that the status struct's DataLastErrorCode and LastErrorCode are set to 7 (No change since last read).
When trying to receive messages with a similar code, the program would also get stuck as if there were no new messages.
As I cannot make that simple setup work I am a bit at lost on what to do, perhaps the STM32 community could have new ideas.
Please feel free to ask for any details, and I would appreciate any help.
Thanks !
Solved! Go to Solution.
2025-05-27 11:56 PM - edited 2025-05-28 12:11 AM
Hello, thank you for your suggestions it helped me for debugging and narrowing down the issue !
While I have now a setup that allows to transmit and receive messages from the STM32 (Hooray !), something is still off so I would like not to close the thread yet.
Summary of the issue resolution
Two things:
1. Thank to your suggestions, I found out that the CAN controller was indeed not being powered correctly. Resolving this lead to this new status struct values:
2. This pointed out that there might have been some issue with the CAN configuration itself as well. And indeed there is, but in a surprising way.
New issue
While STM32CubeIDE reports that, according to the clock and CAN config, the Nominal Baud Rate should have been 500 000 bit/s, meaning 500kHz signal frequency, an oscilloscope measurement revealed that it was instead outputting at 480kHz ! With a quick and dirty tweak in the timing values to raise the nominal baudrate to compensate
allowed to reach ~504kHz, allowing CAN communication.
As I find this finding great (something works!), I wanted to ask whether someone would know if something is going out, perhaps it is just the external oscillator that is not accurate...
2025-05-26 2:34 AM - edited 2025-05-26 2:42 AM
Hello @lgabp1 and welcome to the ST community,
1- The link you provided for that DMMC board doesn't contain anything moreover it is in Chinese language. So please provide the schematics of that board.
2- I'm not comfortable with that Chinese transceiver: SIT1042 are you sure it's a good product?
3- Did you try the Loopback mode before switching to the Normal mode?
I didn't understand what the stepper motor controller has to do with the subject. could you please clarify.
You need to be more accurate in the description and give more details of your hardware you are using. Providing the board names doesn't help.
2025-05-26 3:04 AM
Sometimes it is only the lacking termination resistor.
> I am able to drive the stepmotor controller with my computer by using python-can through the CAN USB device, which indicates that for the most part my wiring seems okay, and that I do have a somewhat working CAN network.
I don't know what 'device' you talk about here, but do you have some bus monitoring software, and if so, can it detect and display error conditions ?
Here an examplary link : https://forum.peak-system.com/viewtopic.php?t=35
You could check the error counter values of the CAN peripheral,, perhaps you quickly run into error-passive and bus-off.
> Basically, I found that the code gets stuck in the while(HAL_FDCAN_IsTxBufferMessagePending() ...
I don't know the Cube/HAL implementation, but a CAN message is not considerated sent until an ack from a receiving node is detected. I think there is no successful transmission at all from the STM32 side.
If you don't have any specific analysing tools (HW+SW), you can use a scope.
2025-05-26 5:14 AM
Thank you for your message !
1- The link you provided for that DMMC board doesn't contain anything moreover it is in Chinese language. So please provide the schematics of that board.
Unfortunately, I could not find non Chinese documentation, please find attached the datasheet of the board, and here are a few relevant schematics:
I am trying to the the pin on the top left corner (next to OUT EN PC14), and please note that U1 here is made of the SIT1042.
2- I'm not comfortable with that Chinese transceiver: SIT1042 are you sure it's a good product?
Well to be honest I cannot say since it is built-in, but I expect it to work because it seems that that board was used for CAN in some projects. You may find attached its english datasheet here: https://semic-boutique.com/wp-content/uploads/2016/05/SIT1042.pdf
3- Did you try the Loopback mode before switching to the Normal mode?
I did, but indeed I should try once more now that I am more familiar with my setup.
I didn't understand what the stepper motor controller has to do with the subject. could you please clarify.
You need to be more accurate in the description and give more details of your hardware you are using. Providing the board names doesn't help.
So I am able to send CAN messages and receive answers from the CAN USB device to the Stepper motor controller, from my understanding it indicates that the electronics setup (such as terminal resistor values) should be good.
Now, my issue is to have the STM32 based board use this CAN setup.
I have made a schematics of for the bus (I changed the DMMC02 connector but it is similar with CAN1).
2025-05-26 6:46 AM - edited 2025-05-26 6:49 AM
Hello,
According to your ioc file, you mapped FDCAN1 on PA11 and PA12 while in the schematic, FDCAN1 is mapped on PD0 and PD1.
So please check this issue before going ahead: need to change FDCAN1 pinouts in the CubeMx.
2025-05-26 8:31 PM - edited 2025-05-26 9:24 PM
Thank you for pointing out the pin issue, I forgot to update them after changing port. You may find attached the new .ioc file.
Unfortunately, as before changing the port, there is still something missing somewhere. Please see my answer to Ozone for updated details.
Edit+Update: I was able to have a basic (external) loopback mode stetup working with my board, but no progress for normal mode.
2025-05-26 8:52 PM - edited 2025-05-26 8:54 PM
Thank you very much for your advice !
While I could not find a CAN monitoring software that allows peeking at the CAN error values compatible with the CANable CAN USB device, I was able to retrieve bus-related info directly using the HAL libraries.
I have applied the pin fix pointed out by mƎALLEm,and then changed my wait loop to this:
while(HAL_FDCAN_IsTxBufferMessagePending(&hfdcan1, FDCAN_TX_BUFFER0) == 1) {
FDCAN_ProtocolStatusTypeDef status1;
HAL_FDCAN_GetProtocolStatus(&hfdcan1, &status1);
__NOP();
}
Since the pin fix, the program is not stuck in the while loop right away so there is definitely something going on, this is the state of status in the first iterations
(Note: "1 iteration" = "1 send attempt" = HAL_FDCAN_AddMessageToTxBuffer + HAL_FDCAN_EnableTxBufferRequest + HAL_FDCAN_IsTxBufferMessagePending) :
LastErrorCode=5 : Bit 0 (dominant) error
DataLastErrorCode=7 : No change since last read
Activity=8 : Node is neither receiver nor transmitter
ErrorPassive=1 : Passive state
Warning=1 : at least one of error counters has reached the Error_Warning limit of 96
, and then after more iterations, the program gets stuck in the while loop waiting for transmission, here is the value of status
As you did anticipate, the setup seems to indeed fail to transmit and accumulate error, leading to error-passive and bus-off states. I also did confirm with a quick setup that when the STM32 is asked to send a CAN message, no signal can be seen on the bus.
[...] but a CAN message is not considerated sent until an ack from a receiving node is detected. I think there is no successful transmission at all from the STM32 side.
I understand that it seems that something is wrong, leading to the STM32 being unable to send any message. I did multiple checks of my wiring and I cannot find issues here.
2025-05-26 10:55 PM
> As you did anticipate, the setup seems to indeed fail to transmit and accumulate error, leading to error-passive and bus-off states. I also did confirm with a quick setup that when the STM32 is asked to send a CAN message, no signal can be seen on the bus.
I think the default setting for the error passive count is 128, while each failed attempt increases the count by (I think) 8. When the count reaches the "bus off" count (default 255), the node turns off for some time.
In absence of specific tools, I would recommend to disconnect the working nodes (the USB-CAN device and the motor controller) from the bus and only connect a termination resistor. Then capture a transmission from the STM32 with a scope (or a logic analyzer which can be configured to the CAN levels). Compare the signal to that of a proper / working transmission.
Either the transceiver hardware on the STM board is the issue, or the CAN bus settings of the STM32 itself are not correct.
If that is possible, you can try to connect the STM32 CAN Tx/Rx pins directly to the respective CAN Tx/Rx pins of the motor controller, and see if that works.
2025-05-26 11:20 PM
Here is an update narrowing down where the issue might be further.
I have followed the guide here https://controllerstech.com/stm32-fdcan-in-loopback-mode/ to make a simple FDCAN Loopback setup, and then I changed the configuration up to when it no longer works.
From my understanding, in external loopback mode, it should send signals on the bus (but no read from it) while it reads its own signal. While I can receive the signals on the STM32, there seem to be no signal on the bus.
The program still works unless I remove change from loopback mode to normal mode (I was able to successfully go form that guide's config to classical CAN, 8bit messages, extended can ID).
In external loopback, as expected, TxData is sent and RxData being filled with the content of received data.
When using normal mode, as before nothing happens. Here again, reading the status with HAL_FDCAN_GetProtocolStatus(&hfdcan1, &status1); gives:
with Activity=8 : Node is neither receiver nor transmitter.
Here is the relevant part of the code, and you may find attached the third .ioc file version. Please note that I am now trying to send a message to 0x0100, a valid CAN node (the stepper motor controller).
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_FDCAN1_Init();
/* USER CODE BEGIN 2 */
FDCAN_FilterTypeDef sFilterConfig;
sFilterConfig.IdType = FDCAN_EXTENDED_ID;
sFilterConfig.FilterIndex = 0;
sFilterConfig.FilterType = FDCAN_FILTER_MASK;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1 = 0x0100;
sFilterConfig.FilterID2 = 0x0100;
sFilterConfig.RxBufferIndex = 0;
if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
{
/* Filter configuration Error */
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)
{
/* Notification Error */
Error_Handler();
}
TxHeader.Identifier = 0x0100;
TxHeader.IdType = FDCAN_EXTENDED_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;
while (1)
{
for (int i=0; i<8; i++)
{
TxData[i] = indx++;
}
FDCAN_ProtocolStatusTypeDef status1;
HAL_FDCAN_GetProtocolStatus(&hfdcan1, &status1);
if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData)!= HAL_OK)
{
Error_Handler();
}
HAL_Delay (400);
}
/* USER CODE END 2 */
From this, I would guess it would point out an issue with my wiring, but I cannot find what could be wrong. Do someone know if Activity=8 could occur for another reason ?
2025-05-26 11:30 PM
> Do someone know if Activity=8 could occur for another reason ?
The CAN section of the MCU reference manual should list all possible causes.
While I use a lot of CAN devices in my dayjob, none of them is based upon a STM32. But the CAN peripherals of most Cortex M devices are very similiar, almost all of them licence the respective IP from Bosch.