No se puede recibir el marco CAN en STM32 debido a una colisión inesperada

Estoy tratando de recibir marcos CAN en un STM32F412G-DISCOVERY con un transceptor SN65HVD233, transmitido desde un dispositivo USB2CAN. Ambos están conectados en un bus de unos 15 cm de largo con dos resistencias de 120 Ω en cada extremo.

Conecté un osciloscopio para leer los pines RX y TX en la placa STM32 antes de que el transceptor los transforme. Cuando configuro el controlador CAN en modo silencioso y envío un marco CAN desde el USB2CAN usando:

$ cansend can0 '144#25'

Veo en el osciloscopio en el pin RX el cuadro completo (el amarillo es el RX de la placa, el azul es el TX):

NB: el cursor indica el intervalo de tiempo de un bit (2 µs, la tasa de bits es de 500 kb/s).

(La HAL_CAN_Receivellamada sigue agotando el tiempo de espera, pero ese es otro problema). Pero cuando pongo el controlador en modo normal, esto es lo que mido:

ingrese la descripción de la imagen aquí

Y aquí está el código:

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);

Parece que el emisor (USB2CAN) intentó escribir un recesivo (1) para el 2do bit del ID mientras que el receptor (STM32) envió un dominante (0): el emisor detectó esa colisión y dejó de emitir.

¿Por qué el controlador STM32 CAN envió ese bit dominante que detuvo la comunicación?

Respuestas (1)

Un desajuste de tiempo.

El STM32 emite un indicador de error. ¿Por qué otra razón transmitiría algo directamente después de los primeros bits?

Se supone que el cuadro de error tiene una longitud de 6 bits, pero en su imagen el ancho de los cursores no cabe en el cuadro tx 6 veces. Lo que significa que los controladores no usan la misma tasa de bits.

El STM32 está configurado con un prescaler de 12 que corresponde a un "tiempo para un bit" de 2000 ns según CubeMX, ¿no es un bitrate de 500 kb/s?
Aparentemente, el STM32 usó una tasa de bits real de 250 kb/s (?!), Al duplicar la tasa de bits, ahora obtengo esto: i.imgur.com/FJ0wge9.jpg ; Todavía no entiendo por qué el STM32 dice algo además de golpear el marco.
Este fue un problema de tiempo, de hecho. Usé un prescaler de 4 con 7/1 para BS1/BS2 y ¡ahora funciona!