cancel
Showing results for 
Search instead for 
Did you mean: 

CAN Transmit timeout error

Dennis Röbisch
Associate II
Posted on March 27, 2017 at 18:54

Hi everyone, I�m using a STM32F103 with SW4STM32 and CubeMX and I`m struggeling with the CAN Communication. When I`ll try to transmit Data with HAL_CAN_Transmit then I get a timeout error. Like I read here in other threads it could be a bug from the HAL library but I dont`t know how to solve this problem. Or it could be a problem with my code. So I hope someone can help me.

Here is my code. If you need some other parts of it I`ll post it too.

Thanks for your support

int main(void)

{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  HAL_Init();

  /* Configure the system clock */

  SystemClock_Config();

  /* Initialize all configured peripherals */

  MX_GPIO_Init();

  MX_SPI1_Init();

  MX_USART1_UART_Init();

  MX_CAN_Init();

  /* USER CODE BEGIN 2 */

  __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);

  /* USER CODE END 2 */

  /* Infinite loop */

  /* USER CODE BEGIN WHILE */

  HAL_GPIO_WritePin(GPIOD, USBEnable_Pin, GPIO_PIN_SET);

  HAL_GPIO_WritePin(GPIOD, canRS_Pin, GPIO_PIN_SET);

  HAL_UART_Receive_IT(&huart1,&Rx_data, 1);

  printf('welcome\r\n');

  uint16_t SOC = 5500;

  uint16_t BatVoltage = 590;

  uint16_t cellVoltageMax = 3900;

  uint16_t cellVoltageMin = 3800;

  uint8_t tempMax = 50;

  uint8_t tempMin = 47;

  while (1)

  {

     printf('Test\r\n');

     hcan.pTxMsg->Data[0] = 0b01110000;

     hcan.pTxMsg->Data[1] = (uint8_t) (SOC/1000);

     hcan.pTxMsg->Data[2] = (uint8_t) ((BatVoltage & 0b111111111111) >> 4);

     hcan.pTxMsg->Data[3] = (uint8_t) (((BatVoltage << 12) | ((cellVoltageMax & 0b0001111000000000) >> 1)) >> 8);

     hcan.pTxMsg->Data[4] = (uint8_t) (((cellVoltageMax & 0b0000000111110000) >> 1) | ((cellVoltageMin & 0b0001110000000000) >> 10));

     hcan.pTxMsg->Data[5] = (uint8_t) (((cellVoltageMin & 0b0000001111110000) >> 2) | (tempMax >> 6));

     hcan.pTxMsg->Data[6] = (uint8_t) ((tempMax << 2) | (tempMin >> 6));

     hcan.pTxMsg->Data[7] = (uint8_t) (tempMin << 2);

     printf('Data[0]: %d\r\n', hcan.pTxMsg->Data[0]);

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

            {

              /* Transmition Error */

              //Error_Handler();

         printf('CAN Transmit Error\r\n');

            }

     printf('%d\r\n', HAL_CAN_GetState(&hcan));

     HAL_Delay(1000);

  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

  }

  /* USER CODE END 3 */

}

/** System Clock Configuration

*/

void SystemClock_Config(void)

{

  RCC_OscInitTypeDef RCC_OscInitStruct;

  RCC_ClkInitTypeDef RCC_ClkInitStruct;

    /**Initializes the CPU, AHB and APB busses clocks

    */

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

  RCC_OscInitStruct.HSEState = RCC_HSE_ON;

  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;

  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;

  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

  {

    Error_Handler();

  }

    /**Initializes the CPU, AHB and APB busses clocks

    */

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

  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;

  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)

  {

    Error_Handler();

  }

  HAL_RCC_MCOConfig(RCC_MCO, RCC_MCO1SOURCE_PLLCLK, RCC_MCODIV_1);

    /**Configure the Systick interrupt time

    */

  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick

    */

  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */

  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

}

/* CAN init function */

static void MX_CAN_Init(void)

