cancel
Showing results for 
Search instead for 
Did you mean: 

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

Zek_De
Senior

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?

4 REPLIES 4

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
Up vote any posts that you find helpful, it shows what's working..
T J
Lead

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
Senior

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

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
Up vote any posts that you find helpful, it shows what's working..