2
\$\begingroup\$

I’m trying to receive CAN frames on a STM32F412G-DISCOVERY with a SN65HVD233 transceiver, transmitted from a USB2CAN device. Both are connected on a bus of about 15 cm long with two 120 Ω resistors on each end.

I connected an oscilloscope to read the RX and TX pins on the STM32 board before they are transformed by the transceiver. When I configure the CAN controller in silent mode and send a CAN frame from the USB2CAN using:

$ cansend can0 '144#25'

I see on the oscilloscope on the RX pin the full frame (yellow is the board’s RX, blue its TX):

NB: the cursor indicate the time interval of one bit (2 µs, bitrate is 500 kb/s).

(The HAL_CAN_Receive call still timeout, but that is another problem.) But when I put the controller in normal mode, here is what I measure:

enter image description here

And here is the code:

hcan1.pTxMsg = &g_out_msg;
hcan1.pRxMsg = &g_in_msg;
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 12;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SJW = CAN_SJW_1TQ;
hcan1.Init.BS1 = CAN_BS1_1TQ;
hcan1.Init.BS2 = CAN_BS2_1TQ;
hcan1.Init.TTCM = DISABLE;
hcan1.Init.ABOM = DISABLE;
hcan1.Init.AWUM = DISABLE;
hcan1.Init.NART = DISABLE;
hcan1.Init.RFLM = DISABLE;
hcan1.Init.TXFP = DISABLE;

if (HAL_CAN_Init(&hcan1) != HAL_OK)
    fatal_error("failed to init HAL CAN.");

CAN_FilterConfTypeDef sFilterConfig;
sFilterConfig.FilterNumber         = 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 = 0;
sFilterConfig.FilterActivation     = ENABLE;
sFilterConfig.BankNumber           = 14;
if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
    fatal_error("failed to setup CAN filter.");

HAL_StatusTypeDef can_status;
if ((can_status = HAL_CAN_Receive(&hcan1, CAN_FIFO0, 20000)) != HAL_OK)
    fatal_error("failed to receive frame: %d", can_status);

It seems that the emitter (USB2CAN) tried to write a recessive (1) for the 2nd bit of the ID while the receiver (STM32) sent a dominant (0): the emitter detected that collision and stopped emitting.

Why did the STM32 CAN controller sent that dominant bit which stopped the communication?

\$\endgroup\$
2
\$\begingroup\$

A timing mismatch.

The STM32 issues an error flag. Why else would it transmit anything directly after the first few bits?

The error frame is supposed to be 6 bits long, yet in your image the width of the cursors does not fit in the tx frame 6 times. Meaning the controllers do not use the same bitrate.

\$\endgroup\$
  • \$\begingroup\$ The STM32 is configured with a prescaler of 12 which corresponds to a "time for one bit" of 2000 ns according to CubeMX, isn't that a bitrate of 500 kb/s? \$\endgroup\$ – lesenk Jun 9 '18 at 21:21
  • \$\begingroup\$ Apparently, the STM32 used an actual bitrate of 250 kb/s (?!), by doubling the bitrate, I now get this: i.imgur.com/FJ0wge9.jpg ; I still don't understand why the STM32 says anything beside acking the frame. \$\endgroup\$ – lesenk Jun 9 '18 at 21:37
  • \$\begingroup\$ This was a timing issue, indeed. I used a prescaler of 4 with 7/1 for BS1/BS2 and it now works! \$\endgroup\$ – lesenk Jun 9 '18 at 22:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.