2019-10-16 05:13 AM
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:
Pin configuration
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: