Ya que soy bastante nuevo en el uso de CAN, no estoy seguro de qué información es relevante, pero intentaré describir lo mejor que pueda.
Tengo un STMF746 en el que quiero usar el bus CAN. Tengo PD0 (CAN1_Rx), PD1 (CAN1_Tx) y PG0 (modo de espera bajo) conectados a un tranceiver CAN.
Quizás debería mencionar también que estoy usando controladores HAL.
Mis ajustes de inicio son
hw_return_type can_Open(void)
{
__HAL_RCC_CAN1_CLK_ENABLE();
hcan.Instance = CAN1;
hcan.Init.Mode = CAN_MODE_NORMAL;
//Should be 125kbit with 75% sampling
hcan.Init.Prescaler = 27;
hcan.Init.BS1 = CAN_BS1_11TQ;
hcan.Init.BS2 = CAN_BS2_4TQ;
hcan.Init.SJW = CAN_SJW_2TQ;
hcan.Init.TTCM = DISABLE;
hcan.Init.ABOM = ENABLE;
hcan.Init.AWUM = DISABLE;
hcan.Init.NART = DISABLE;
hcan.Init.RFLM = DISABLE;
hcan.Init.TXFP = DISABLE;
HAL_CAN_Init(&hcan);
(&hcan)->Instance->MCR |= CAN_MCR_TXFP;
rxMsg.FIFONumber = CAN_FIFO0;
rxMsg.IDE = CAN_ID_STD;
rxMsg.RTR = CAN_RTR_DATA;
rxMsg.FMI = 0;
hcan.pRxMsg = &rxMsg;
can_SetFilter(0, 0, 0);
can_recv_fifo = utilFIFO_Create(can_recv_fifo_buf, sizeof(hw_can_msg_type), CAN_FIFO_LENGTH);
return HW_OK;
}
void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hcan->Instance==CAN1)
{
__CAN_CLK_ENABLE();
__GPIOD_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
HAL_NVIC_SetPriority(CAN1_TX_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(CAN1_TX_IRQn);
HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
HAL_NVIC_SetPriority(CAN1_RX1_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(CAN1_RX1_IRQn);
}
}
static void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 12;
RCC_OscInitStruct.PLL.PLLN = 432;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 2;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
HAL_PWREx_ActivateOverDrive();
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK |RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV4;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7);
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_USART2;
PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
Al usar un código de depuración, he encontrado que cuando trato de enviar datos continuamente, se llenan los 3 buzones y la función
static HAL_StatusTypeDef HAL_CAN_Transmit_IT_local(CAN_HandleTypeDef* hcan)
{
uint32_t transmitmailbox = CAN_TXSTATUS_NOMAILBOX;
/* Check the parameters */
assert_param(IS_CAN_IDTYPE(hcan->pTxMsg->IDE));
assert_param(IS_CAN_RTR(hcan->pTxMsg->RTR));
assert_param(IS_CAN_DLC(hcan->pTxMsg->DLC));
/* Process Locked */
__HAL_LOCK(hcan);
/* Select one empty transmit mailbox */
if((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0)
{
transmitmailbox = 0;
}
else if((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1)
{
transmitmailbox = 1;
}
else if((hcan->Instance->TSR&CAN_TSR_TME2) == CAN_TSR_TME2)
{
transmitmailbox = 2;
}
if(transmitmailbox != CAN_TXSTATUS_NOMAILBOX)
{
/* Set up the Id */
hcan->Instance->sTxMailBox[transmitmailbox].TIR &= CAN_TI0R_TXRQ;
if(hcan->pTxMsg->IDE == CAN_ID_STD)
{
assert_param(IS_CAN_STDID(hcan->pTxMsg->StdId));
hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->StdId << 21) | \
hcan->pTxMsg->RTR);
}
else
{
assert_param(IS_CAN_EXTID(hcan->pTxMsg->ExtId));
hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->ExtId << 3) | \
hcan->pTxMsg->IDE | \
hcan->pTxMsg->RTR);
}
/* Set up the DLC */
hcan->pTxMsg->DLC &= (uint8_t)0x0000000F;
hcan->Instance->sTxMailBox[transmitmailbox].TDTR &= (uint32_t)0xFFFFFFF0;
hcan->Instance->sTxMailBox[transmitmailbox].TDTR |= hcan->pTxMsg->DLC;
/* Set up the data field */
hcan->Instance->sTxMailBox[transmitmailbox].TDLR = (((uint32_t)hcan->pTxMsg->Data[3] << 24) |
((uint32_t)hcan->pTxMsg->Data[2] << 16) |
((uint32_t)hcan->pTxMsg->Data[1] << 8) |
((uint32_t)hcan->pTxMsg->Data[0]));
hcan->Instance->sTxMailBox[transmitmailbox].TDHR = (((uint32_t)hcan->pTxMsg->Data[7] << 24) |
((uint32_t)hcan->pTxMsg->Data[6] << 16) |
((uint32_t)hcan->pTxMsg->Data[5] << 8) |
((uint32_t)hcan->pTxMsg->Data[4]));
/* Set CAN error code to none */
hcan->ErrorCode = HAL_CAN_ERROR_NONE;
/* Process Unlocked */
__HAL_UNLOCK(hcan);
/* Enable Transmit mailbox empty Interrupt */
__HAL_CAN_ENABLE_IT(hcan, CAN_IT_TME);
/* Request transmission */
hcan->Instance->sTxMailBox[transmitmailbox].TIR |= CAN_TI0R_TXRQ;
}
else
{
/* Process Unlocked */
__HAL_UNLOCK(hcan);
return HAL_BUSY;
}
return HAL_OK;
}
devuelve HW_OK las primeras 3 veces (3 buzones llenos). Después de eso solo obtengo HW_BUSY, lo que para mí indica que los buzones no se vacían correctamente. Y aquí es donde estoy atrapado. Siendo bastante nuevo en cómo funciona CAN, no tengo idea de dónde debería buscar más.
Cuando miro con un analizador CAN en el bus, todo lo que puedo ver son cuadros de error que para mí no significan nada, ya que no he encontrado ninguna buena referencia a qué tipo de errores activan un cuadro de error.
Mis teorías son que quizás el registro de estado de transmisión
__IO uint32_t TSR; /*!< CAN transmit status register, Address offset: 0x08 */
no se restablece correctamente. O que no lo borre hasta que haya recibido un Ack del otro nodo en el bus.
Si alguien tiene alguna buena idea de lo que he hecho mal o de lo que me estoy perdiendo. Yo realmente aplaudiría tu ayuda.
No dude en hacer preguntas o pedir más código