Monday, 23 February 2015

can - STM32 HAL_CAN_Transmit always returns TIMEOUT (HAL_CAN_STATE_TIMEOUT)


Setup


I am using an STM32F103C8T6 (aka Blue Pill). With the STM32Cube I set CAN_RX to PB8 and CAN_TX9 to PB9 (these are defaults/nonchangeable).


Circuit


schematic


simulate this circuit – Schematic created using CircuitLab



Components in above circuit:



  • STM #1: STM32F103C8T6

  • STM #2: STM32F103C8T6

  • Transceiver #1: TJA1050 based transceiver (see TJA 1050)

  • Transceiver #2: TJA1050 based transceiver (see TJA 1050)


I found out the TJA1050 works on 5V and the output VCCs from STM32 are 3.3V, so I used a breadboard power supply to give 5V to Transceiver 1 and 2 VCC. I assume the USB GNDs are coupled to the GNDs of the STM32s (probably internally since I didn't do any specific wiring), same as the USB +5V is coupled to the VCC of the STMs.


The transceivers already contain 120 ohm resistors so I assume I don't need any additional. The current distance between CANL and CANH of transceiver #1 and #2 is about 10 cm / 4" (simple wire). In my real application it will be about 2 meters.


Also I assume that the CAN TX needs to be connected to the Tranceiver's TX (and RX to RX).



Can Settings


The generated CAN settings are below. This executes ok.


/* 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();
}
}

Program


(removed STM generated comments blocks)



Transmitter:


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

Receiver (interrupt code is never called):


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

within main:


if (HAL_CAN_Receive_IT(&hcan, CAN_FIFO0) != HAL_OK)
{
Error_Handler();

}

Loopback mode


When I use loopback mode:


hcan.Init.Mode = CAN_MODE_LOOPBACK 

instead of Normal mode, I can transmit and receive messages (and the hcan shows the correct data in the received message).


Problem


However, in Normal mode (as shown in the code fragment above) I always get a timeout in the next command:


 if (HAL_CAN_Transmit(&hcan, 10) != HAL_OK)


The function returns: HAL_CAN_STATE_TIMEOUT within this fragment (default HAL code):


/* 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;
}
}

}

All initialization seems to be ok (all functions return HAL_OK).


Analysis


What I tried/checked was:



  • Using another STM32: no difference

  • Using another transceiver: no difference

  • Played a bit with the SJW/BS1/BS2 time quantities: no difference

  • Making sure the time quantities were equal


  • Playing with different data values and filters: no difference

  • Checked the output of PB9 (CAN transmit): it seems not to change at all (so this is a problem): no difference

  • Removing the wire from GPIO PB9 (CAN Tx) to the TX of my CAN transceiver : no difference.

  • Checking the Transmit is cancelled (which is needed and was an old bug, but has already been fixed by the HAL library I'm using).

  • Checking the resistance between CANL and CANH which moves between 63 and 70 ohms.

  • Checking the voltage between CANL and CANH (while not sending after the error). 0 Voltage; I wouldn't expect this.


Questions



  1. Why do I get a timeout? I'm having a hard time trying to find more to check what I already did.



Related question:


Update


This is an old question, but trying again to get CAN working with same bad result (timeout). I changed some settings and updated the information above accordingly.




No comments:

Post a Comment

arduino - Can I use TI's cc2541 BLE as micro controller to perform operations/ processing instead of ATmega328P AU to save cost?

I am using arduino pro mini (which contains Atmega328p AU ) along with cc2541(HM-10) to process and transfer data over BLE to smartphone. I...