cancel
Showing results for 
Search instead for 
Did you mean: 

How to configure CAN in STM32F103 using CMSIS?

AKilo
Associate

Hi everyone! I use the STM32F103 microcontroller to work with the CAN bus. I work in the Keil v5 environment and use the CMSIS library (I took the source files for my MCU from CubeMX). However, during debug, when I send the first data frame, I get the "Bit dominant Error" error in the CAN_ESR register. For verification, I created a project in CubeMX with the same settings and there I get an "Acknowledgment Error" error (this is a must because the module is not connected to the bus, but this at least means that it sends the frame). All register values ​​in my project (using CMSIS) and the project from CubeMX coincide except for the WKUI bit in the CAN_MSR register (it is not installed in my project, but it is installed in the CubeMX project). I think that in my project the CAN controller does not exit Sleep Mode since an invalid signal is on the Rx pin. However, I don’t understand why everything is normal in the CubeMX project, the values ​​of the registers are identical, maybe I'm missing something? Nzhe settings and sending packages in my project and project from CubeMX

Clocking:

0690X00000AqQZzQAN.jpg

Pin configuration

0690X00000AqQaYQAV.jpg

CAN Settings

hcan.Instance = CAN1;
		hcan.Init.Prescaler = 15;
		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 = ENABLE;
		hcan.Init.NART = ENABLE;
		hcan.Init.RFLM = DISABLE;
		hcan.Init.TXFP = DISABLE;
		if (HAL_CAN_Init(&hcan) != HAL_OK)
		{
			Error_Handler();
		}
		hcan.pTxMsg = &TxMessage;
		hcan.pRxMsg = &RxMessage;
	
	
	 sFilterConfig.FilterNumber = 0;
	 sFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;
	 sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;
	 sFilterConfig.FilterIdHigh = 0x0000;
	 sFilterConfig.FilterIdLow = 0x0020;
	 sFilterConfig.FilterMaskIdHigh = 0x0000;
	 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();
	 }
	 hcan.pTxMsg->StdId = 0x1;
	 hcan.pTxMsg->ExtId = 0x0;
	 hcan.pTxMsg->RTR = CAN_RTR_DATA;
	 hcan.pTxMsg->IDE = CAN_ID_STD;
	 hcan.pTxMsg->DLC = 5;
	 hcan.pTxMsg->Data[0] = 0xEE;
	 hcan.pTxMsg->Data[1] = 0xDD;
	 hcan.pTxMsg->Data[2] = 0xCC;
	 hcan.pTxMsg->Data[3] = 0xBB;
	 hcan.pTxMsg->Data[4] = 0xAA;

And sending a message

hcan.Instance->MCR &= ~(0x00010000); //Reset bit DBF for debug
  while (1)
  {
		HAL_CAN_Transmit(&hcan, 200);
		HAL_Delay(1000);
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }

And here are my settings using the CMSIS library

Clocking:

void RCC_Init(void){
	Clock_init RCC_ini;
	
	RCC_ini.Clock_source 					= PLLCLK;
	RCC_ini.PLLXTPRE 							= PLLXTPRE_Source_HSE;
	RCC_ini.PLLSRC 								= PLL_Source_HSE;
	RCC_ini.PLLMULL 							= PLL_4;
	RCC_ini.AHB_Prescaller 				= AHB_Prescaller_Div2;
	RCC_ini.APB1_Prescaller 			= APB1_Prescaller_Div1;
	RCC_ini.APB2_Prescaller 			= APB2_Prescaller_Div1;
	
	Clock_Friquency_init(&RCC_ini);
}

Pin and CAN configuration

void CAN_Init(void){
	/*************  GPIO Settings	*************/
	//	PA11(PB8) - CAN_RX  Input floating (Default) / Input pull-up
	//	PA12(PB9) - CAN_TX	Alternate function push-pull
	///////////////////////////////////////////////////////////////
	RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
	GPIOB->CRH &= ~(GPIO_CRH_CNF9 | GPIO_CRH_MODE9);
	GPIOB->CRH |= GPIO_CRH_CNF9_1 | GPIO_CRH_MODE9_0;
	GPIOB->CRH &= ~(GPIO_CRH_CNF8 | GPIO_CRH_MODE8);
	GPIOB->CRH |= GPIO_CRH_CNF8_0;
	//GPIOB->ODR |= GPIO_ODR_ODR8;
	/*************  CAN Settings	*************/
	RCC->APB1ENR |= RCC_APB1ENR_CAN1EN;
	CAN1->MCR &= ~CAN_MCR_SLEEP; //Leave Sleep mode
	CAN1->MCR |= CAN_MCR_INRQ; //Enter to Initialization mode
	while(!(CAN1->MSR&CAN_MSR_INAK));
	CAN1->MCR &= ~CAN_MCR_DBF; 
	CAN1->MCR |= CAN_MCR_NART | CAN_MCR_ABOM | CAN_MCR_AWUM;
	////////////Bit timing setting////////////
	/*Calculated with special calculator*/
	//Prescaler 8
	//BS1 13 tq
	//BS2 2 tq
	CAN1->BTR = 0x001c000e;
//	CAN1->BTR |= CAN_BTR_LBKM;	 // Turn on Silent and Loop Back Modes   
 
	CAN1->MCR &= ~CAN_MCR_INRQ; // Leave the Initailization mode
	while((CAN1->MSR&CAN_MSR_INAK)); //Wait until leave Initialization mode
	////////////Filters setting////////////
	CAN1->FMR &= ~CAN_FMR_CAN2SB; //Clear numder of filter banks
	CAN1->FMR |= CAN_FMR_FINIT;		//Enter to filter init mode
	CAN1->FMR |= (0x1U)<<8;   //Use 1 filter bank
	CAN1->FM1R |= CAN_FM1R_FBM0; // filter in Identifier List Mode
	CAN1->FS1R &= ~CAN_FS1R_FSC0; // Dual 16-bit scale configuration
	//The massage passing through this filter will be stored in FIFO 0 FFA1R = 0
	CAN1->sFilterRegister[0].FR1 = 0x20; // STDID = 0x1, RTR = 0, IDE = 0; EXTID = 0;
	CAN1->FMR &= ~CAN_FMR_FINIT; //Enter to Active filters mode
	CAN1->FA1R |= CAN_FA1R_FACT0; // Activate Filter
}

And sending a message

while(1){
		CAN1->sTxMailBox[0].TDTR = (0x1U) | (0x1U<<2);
		CAN1->sTxMailBox[0].TIR = 0;
		CAN1->sTxMailBox[0].TIR |= (0x1U<<21);
		CAN1->sTxMailBox[0].TDHR = 0xAA;
		CAN1->sTxMailBox[0].TDLR = (0xBB<<24) | (0xCC<<16) | (0xDD<<8) | (0xEE<<0);
		CAN1->sTxMailBox[0].TIR |= CAN_TI0R_TXRQ;
		delay_ms(500);
	}

 Here is a calculator with which I counted bit timings:

http://www.bittiming.can-wiki.info/#bxCAN

0 REPLIES 0