{

  CAN_FilterConfTypeDef  sFilterConfig;

  static CanTxMsgTypeDef        TxMessage;

  static CanRxMsgTypeDef        RxMessage;

  hcan.Instance = CAN1;

  hcan.pTxMsg = &TxMessage;

  hcan.pRxMsg = &RxMessage;

  hcan.Init.Prescaler = 4;

  hcan.Init.Mode = CAN_MODE_NORMAL;

  hcan.Init.SJW = CAN_SJW_2TQ;

  hcan.Init.BS1 = CAN_BS1_12TQ;

  hcan.Init.BS2 = CAN_BS2_5TQ;

  hcan.Init.TTCM = DISABLE;

  hcan.Init.ABOM = ENABLE;

  hcan.Init.AWUM = ENABLE;

  hcan.Init.NART = DISABLE;

  hcan.Init.RFLM = DISABLE;

  hcan.Init.TXFP = DISABLE;

  if (HAL_CAN_Init(&hcan) != HAL_OK)

  {

    Error_Handler();

  }

  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(&hcan, &sFilterConfig) != HAL_OK)

   {

     /* Filter configuration Error */

     Error_Handler();

   }

   hcan.pTxMsg->StdId = 0x100;

   hcan.pTxMsg->ExtId = 0x0;

   hcan.pTxMsg->RTR = CAN_RTR_DATA;

   hcan.pTxMsg->IDE = CAN_ID_STD;

   hcan.pTxMsg->DLC = 8;

}

#can-timeout #can #stm32f103
21 REPLIES 21
T J
Lead
Posted on March 28, 2017 at 13:39

Can is a great unit when it works.

my implementation uses a BxCan.

Do you have a slave connected ?

I use the CAN-DO unit from UK to monitor the line and send specialised packets and send lots of rubbish packets too, it's great for testing.

do you have approx 60ohms line impedance ?

for a short run anything under 200ohms is ok, but best to stay above or on 60ohms.

My code triggers the HAL system at startup, then I just fiddle the buffers after that for higher throughput with lower overhead for the processor.

its late now just south of cyclone Daisy...

Dennis Röbisch
Associate II
Posted on March 30, 2017 at 00:53

Hi marsh.nick,

i have connected a PCAN-USB from Peak System to monitor the packets. The only message it shows is 'stuff error' but i dont know how to handle this.

60 Ohms impedance should also exist.

T J
Lead
Posted on March 30, 2017 at 01:05

I use this to initialise my 1km line,

