CAN-Frame kann auf STM32 wegen unerwarteter Kollision nicht empfangen werden

Ich versuche, CAN-Frames auf einem STM32F412G-DISCOVERY mit einem SN65HVD233-Transceiver zu empfangen, die von einem USB2CAN-Gerät gesendet werden. Beide sind an einem etwa 15 cm langen Bus mit zwei 120-Ω-Widerständen an jedem Ende angeschlossen.

Ich habe ein Oszilloskop angeschlossen, um die RX- und TX-Pins auf der STM32-Platine zu lesen, bevor sie vom Transceiver transformiert werden. Wenn ich den CAN-Controller im Silent-Modus konfiguriere und einen CAN-Frame vom USB2CAN sende, verwende ich:

$ cansend can0 '144#25'

Ich sehe auf dem Oszilloskop am RX-Pin das Vollbild (gelb ist der RX der Platine, blau sein TX):

Hinweis: Der Cursor zeigt das Zeitintervall von einem Bit an (2 µs, Bitrate ist 500 kb/s).

(Der HAL_CAN_ReceiveAnruf läuft immer noch ab, aber das ist ein anderes Problem.) Aber wenn ich den Controller in den normalen Modus versetze, messe ich Folgendes:

Geben Sie hier die Bildbeschreibung ein

Und hier ist der 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);

Es scheint, dass der Emitter (USB2CAN) versucht hat, eine rezessive (1) für das 2. Bit der ID zu schreiben, während der Empfänger (STM32) eine dominante (0) gesendet hat: Der Emitter hat diese Kollision erkannt und die Emission gestoppt.

Warum hat der STM32-CAN-Controller dieses dominante Bit gesendet, das die Kommunikation gestoppt hat?

Antworten (1)

Ein Timing-Missverhältnis.

Der STM32 gibt ein Fehlerflag aus. Warum sonst sollte es etwas direkt nach den ersten paar Bits übertragen?

Der Fehlerrahmen soll 6 Bit lang sein, aber in Ihrem Bild passt die Breite der Cursor nicht 6 Mal in den TX-Rahmen. Das bedeutet, dass die Controller nicht dieselbe Bitrate verwenden.

Der STM32 ist mit einem Prescaler von 12 konfiguriert, was laut CubeMX einer "Zeit für ein Bit" von 2000 ns entspricht, ist das nicht eine Bitrate von 500 kb/s?
Anscheinend verwendete der STM32 eine tatsächliche Bitrate von 250 kb/s (?!), durch Verdoppeln der Bitrate bekomme ich jetzt Folgendes: i.imgur.com/FJ0wge9.jpg ; Ich verstehe immer noch nicht, warum der STM32 etwas anderes sagt, als den Rahmen zu bestätigen.
Das war in der Tat ein Timing-Problem. Ich habe einen Prescaler von 4 mit 7/1 für BS1/BS2 verwendet und es funktioniert jetzt!