Hice el siguiente circuito. Los STM32 son STM32F103C8T6 (píldoras azules). Dejé fuera los cables obvios:
simular este circuito : esquema creado con CircuitLab
Los TJA son estos:
Software más importante que se ejecuta en TX STM32:
/* CAN init function */
static void MX_CAN_Init(void)
{
static CanRxMsgTypeDef CanRX;
static CanTxMsgTypeDef CanTX;
CAN_FilterConfTypeDef sFilterConfig;
hcan.Instance = CAN1;
hcan.pRxMsg = &CanRX;
hcan.pTxMsg = &CanTX;
hcan.Init.Prescaler = 8;
hcan.Init.Mode = CAN_MODE_NORMAL;
hcan.Init.SJW = CAN_SJW_1TQ;
hcan.Init.BS1 = CAN_BS1_12TQ;
hcan.Init.BS2 = CAN_BS2_5TQ;
hcan.Init.TTCM = DISABLE;
hcan.Init.ABOM = DISABLE;
hcan.Init.AWUM = DISABLE;
hcan.Init.NART = DISABLE;
hcan.Init.RFLM = DISABLE;
hcan.Init.TXFP = DISABLE;
if (HAL_CAN_Init(&hcan) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sFilterConfig.FilterNumber = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterIdHigh = 0x07ff;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x07ff;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.BankNumber = 14;
if (HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
{
Error_Handler();
}
}
en principal:
..
hcan.pTxMsg->StdId = 0x100;
hcan.pTxMsg->ExtId = 0x01;
hcan.pTxMsg->IDE = CAN_RTR_DATA;
hcan.pTxMsg->IDE = CAN_ID_STD;
hcan.pTxMsg->DLC = 2;
while (1)
{
hcan.pTxMsg->Data[0] = 0x10;
hcan.pTxMsg->Data[1] = 0x1;
HAL_CAN_Transmit(&hcan, 10)
HAL_Delay(1000);
}
Y en TX STM32 el mismo código para inicializar CAN, y el siguiente código en main:
if (HAL_CAN_Receive_IT(&hcan, CAN_FIFO0) != HAL_OK)
{
Error_Handler();
}
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
{
if ((CanHandle->pRxMsg->StdId == 0x100) &&
(CanHandle->pRxMsg->IDE == CAN_ID_STD) &&
(CanHandle->pRxMsg->DLC == 2))
{
printf("1");
}
Sin embargo, la devolución de llamada nunca se llama.
Lo que veo con un analizador lógico:
Veo X en la captura de pantalla a continuación, no estoy seguro de si esto es un problema.
Lo que hice
Pregunta:
Actualizar
Descubrí que hay algún problema de transmisión:
dentro
HAL_StatusTypeDef HAL_CAN_Transmit(CAN_HandleTypeDef* hcan, uint32_t Timeout)
se produce un tiempo de espera (última línea):
while(!(__HAL_CAN_TRANSMIT_STATUS(hcan, transmitmailbox)))
{
/* Check for the Timeout */
if(Timeout != HAL_MAX_DELAY)
{
if((Timeout == 0U) || ((HAL_GetTick()-tickstart) > Timeout))
{
hcan->State = HAL_CAN_STATE_TIMEOUT;
/* Cancel transmission */
__HAL_CAN_CANCEL_TRANSMIT(hcan, transmitmailbox);
/* Process unlocked */
__HAL_UNLOCK(hcan);
return HAL_TIMEOUT;
}
}
}
No he averiguado de dónde viene este error.
También debido al error, no se envía nada después.
No hay más tiempo ahora, revisaré más mañana o el martes por la noche.
Otros controles:
Actualizar
Todavía por tiempo limitado, pero hice una prueba sin usar transceptores, sino directamente con un circuito simple como se describe en este documento (gracias a Maple). Parte relevante:
Sin embargo, el resultado sigue sin funcionar. Los lados del receptor son CASI iguales, pero el transmisor apenas transmite nada
En el detalle (abajo), en la rampa seleccionada se puede ver una ligera diferencia (hay más de esas). Sin embargo, dado que están conectados entre sí, no los esperaría, pero tal vez mi analizador lógico barato (5 $) podría causarlos.
CANH (Canal 2) y CANL (Canal 0) reciben información
Si el canal 2 es realmente CANH, con la misma base de tiempo que CANL en el canal 0, obviamente ese es su problema. No se ve saludable para nada, debería verse como un espejo diferencial de CANL.
Sospecharía que algo como CANH está en cortocircuito con otra señal o algo en el circuito del transceptor CAN se está comportando mal (¿soldadura deficiente?).
También asegúrese de que no haya resistencias de extracción entre la MCU y el transceptor, o dentro de la MCU en los registros del puerto. Aunque lógicamente, si este fuera el problema, también causaría que CANL fallara.
Agregue siempre 2 resistencias de terminación de 120 ohmios, una en cada extremo del bus, incluso si trabaja con velocidades de transmisión lentas y distancias cortas. A menudo se necesita una cierta diferencia de impedancia de aproximadamente 60 ohmios entre CANH y CANL para que el circuito CAN permanezca feliz.
Obviamente, adjunte una señal a tierra entre cada nodo según lo requiera y exija el estándar CAN. De lo contrario, está a merced de cualquier potencial de tierra que tengan sus nodos, y si hay altas corrientes de tierra en la tierra del suministro, podría afectar la comunicación CAN si no usa una tierra de señal dedicada.
Existe un mito circulando entre los que no son ingenieros de que no necesita una señal a tierra para señales diferenciales, pero eso no tiene sentido a menos que el bus CAN esté aislado galvánicamente con optoacopladores o similar. Las señales diferenciales son simplemente mucho más resistentes que otras señales, por lo que pueden funcionar por suerte incluso si el diseño del sistema es malo y no incluye una señal a tierra. Los transceptores CAN pueden soportar una diferencia de potencial de aproximadamente 40 V antes de que la comunicación se vea afectada.
La X roja en su alcance no es un error sino un relleno de bits. Su alcance los agrega allí para indicar que no son parte de los datos reales. Es tal como se esperaba, siempre debe tener un bit de relleno después de 5 bits altos/bajos consecutivos en un cuadro CAN.
Un problema obvio es que no tiene resistencias de terminación en el bus CAN. Recuerde, no son solo para terminar la línea de transmisión, sino que también son las resistencias de unión para que el bus esté en estado recesivo cuando no está siendo activado explícitamente.
Si esto está en una sola placa, puede salirse con la suya colocando alrededor de 60 Ω entre CANL y CANH. Si el bus CAN es un cable real, coloque 120 Ω entre CANL y CANH en cada extremo. En ese caso, el cable también debe tener tierra para que ambos dispositivos usen la misma referencia de tierra.
Revisé una enorme cantidad de sugerencias, argumentos y contraargumentos aquí y creo que todo esto te hizo un flaco favor. No hay magia en CAN, y aquí está la prueba:
Este horrible desorden en mi escritorio es un banco de pruebas rápido y sucio para un software en el que estoy trabajando en este momento. Tiene dos controladores de motor duales con interfaces CAN y AVR conectados a CAN a través del controlador MCP2515 + transceptor TJA1050 (¡exactamente lo mismo que tiene usted!).
Los controladores del motor se conectaron con 3 cables (incluida la conexión a tierra), pero el AVR solo tiene 2. Ni siquiera tengo un bus directo: todo está conectado en estrella en el enchufe DB15 que no se usa (en este momento, había otro controlador allí antes). en la foto. Puede ver una sola resistencia de 100 ohmios sentada allí que conecta todos los CANL y CANH juntos. Y todo funciona bien a 500kb/s.
No estoy sugiriendo que esta sea la manera correcta de hacer las cosas. Todo lo que digo es que a esta distancia y velocidad, sin interferencias y con potencia estable, todos esos detalles finos y conocimientos técnicos simplemente no importan.
Entonces, esto es lo que estoy sugiriendo.
Tus esquemas están bien. Asegúrese de que todos los RX, TX, CANL, CANH estén conectados de acuerdo con esto (incluso si sabe que están bien, nunca está de más comprobarlo).
Deje esas resistencias de 120 ohmios en los módulos.
Puede conectar las tierras de dos TJA1050 juntos si lo desea, pero si su configuración es como la mía, no importa en absoluto, ya que todos se alimentan del mismo suministro y la distancia es insignificante.
Conecte su analizador lógico para medir TX (a tierra) en el lado de envío y RX (a tierra) en el lado de recepción. Creo que esto ya se ha sugerido al menos 3 veces, pero nunca vi los resultados.
Ejecute sus programas. Debería ver exactamente la misma señal en RX que en TX. Si no lo hace, entonces el problema está en algún lugar de la conexión CAN. Pero si lo hace, entonces el problema está en el software, muy probablemente en la configuración del filtro o la máscara.
ACTUALIZAR
El objetivo de conectar los controladores directamente era eliminar (tanto como fuera posible) el aspecto físico. Si los cables son cortos, los diodos son rápidos y el pull-up es correcto, no debería haber ninguna diferencia en los pines RX. Asegúrese de conectar el pull-up a su Vcc real (ese documento fue escrito para el sistema de 5V).
Sugiero verificar sus conexiones una vez y dejar de lado la cuestión del cableado. Centrémonos en el lado del software. Así es como lo diagnosticaría.
Minimiza tu código. Lo único que debe tener en el lado de TX es suficiente para enviar un marco de datos base una vez por segundo en un bucle. Sugiero transmitir un número de secuencia cíclico simple de un byte. Lo único que debería tener su lado RX es lo suficiente para leer este byte y tal vez imprimirlo en la depuración. No debe devolver nada para evitar contaminar la prueba.
Primero depure TX. Mencionaste que en un momento solo estabas recibiendo un mensaje. Entonces, el objetivo número 1 es asegurarse de que TX envíe esos mensajes cada segundo. Y debería verlos con su analizador lógico en ese bus de un solo cable.
Problemas comunes aquí: uso incorrecto de los búferes de transmisión, manejo incorrecto de EOT, marco de datos mal formado (ID, bits de control, etc.). También verifique cómo su biblioteca/controlador maneja el bit ACK. Técnicamente no es necesario, pero algunas implementaciones podrían intentar retransmitir el mismo mensaje una y otra vez hasta que se reciba ACK, bloqueando así los búferes Tx para que no obtengan nuevos datos.
Problemas comunes aquí: tasa de datos diferente, uso incorrecto de búferes RX, manejo incorrecto de interrupciones, filtro o máscara de filtro incorrectos. Podría ayudar configurar sus filtros para aceptar cualquier mensaje al principio.
Aunque todavía no lo he intentado (después de todo, no necesitaba CAN), la solución es actualizar dentro de STM32CubeMX, la biblioteca HAL F1 a 1.7 (o superior), donde la implementación de CAN se ha corregido/cambiado.
Arce
Arce
michel keijzers
Arce
Arce
michel keijzers
Pedro Mortensen
Pedro Mortensen
michel keijzers
michel keijzers
Pedro Mortensen
Pedro Mortensen
michel keijzers
Lundin
Lundin
michel keijzers
Arce
michel keijzers
Lundin
Lundin
Lundin
Jeroen3
michel keijzers
Lundin
michel keijzers
Arce
michel keijzers
michel keijzers
aldaba_d
michel keijzers