2017-07-07 10:40 AM
Hi everyone,
I'm trying to receive a msg via CAN-bus in interrupt mode with STM32F105 mcu. I set the CAN filter so that only 0x0106 and 0x010A IDs are allowed. This is the first time I use this microcontroller so I'm not completely sure of the code. Can you help me?
/* Main Code*/
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_ADC1_Init(); MX_CAN1_Init(); MX_IWDG_Init(); MX_RTC_Init(); MX_SPI1_Init(); MX_TIM1_Init(); MX_TIM2_Init(); MX_UART4_Init(); MX_UART5_Init();/* USER CODE BEGIN 2 */
/* Initialize CAN Filter */ CAN_FilterConfTypeDef sFilterConfig; sFilterConfig.FilterNumber=0; sFilterConfig.FilterMode=CAN_FILTERMODE_IDMASK; sFilterConfig.FilterScale=CAN_FILTERSCALE_16BIT; sFilterConfig.FilterIdHigh=0x010A; sFilterConfig.FilterIdLow=0x0106; sFilterConfig.FilterMaskIdHigh=0x0000; sFilterConfig.FilterMaskIdLow=0x0000; sFilterConfig.FilterFIFOAssignment=0; sFilterConfig.FilterActivation=ENABLE; sFilterConfig.BankNumber=0; HAL_CAN_ConfigFilter(&hcan1,&sFilterConfig); if (HAL_CAN_ConfigFilter(&hcan1,&sFilterConfig) != HAL_OK) { Error_Handler(); }HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_3); /* USER CODE END 2 *//* Infinite loop */
/* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE *//* USER CODE BEGIN 3 */
/* Counts time, if no msg arrives after a certain time, assume something is broken and set arbitrarily to 75% the duty cycle */ HAL_CAN_Receive_IT(&hcan1,CAN_FIFO0);//other code..
HAL_Delay(delay);
} /* USER CODE END 3 */}
/* CAN1 init function */
static void MX_CAN1_Init(void){hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 11; hcan1.Init.Mode = CAN_MODE_NORMAL; hcan1.Init.SJW = CAN_SJW_1TQ; hcan1.Init.BS1 = CAN_BS1_1TQ; hcan1.Init.BS2 = CAN_BS2_1TQ; hcan1.Init.TTCM = DISABLE; hcan1.Init.ABOM = DISABLE; hcan1.Init.AWUM = DISABLE; hcan1.Init.NART = DISABLE; hcan1.Init.RFLM = DISABLE; hcan1.Init.TXFP = DISABLE; if (HAL_CAN_Init(&hcan1) != HAL_OK) { Error_Handler(); }}
And in the interrupt section
void CAN1_RX0_IRQHandler(void)
{ /* USER CODE BEGIN CAN1_RX0_IRQn 0 *//* USER CODE END CAN1_RX0_IRQn 0 */
HAL_CAN_IRQHandler(&hcan1); /* USER CODE BEGIN CAN1_RX0_IRQn 1 *///my own code
HAL_Delay(delay);
/* USER CODE END CAN1_RX0_IRQn 1 */#stm32f105-can-bus2017-07-07 10:47 AM
sFilterConfig.FilterMode=CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale=CAN_FILTERSCALE_16BIT;
sFilterConfig.FilterIdHigh=0x10A << 5; // Standard ID top 11-bits
sFilterConfig.FilterIdLow=0x106 << 5;
sFilterConfig.FilterMaskIdHigh=0x7FF << 5; // It is a MASK, remember something AND'd with zero is ZERO
sFilterConfig.FilterMaskIdLow=0x7FF << 5;
>>
This is the first time I use this microcontroller so I'm not completely sure of the code.
Reading and understanding the relevant parts of the Reference Manual will help considerably.
2017-07-07 12:49 PM
Thinking this is nonsense. What on earth is the baud rate here?
hcan1.Init.Prescaler = 11;
hcan1.Init.SJW = CAN_SJW_1TQ;
hcan1.Init.BS1 = CAN_BS1_1TQ;
hcan1.Init.BS2 = CAN_BS2_1TQ;
2017-07-07 12:53 PM
This is code automatically generated with STM32CubeMX. The baudrate I wanted to set is 1Mbps and with the program I mentioned before I set the Prescaler so that the Time for One Bit is 1031ns
2017-07-07 02:06 PM
If the APB is clocking at 36 MHz you've achieved 1.091 Mbps
2017-07-07 02:23 PM
The APB frequence is 32Mhz, after checking some documentation online my choice is Prescaler=4, Time Quanta in Bit Segment 1=6 and Time Quanta in Bit Segment 2=1.
If I'm not mistaken, thanks to the HAL_Receive_IT function when a msg arrives the micro checks the can's routine which is CAN1_RX0_IRQHandler, isn't it? The way I used these functions is correct?
Thanks for your patience, I realize these questions may be stupid but as I mentioned before this is my very first time programming a microcontroller, so I still have to learn many things
2017-07-07 07:06 PM
I have this for my receive interrupt:
void CEC_CAN_IRQHandler(void)
{ /* USER CODE BEGIN CEC_CAN_IRQn 0 */ CAN_IRQFlag = true; checkCanRxFifos();/* USER CODE END CEC_CAN_IRQn 0 */
HAL_CAN_IRQHandler(&hcan); /* USER CODE BEGIN CEC_CAN_IRQn 1 *//* USER CODE END CEC_CAN_IRQn 1 */
}checkCanRxFifos
is how I pull the data from the fifos, before HAL upsets my flags...
void checkCanRxFifos(void){ int readCanBytecount; char canFifo1FullFlag = CAN->RF1R & CAN_RF1R_FMP1; if(canFifo1FullFlag){ { readCanBytecount = (CAN->sFIFOMailBox[1].RDTR &0x0f); canRxMsgBottomWord[canRxMsgIN] = CAN->sFIFOMailBox[1].RDLR; canRxMsgTopWord [canRxMsgIN] = CAN->sFIFOMailBox[1].RDHR;canRxMsgID [canRxMsgIN] = CAN->sFIFOMailBox[1].RIR >> 21;
CAN->RF1R |= CAN_RF1R_RFOM1; // release FIFOcanRxMsgLength [canRxMsgIN] = readCanBytecount; // was 0x10+ to signify FIFO1
++ canRxMsgIN &= 0x3F; // 16 entries only canRxMsgTableEMPTY = false; if( canRxMsgIN == canRxMsgOUT) canRxMsgTableFULL = true;}
CAN->IER |= CAN_IER_FMPIE1; // (11) Set FIFO1 message pending IT enable }char canFifo0FullFlag = CAN->RF0R & CAN_RF0R_FMP0;
if(canFifo0FullFlag){ { readCanBytecount = (CAN->sFIFOMailBox[0].RDTR &0x0f);canRxMsgBottomWord[canRxMsgIN] = CAN->sFIFOMailBox[0].RDLR;
canRxMsgTopWord [canRxMsgIN] = CAN->sFIFOMailBox[0].RDHR;uint32_t canRxmsgID = CAN->sFIFOMailBox[0].RIR >> 21;
CAN->RF0R |= CAN_RF0R_RFOM0; // release FIFOif ( canRxMsgTableFULL){
canRxMsgTableOverflow = true; // now dump new frame... }else{ canRxMsgID [canRxMsgIN] = canRxmsgID; canRxMsgLength [canRxMsgIN] = readCanBytecount; // to signify FIFO0 ++ canRxMsgIN &= 0x3F; // 16 entries only canRxMsgTableEMPTY = false; if( canRxMsgIN == canRxMsgOUT) canRxMsgTableFULL = true; } // show data//length = sprintf(string + length,'%08X, %08X :W',canFifoBuf.d32[0],canFifoBuf.d32[1]);
// for( int i = 0; i < readCanBytecount; i++){// // canRxBuffer[canRxpointerIN++] = canFifoBuf.d8[i]; // canRxpointerIN &= 0xFF;// if (canRxpointerIN == canRxpointerOUT ) CanRxbufferOverrun = true;// //length += sprintf(string + length,'%02X, ',canFifoBuf.d8[i]);// }//sprintf(string + length -2,'\n\r'); // remove 2 bytes, the last comma and space
//canFifo0FullFlag = CAN->RF0R & CAN_RF0R_FMP0; } CAN->IER |= CAN_IER_FMPIE0; // (11) Set FIFO1 message pending IT enable }// if (length >0) puts(string);}
2017-07-08 02:37 AM
I think the code you posted is already implemented inside the functions called in HAL_CAN_IRQHandler(&hcan1) inside the interrupt section. When I tested my board it seems like it never executes the interrupt routine, and I think that's because of my lines of code. The problem is there are some examples but they refer to the STM32F103 and I don't know if they're valid for the STM32F105 too
2017-07-08 03:09 AM
I run this before the while(1)
//init interrupts;
__HAL_CAN_ENABLE_IT (&hcan, CAN_IT_FMP1);
__HAL_CAN_ENABLE_IT (&hcan, CAN_IT_FMP0);2017-07-08 03:52 AM
These enable are already present in the HAL_CAN_Receive_IT function, so I don't think that's what doesn't allow me to receive any message