void MX_CAN_Init(void)
{
 hcan.Instance = CAN;
 hcan.Init.Prescaler = 150;
 hcan.Init.Mode = CAN_MODE_NORMAL;
 hcan.Init.SJW = CAN_SJW_1TQ;
 hcan.Init.BS1 = CAN_BS1_13TQ;
 hcan.Init.BS2 = CAN_BS2_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;
 if (HAL_CAN_Init(&hcan) != HAL_OK)
 {
 Error_Handler();
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Posted on March 30, 2017 at 01:01

hi,

I haven't seen a stuff error, are you sure the wires are not swapped around ?

are you sure about the baud rate ?

I started by sending data from the Can-Do unit, and making my receiver work.

then I worked on the transmitter,

do you have a CRO ? (Oscilloscope)

Posted on March 30, 2017 at 01:06

hcan.Init.AWUM = ENABLE;  // in my code this is disabled

Dennis Röbisch
Associate II
Posted on March 31, 2017 at 17:09

hi,

indeed the wires were swapped around so the stuff error is gone.

I tried with your initialisation but still no effort. I noticed that it fills one transmit mailbox at every iteration but it doesn`t empty the used one. So at the 4th Iteration he cant take a mailbox anymore.

The CAN Receive function i havent written not yet. Could it be possible that I also need the receive function to get transmit work ?

At the oscilloscope i saw only a little peak when it gets power and then nothing happend.

Maybe my CAN_MspInit could be helpful

void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)

{

  GPIO_InitTypeDef GPIO_InitStruct;

  if(hcan->Instance==CAN1)

  {

  /* USER CODE BEGIN CAN1_MspInit 0 */

  /* USER CODE END CAN1_MspInit 0 */

    /* Peripheral clock enable */

    __HAL_RCC_CAN1_CLK_ENABLE();

 

    /**CAN GPIO Configuration    

    PD0     ------> CAN_RX

    PD1     ------> CAN_TX

    */

    GPIO_InitStruct.Pin = GPIO_PIN_0;

    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_1;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

    __HAL_AFIO_REMAP_CAN1_3();

    /* Peripheral interrupt init */

    HAL_NVIC_SetPriority(USB_HP_CAN1_TX_IRQn, 0, 0);

    HAL_NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn);

    HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 0, 0);

    HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);

    HAL_NVIC_SetPriority(CAN1_RX1_IRQn, 0, 0);

    HAL_NVIC_EnableIRQ(CAN1_RX1_IRQn);

  /* USER CODE BEGIN CAN1_MspInit 1 */

  /* USER CODE END CAN1_MspInit 1 */

  }

}

Dennis Röbisch
Associate II
Posted on April 07, 2017 at 12:02

Anyone else with some hints for me ?

T J
Lead
Posted on April 08, 2017 at 00:12

CanBX Init from Cube MX (running @ 20KHz )

void MX_CAN_Init(void)
{
 hcan.Instance = CAN;
 hcan.Init.Prescaler = 150;
 hcan.Init.Mode = CAN_MODE_NORMAL;
 hcan.Init.SJW = CAN_SJW_1TQ;
 hcan.Init.BS1 = CAN_BS1_13TQ;
 hcan.Init.BS2 = CAN_BS2_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;
 if (HAL_CAN_Init(&hcan) != HAL_OK)
 {
 Error_Handler();
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Init CanBX in Foreground (before while(1) )

void initCairoCan (void) {
CAN_Config();
 __HAL_CAN_ENABLE_IT (&hcan, CAN_IT_FMP1);
 __HAL_CAN_ENABLE_IT (&hcan, CAN_IT_FMP0);

}
void CAN_Config() {
 CAN_FilterConfTypeDef sFilterConfig;
 static CanTxMsgTypeDef TxMessage;
 static CanRxMsgTypeDef RxMessage;
//##-1- Configure the CAN peripheral #######################################
// hcan.Instance = CANx;
 hcan.pTxMsg = &TxMessage;
 hcan.pRxMsg = &RxMessage;
hcan.pTxMsg->RTR = CAN_RTR_DATA; //can be CAN_RTR_DATA or CAN_RTR_REMOTE
hcan.pTxMsg->DLC = 8; 
hcan.pTxMsg->StdId = 0x101;
hcan.pTxMsg->ExtId = 0x102;
hcan.pRxMsg->DLC = 8; 
hcan.pRxMsg->StdId = 0x101;
hcan.pRxMsg->ExtId = 0x102;
hcan.pRxMsg->RTR = CAN_RTR_DATA; //can be CAN_RTR_DATA or CAN_RTR_REMOTE
 if (HAL_CAN_Init(&hcan) != HAL_OK)
 {
 // Initiliazation Error 
 Error_Handler();
 }
//##-2- Configure the CAN Filter ###########################################
 sFilterConfig.FilterNumber = 0;
 sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
 sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
 sFilterConfig.FilterIdHigh = 0x400 << 5; //11-bit ID in top bits
 sFilterConfig.FilterIdLow = 0x0000;
 sFilterConfig.FilterMaskIdHigh= 0x600 << 5;// resolves as 0x0400 - 0x05FF
 sFilterConfig.FilterMaskIdLow= 0x0000;
 sFilterConfig.FilterFIFOAssignment= 0;
 sFilterConfig.FilterActivation= ENABLE;
 sFilterConfig.BankNumber = 0;
 if (HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
 {
 // Filter configuration Error 
 Error_Handler();
sprintf(console::string,'Can Filter configuration Error

');
console::io.puts(console::string);
 }

//##-2- Configure the 2nd CAN Filter ###########################################
 sFilterConfig.FilterNumber = 1;
 sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
 sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
 sFilterConfig.FilterIdHigh = 0x600 << 5; //11-bit ID in top bits// command channel
 sFilterConfig.FilterIdLow = 0x0000;
 sFilterConfig.FilterMaskIdHigh= 0x700 << 5;// resolves as 0x0600 - 0x06FF
 sFilterConfig.FilterMaskIdLow= 0x0000;
 sFilterConfig.FilterFIFOAssignment= 1;
 sFilterConfig.FilterActivation= ENABLE;
 sFilterConfig.BankNumber = 1;
 if (HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
 {
 // Filter configuration Error 
 Error_Handler();
sprintf(console::string, 'Can Filter configuration Error

');
console::io.puts(console::string);
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

the transmitter;

void checkCanTxMsgs(void) {// this is a non-ordered packet transmitter.
//int canMsgCounter =0;
if (!canTxMsgTableEMPTY)
if ((canTxMsgOUT != canTxMsgIN) || canTxMsgTableFULL ) // a non - ordered packet transmitter has an 8 byte payload
if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) // (1) 
{
CAN->sTxMailBox[0].TDTR = canTxMsgLength[canTxMsgOUT];// (2) length
CAN->sTxMailBox[0].TDLR = canTxMsgBottomWord[canTxMsgOUT]; // (3) 4bytes
CAN->sTxMailBox[0].TDHR = canTxMsgTopWord[canTxMsgOUT]; // (3) 4bytes
CAN->sTxMailBox[0].TIR = ((uint32_t)canTxMsgID [canTxMsgOUT] << 21 | CAN_TI0R_TXRQ); // (4)// send it now if the line is idle
// destroy old data to be sure we only transmit fresh data
// not needed
canTxMsgLength[canTxMsgOUT] = 0;
canTxMsgBottomWord[canTxMsgOUT] = 0; 
canTxMsgTopWord[canTxMsgOUT]= 0; 
canTxMsgID [canTxMsgOUT]= 0;

++canTxMsgOUT &=0x3F;// 64 buffer elements
canTxMsgTableFULL = false;
canTxMsgOverrun = false;
}
if ((canTxMsgOUT != canTxMsgIN) || canTxMsgTableFULL) // a non - ordered packet transmitter has an 8 byte payload
if ((CAN->TSR & CAN_TSR_TME1) == CAN_TSR_TME1) // (1) 
{
CAN->sTxMailBox[1].TDTR = canTxMsgLength[canTxMsgOUT];// (2) length
CAN->sTxMailBox[1].TDLR = canTxMsgBottomWord[canTxMsgOUT]; // (3) 4bytes
CAN->sTxMailBox[1].TDHR = canTxMsgTopWord[canTxMsgOUT]; // (3) 4bytes
CAN->sTxMailBox[1].TIR = ((uint32_t) canTxMsgID [canTxMsgOUT] << 21 | CAN_TI1R_TXRQ); // (4)// send it now if the line is idle
// destroy old data to be sure we only transmit fresh data
// not needed
canTxMsgLength[canTxMsgOUT] = 0;
canTxMsgBottomWord[canTxMsgOUT] = 0; 
canTxMsgTopWord[canTxMsgOUT]= 0; 
canTxMsgID [canTxMsgOUT]= 0;

++canTxMsgOUT &=0x3F;// 64 buffer elements
canTxMsgOverrun = false;
canTxMsgTableFULL = false;
}
if ((canTxMsgOUT != canTxMsgIN) || canTxMsgTableFULL) // a non - ordered packet transmitter has an 8 byte payload
if ((CAN->TSR & CAN_TSR_TME2) == CAN_TSR_TME2) // (1) 
{
CAN->sTxMailBox[2].TDTR = canTxMsgLength[canTxMsgOUT];// (2) length
CAN->sTxMailBox[2].TDLR = canTxMsgBottomWord[canTxMsgOUT]; // (3) 4bytes
CAN->sTxMailBox[2].TDHR = canTxMsgTopWord[canTxMsgOUT]; // (3) 4bytes
CAN->sTxMailBox[2].TIR = ((uint32_t) canTxMsgID[canTxMsgOUT] << 21 | CAN_TI2R_TXRQ); // (4)// send it now if the line is idle
// destroy old data to be sure we only transmit fresh data
// not needed
canTxMsgLength[canTxMsgOUT] = 0;
canTxMsgBottomWord[canTxMsgOUT] = 0; 
canTxMsgTopWord[canTxMsgOUT]= 0; 
canTxMsgID [canTxMsgOUT]= 0;

++canTxMsgOUT &=0x3F;// 64 buffer elements
canTxMsgOverrun = false;
canTxMsgTableFULL = false;
}
if (canTxMsgOUT == canTxMsgIN)canTxMsgTableEMPTY = true;
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

this was not easy to work out, but it works very well.

I used the CanDo unit from UK to transmit at the frequency I needed, then worked on the receiver first.

Then this transmitter code above was relatively easy.

Posted on April 08, 2017 at 00:18

I have replied with my code that works, but it is currently being moderated...

:(