Configuración
Estoy usando un STM32F103C8T6 (también conocido como Blue Pill). Con el STM32Cube establecí CAN_RX en PB8 y CAN_TX9 en PB9 (estos son valores predeterminados / no modificables).
Circuito
Componentes en el circuito anterior:
- STM # 1: STM32F103C8T6
- STM # 2: STM32F103C8T6
- Transceptor # 1: Transceptor basado en TJA1050 (consulte TJA 1050 )
- Transceptor # 2: Transceptor basado en TJA1050 (consulte TJA 1050 )
Descubrí que el TJA1050 funciona en 5V y que los VCC de salida de STM32 son 3.3V, así que usé una fuente de alimentación de tablero para dar 5V al Transceiver 1 y 2 VCC. Supongo que las GND USB están acopladas a las GND de los STM32 (probablemente internamente, ya que no hice ningún cableado específico), al igual que el USB + 5V está acoplado a la VCC de los STM.
Los transceptores ya contienen resistencias de 120 ohmios, por lo que supongo que no necesito más. La distancia actual entre CANL y CANH del transceptor n. ° 1 y n. ° 2 es de aproximadamente 10 cm / 4 "(cable simple). En mi aplicación real, será de aproximadamente 2 metros.
También asumo que el CAN TX debe estar conectado al TX del Tranceiver (y RX a RX).
Configuración de latas
Las configuraciones CAN generadas están abajo. Esto se ejecuta bien.
/* 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 = 128;
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 = 0x0000;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.BankNumber = 14;
if (HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
{
Error_Handler();
}
}
Programa
(se eliminaron los bloques de comentarios generados por STM)
Transmisor:
int main(void)
{
..
/* USER CODE BEGIN 2 */
hcan.pTxMsg->StdId = 0x100;
hcan.pTxMsg->ExtId = 0x01;
hcan.pTxMsg->RTR = 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;
if (HAL_CAN_Transmit(&hcan, CAN_FIFO0) != HAL_OK)
{
Error_Handler();
}
HAL_Delay(1000);
}
}
Receptor (el código de interrupción nunca se llama):
vox RxIntEnable (CAN_HandleTypeDef * CanHandle)
{
if (CanHandle->State == HAL_CAN_STATE_BUSY_TX)
{
CanHandle->State = HAL_CAN_STATE_BUSY_TX_RX0;
}
else
{
CanHandle->ErrorCode = HAL_CAN_ERROR_NONE;
__HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_EWG); // Error warning interrupt
__HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_EPV); // Error passive interrupt
__HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_BOF); // Bus-off interrupt
__HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_LEC); // Last error code interrupt
__HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_ERR); // Error interrupt
}
__HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_FMP0); // FIFO0 message pending interrupt
}
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
{
if ((CanHandle->pRxMsg->StdId == 0x100) &&
(CanHandle->pRxMsg->IDE == CAN_ID_STD) &&
(CanHandle->pRxMsg->DLC == 2))
{
printf("1");
}
RxIntEnable(CanHandle);
}
dentro de main:
if (HAL_CAN_Receive_IT(&hcan, CAN_FIFO0) != HAL_OK)
{
Error_Handler();
}
Modo de bucle invertido
Cuando uso el modo de bucle invertido:
hcan.Init.Mode = CAN_MODE_LOOPBACK
en lugar del modo Normal, puedo transmitir y recibir mensajes (y el hcan muestra los datos correctos en el mensaje recibido).
Problema
Sin embargo, en el modo Normal (como se muestra en el fragmento de código anterior), siempre obtengo un tiempo de espera en el siguiente comando:
if (HAL_CAN_Transmit(&hcan, 10) != HAL_OK)
La función devuelve: HAL_CAN_STATE_TIMEOUT dentro de este fragmento (código HAL predeterminado):
/* Check End of transmission flag */
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;
}
}
}
Toda la inicialización parece estar bien (todas las funciones devuelven HAL_OK).
Análisis
Lo que probé / revisé fue:
- Usando otro STM32: no hay diferencia
- Usando otro transceptor: no hay diferencia
- Jugó un poco con las cantidades de tiempo SJW / BS1 / BS2: no hay diferencia
- Asegurarse de que las cantidades de tiempo fueran iguales
- Jugando con diferentes valores de datos y filtros: no hay diferencia
- Se verificó la salida de PB9 (CAN transmisión): parece que no cambia en absoluto (por lo que esto es un problema): no hay diferencia
- Eliminando el cable del GPIO PB9 (CAN Tx) al TX de mi transceptor CAN: no hay diferencia.
- La verificación de la transmisión se canceló (lo cual es necesario y era un error anterior, pero ya fue corregido por la biblioteca HAL que estoy usando).
- Comprobar la resistencia entre CANL y CANH que se mueve entre 63 y 70 ohmios.
- Comprobando el voltaje entre CANL y CANH (mientras no se envía después del error). 0 Voltaje; No esperaría esto.
Preguntas
- ¿Por qué tengo un tiempo de espera? Me cuesta mucho encontrar más para comprobar lo que ya hice.
Pregunta relacionada:
Actualizar
Esta es una pregunta antigua, pero volver a intentar que CAN funcione con el mismo resultado negativo (timeout). Cambié algunas configuraciones y actualicé la información anterior correspondiente.