cancel
Showing results for 
Search instead for 
Did you mean: 

Send more than 8 bytes over Standard CAN bus in STM32CubeIDE

Ali Suleimani
Associate II

Hi

I am trying to send more than 8 bytes over standard CAN Bus but I do not know how to do that. I know it must be possible but I tried different method but it didn't work. 

I get three floating point values voltage, temperature and SOC. Each of them is 4 bytes so in total 12 bytes. I get the values from the main_function(dev_address) and send them to SendFloatsOverCAN(). here is my code:

while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
   main_function(dev_address);
  SendFloatsOverCAN(&hcan2, voltage, temperature, SOC);
  HAL_Delay(500);
  }
here I call the SendFloatsOverCAN() function: 
 void SendFloatsOverCAN(CAN_HandleTypeDef *hcan, float voltageVal, float temperatureVal, floats SOC){
  TxHeader.DLC = 8;  // this specifies the length of the data that will be send //8
   TxHeader.ExtId = 0;  // since we use standard protocol we set it to zero
   TxHeader.IDE = CAN_ID_STD; // the IDE is the standard ID
   TxHeader.RTR = CAN_RTR_DATA;  // we send data not frame
   TxHeader.StdId = 0x102;  // this is the identifire, must check why 0x103
   TxHeader.TransmitGlobalTime = DISABLE;
  
    HAL_CAN_AddTxMessage(&hcan2, &TxHeader, TxData, TxMailbox);
    }
Here I receive the sending message

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData); // data will be recieved from CAN_RX_FIFO0, the header will be stored in RxHeader, data will be saved in RxData

}

I can send and receive the first two floating point values but when I try to send the third one SOC it gets trouble. There must be a way to solve this problem, maybe using multiple message but I do not know how solve this. would be greatful if someone could explain a little bit with some lines of code. 

 

3 REPLIES 3

Split the data over multiple packets. Perhaps use different message ID's or create an eight byte structure which contains an index or sequence number so you can identify what type of data a specific packet contains.

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

TxHeader.StdId = msgtype; // where msgtype 0x102 VOLTAGE, 0x103 TEMPERATURE, 0x104 SOC

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Karl Yamashita
Lead II

You can use something like a target ID. So when you want to send voltage data, you can use a parameter to indicate it's a voltage value being sent, or Temperature. You can also use a requesting ID that indicates where the voltage/temperature is coming from. 

 

enum reqId
{
	ENGINE = 1,
	DRV_SEAT,
	PASS_SEAT,
	BATTERY_VOLTAGE
};

enum targId
{
	VOLTAGE,
	TEMPERATURE,
	SOC
};

typedef union{
	struct{
		uint8_t data[8];
	}Bytes;
    struct{
        unsigned RequestID:3;
        unsigned TargetID:3;
        unsigned :26;
        uint32_t data;
    }Status;
}TelemetryDataStruct;

TelemetryDataStruct telemInfo = {0};

// called from inside main while loop
void PollingRoutine(void)
{
	{  // voltage, current and SOC updated elsewhere
		voltage = 12.4;
		temperature = 32.9;
	}

	if(newVoltageFlag)
	{
		newVoltageFlag = 0;
		SomeFunction(ENGINE, VOLTAGE, voltage);
		SendCAN_Data();
	}
	else if(newTempFlag)
	{
		newTempFlag = 0;
		SomeFunction(ENGINE, TEMPERATURE, temperature);
		SendCAN_Data();
	}
}

void SomeFunction(uint32_t r_id, uint32_t t_id, double value)
{
	uint32_t data;

	data = ConvertTo32(value); // some function to convert float to 32bit value

    telemInfo.Status.RequestID = r_id; // Engine
    telemInfo.Status.TargetID = t_id; // voltage
    telemInfo.Status.data = data; // 32 bit data
}

void SendCAN_Data(void)
{
	// update pTxHeader accordingly
    HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &pTxHeader, telemInfo.Bytes.data);
}

 

If you find my answers useful, click the accept button so that way others can see the solution.