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 1:30 AM - edited 2025-05-27 1:52 AM
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.
I have tried what you advised to do, wiring the CAN_H and CAN_L with a terminator resistor and an oscilloscope. I can see absolutely no signal, both in normal and external loopback mode. In external loopback mode, the MCU will send and recieve the signal still (but well since loopback is done at the TX/RX level, I guess it doesn't show that the CAN controller works).
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.
Unfortunately these pins are too difficult and tiny to access, I don't think I can.
Either the transceiver hardware on the STM board is the issue, or the CAN bus settings of the STM32 itself are not correct.
Since the program works in external loopback mode, but there are no signals to be seen on the bus, to me it looks like it is not the settings that are wrong.
Thank you for the additionnal info about error counters.
Edit+Update: I have tried with CAN2 and CAN3 ports as well as there are 3 different CAN controllers, but to no avail.
2025-05-27 1:56 AM
@lgabp1 wrote:
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.
According to that statement, I thought you succeeded the Loopback mode.
Could you please confirm again the Loopback mode is not working?
2025-05-27 2:01 AM - edited 2025-05-27 2:06 AM
Sorry for not having been clear enough. I have tried loopback a week ago and did get something but back then I did not understand the whole process that much.
But anyway I have started a fresh setup with external lookback mode today, that fresh setup does work. (In external loopback mode, the STM32 successfully sends data and receives it. This probably means that there are no issues up to the RX/TX wires. However, there is no signal to be seen on the CAN_H and CAN_L wires).
2025-05-27 2:05 AM
> I have tried what you advised to do, wiring the CAN_H and CAN_L with a terminator resistor and an oscilloscope. I can see absolutely no signal, ...
Did you check the MCU Tx/Rx pins ?
If you don't see anything there, you are either at the wrong pins, or the initialisation is not correct.
> Unfortunately these pins are too difficult and tiny to access, I don't think I can.
Not unexpected ...
Perhaps you have another STM32 board you can use, of the same kind or another.
> Edit+Update: I have tried with CAN2 and CAN3 ports as well as there are 3 different CAN controllers, but to no avail.
Switching from one peripheral instance to another is not always as trivial as it seems. A different GPIO port requires different RCC enabling flags, and not all instances of peripherals are always on the same peripheral bus.
If you don't see any signal on the MCU CAN Tx pin, it is almost certainly your code.
2025-05-27 4:37 AM
@lgabp1 wrote:
, the STM32 successfully sends data and receives it. This probably means that there are no issues up to the RX/TX wires. However, there is no signal to be seen on the CAN_H and CAN_L wires).
To me this is a sign of a hardware issue in the Normal mode, may be an issue with the transceiver.
Check the power supply of the transceiver on its pins: Pin 3: VDD=5V, Pin 5: VIO=3.3V.
Check also STDBY pin. In the schematic, the pin is connected to the ground which is correct but you need to check with continuity function of your multimeter with board powered off. It could be an issue with the PCB.
2025-05-27 4:45 AM
Another question,
In the datasheet the transceiver is an 8 pin package:
while in the schematics the transceiver has the pin 9 called "EPAD":
.. not sure if this the same transceiver part number..
2025-05-27 5:07 AM - edited 2025-05-27 5:08 AM
> while in the schematics the transceiver has the pin 9 called "EPAD":
This is usually a metallic & conductive connection to die bulk, often cooling fins. Sometimes simply the exposed die itself.
However, the standard version of this transceiver is 5V logic, as I understood it.
Only the xxx/3 version is 3.3V logic. I would at least check.
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-28 12:21 AM
This seems purely a clock setup issue, either the system clock or the peripheral one.
I have no experience with the H7 in this regard, though.
But you don't use HSI as main clock source, do you ?
2025-05-28 12:28 AM
This is entirely a Mea Culpa, I was so focused on CAN parameters that I forgot to change the HSE base frequency to what its datasheet says to...
Thank you for the help !