Skip to main content
Zek_De
Senior
August 11, 2018
Question

How can I get all data on CAN using a lot of devices in a lump

  • August 11, 2018
  • 4 replies
  • 783 views

Hello friends,

I have to use CAN protocol that I have a lot of devices.

How can I get all data in a lump.

Is there a way by hardware or I have to control data with software like USART.

Any offer?

    This topic has been closed for replies.

    4 replies

    Tesla DeLorean
    Guru
    August 11, 2018

    You set the filters to accept all IDs, and then read the whole packets out of the FIFOs as they are received.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    T J
    Senior III
    August 11, 2018

    I use a large array of Rx packets

    under interrut, I stuff the received packet into the buffer and exit.

    under a worker thread, I check the packet storage and process any new packets.

    I only look at MsgIDs in the ranges 0x400 - 0x5FF and 0x600-0x6FF 
     
    This is my Startup init code:
     
    char canRxString [1024];
    uint16_t canRxMsgID [64];
    uint8_t canRxMsgLength [64];
    uint32_t canRxMsgBottomWord [64];
    uint32_t canRxMsgTopWord [64];
    char 	 canRxHaveSegmentID [64];							
     
    char canTxString[1024];
    uint16_t canTxMsgID [64];
    uint8_t canTxMsgLength [64];
    uint32_t canTxMsgBottomWord [64];
    uint32_t canTxMsgTopWord [64];
     
     
     
     
     
     
    in HAL void CAN_Config() {
    :
    .
    .
    .
     
    	
     //##-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(__FILE__, __LINE__);
     char string[38];
     
     sprintf( string, "Can Filter configuration Error\n\r");
     puts1( 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(__FILE__, __LINE__);
     char string[38];
     sprintf( string, "Can Filter configuration Error\n\r");
     puts1( string);
     }
     
     
     
    after HAL Can init code:
     
    void initCairoCan(void) {
     CAN_Config();
     canRxpointerIN = 0;
     canRxMsgIN = 0;
     canRxMsgOUT = 0;
     canRxMsgTableEMPTY = true;
     canRxMsgTableFULL = false; 
     
     for (int i = 0; i < 16; i++)
     IOCanMsgFlag[i] = false;
     
    			
    	
     __HAL_CAN_ENABLE_IT(&hcan, CAN_IT_FMP1);
     __HAL_CAN_ENABLE_IT(&hcan, CAN_IT_FMP0);
    		
     canTxMsgIN = 0;
     canTxMsgOUT = 0;
     canTxMsgTableEMPTY 		= true;
     canTxMsgTableFULL 		= false;
     canTxMsgTableOverflow = false;
     canTxMsgOverrun = false;
     blockCanTx = false;
     
    }
     
    I edited the initrrupt code :
    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 */
    }
     
     
    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 FIFO 
     
     canRxMsgLength[canRxMsgIN] =	readCanBytecount; 
     
     canRxMsgIN++;
     canRxMsgIN &= 0x3F; 	// 64 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 FIFO 
     
     if(canRxMsgTableFULL) {	
     canRxMsgTableOverflow = true; // now dump new frame...
     }else {
     canRxMsgID[canRxMsgIN] = canRxmsgID;
     canRxMsgLength[canRxMsgIN] = readCanBytecount; 	
     canRxMsgIN++;
     canRxMsgIN &= 0x3F; 	// 64 entries only
     canRxMsgTableEMPTY = false;
     if (canRxMsgIN == canRxMsgOUT)
     canRxMsgTableFULL = true;
     }
    			
     //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
     
     }
     CAN->IER |= CAN_IER_FMPIE0; 		// (11)		Set FIFO1 message pending IT enable 
     }
     //			if (length >0) puts(string);
     
    }
    inside my foreground process I call DoCan, which only checks all new RXframes before it leaves.
     
     
    void DoCan(void) {
     char string[1024];
     int length = 0;
     if (canRxMsgTableOverflow) {
     canRxMsgTableOverflow = false;
     sprintf(string, "CanFlags Table has Overflowed, new frames are being dumped\n\r"); // now dump new frame...
     puts1(string);
     }
     if (canRxMsgTableFULL) {
     canRxMsgTableFULL = false;
     sprintf(string, "CanFlags Table is Full, probably missing frames now\n\r");
     puts1(string);
     }
    			
     if (checkCanRxSensorFreshDataCompleted()) 
     showCanSensorADCArray();
     if (haveCanString)
     showCanString();
     
     			
     while (!canRxMsgTableEMPTY) {
     int canRxMsgBytecount = canRxMsgLength[canRxMsgOUT];
    					
     int16_t dataChannel 	= canRxMsgID[canRxMsgOUT];
     canRxCmdFifoBuf.d32[0] 	= canRxMsgBottomWord[canRxMsgOUT];
     canRxCmdFifoBuf.d32[1] 	= canRxMsgTopWord[canRxMsgOUT];
     
     // zero data within RxCanFrameBuffer to make sure we only use valid data, but not necessary
     canRxMsgID[canRxMsgOUT] = 0; 
     canRxMsgBottomWord[canRxMsgOUT] = 0;
     canRxMsgTopWord[canRxMsgOUT] = 0;
     canRxMsgLength[canRxMsgOUT] = 0;				
     
     /*	if (dataChannel == 0x418) 
     		while(1);
     	if (dataChannel == 0x408) 
     		while(1);
     */
     canRxMsgTableFULL = false;
     canRxMsgOUT++;
     canRxMsgOUT &= 0x3f; 		// only 16 messages
     if(canRxMsgOUT == canRxMsgIN) canRxMsgTableEMPTY = true;
    			.
    			.
    			.
    			.
    		process frame here
     
     
     
     
    the transmit function
    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
     
     
    }
     
    if ((CAN->TSR & CAN_TSR_TME1) == CAN_TSR_TME1) // (1) 
     {
    if ((CAN->TSR & CAN_TSR_TME2) == CAN_TSR_TME2) // (1) 
     {
     
     
     
    void CAN1_RX0_IRQHandler(void)
    {
     /* USER CODE BEGIN CAN1_RX0_IRQn 0 */
     //CAN_Rx0_IRQFlag = true;
     //CAN_IRQFlag = true;
     checkCanRxFifos();
     
     /* USER CODE END CAN1_RX0_IRQn 0 */
     HAL_CAN_IRQHandler(&hcan1);
     /* USER CODE BEGIN CAN1_RX0_IRQn 1 */
     
     /* USER CODE END CAN1_RX0_IRQn 1 */
    }
     
    /**
    * @brief This function handles CAN1 RX1 interrupt.
    */
    void CAN1_RX1_IRQHandler(void)
    {
     /* USER CODE BEGIN CAN1_RX1_IRQn 0 */
    // CAN_Rx1_IRQFlag = true;
    // CAN_IRQFlag = true;
     checkCanRxFifos();
     
     /* USER CODE END CAN1_RX1_IRQn 0 */
     HAL_CAN_IRQHandler(&hcan1);
     /* USER CODE BEGIN CAN1_RX1_IRQn 1 */
     
     /* USER CODE END CAN1_RX1_IRQn 1 */
    }

    Zek_De
    Zek_DeAuthor
    Senior
    August 12, 2018

    Thank you fot your help ,I will examine that code but it seems very complex​

    Tesla DeLorean
    Guru
    August 12, 2018

    I suppose if this stuff were simple we'd all be making minimum wage..

    Some of the complexity above comes from buffering the incoming packets so they can be processed in a deferred thread rather than in the interrupt/callback handler.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..