2017-03-27 09:54 AM
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 #stm32f1032017-03-28 04:39 AM
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...
2017-03-29 03:53 PM
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.
2017-03-29 04:05 PM
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();
}
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2017-03-29 06:01 PM
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)
2017-03-29 06:06 PM
hcan.Init.AWUM = ENABLE; // in my code this is disabled
2017-03-31 08:09 AM
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 */
}}
2017-04-07 03:02 AM
Anyone else with some hints for me ?
2017-04-07 03:12 PM
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.
2017-04-07 05:18 PM
I have replied with my code that works, but it is currently being moderated...
:(