# About the source code of this protocol

**URL:** <https://discuss.cubepilot.org/t/about-the-source-code-of-this-protocol/7088>\
**Category:** Uncategorized\
**Created:** [23 August 2021 03:22 UTC](https://discuss.cubepilot.org/t/about-the-source-code-of-this-protocol/7088 "2021-08-23T03:22:15Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![ZLL6](https://discuss.cubepilot.org/user_avatar/discuss.cubepilot.org/zll6/32/4247_2.png) [@ZLL6](https://discuss.cubepilot.org/u/ZLL6)\
**Post date:** [23 August 2021 03:22 UTC](https://discuss.cubepilot.org/t/about-the-source-code-of-this-protocol/7088/1 "2021-08-23T03:22:16Z")

</div>

/\*  
The data type ID in the node ID may be wrong, but it is because of the error that successfully avoided the conflict with the correct data type ID  
\*/

#define CAN\_ID2\_OUT ((u32)0x1109216)

//Pack the payload to be sent  
void CAN\_CustomerCode\_TX(void)  
{  
static uint32\_t tickstart\_CAN = 0;  
static uint32\_t ticksotp\_CAN = 0;  
if(tickstart\_CAN == 0)  
{  
tickstart\_CAN = HAL\_GetTick();  
}

```
ticksotp_CAN = HAL_GetTick();
if(ticksotp_CAN<tickstart_CAN)//
{
	ticksotp_CAN=0xffffffff-tickstart_CAN+ticksotp_CAN;
}
else
	ticksotp_CAN=ticksotp_CAN-tickstart_CAN;

if((ticksotp_CAN>250)&&(CAN_TX_Falg == 0))
{
	tickstart_CAN = 0;
	ticksotp_CAN = 0;
}
else
{
	return;
}	
//Battery manufacturer code
CAN_CustomerCode.gBatCode[0]= BMS_config.CustomerCode.gBatCode[0];
CAN_CustomerCode.gBatCode[1]= BMS_config.CustomerCode.gBatCode[1];      
    //Battery model code
CAN_CustomerCode.gBatCodeNumber[0]=BMS_config.CustomerCode.gBatPack[0]; 
CAN_CustomerCode.gBatCodeNumber[1]=BMS_config.CustomerCode.gBatPack[1];        	
    //Total voltage 1mV
CAN_CustomerCode.gVoltSum = BMS_config.BMS_Read.gVoltSum*100;    
    //Current current value 		
CAN_CustomerCode.gCurrent = BMS_config.BMS_Read.gCurrent*10;  
     //Average temperature    				
CAN_CustomerCode.gTemAvg = BMS_config.BMS_Read.gTemAvg; 
    //Battery pack SOC         				
CAN_CustomerCode.gSOC = BMS_config.Pack_RW_config.gSOC;    
    //Number of cycles                  	
CAN_CustomerCode.gsCycleCnt= BMS_config.Pack_RW_config.gsCycleCnt;  
    //Battery pack SOH            
CAN_CustomerCode.gSOH= BMS_config.Pack_RW_config.gSOH;                 			
memcpy(&CAN_CustomerCode.g_Volt_call,&BMSVoltTemperature.g_Volt_call,
		sizeof(CAN_CustomerCode.g_Volt_call));  
   //Design capacity of battery pack
CAN_CustomerCode.gSetPackCapacity = BMS_config.Pack_RW_config.gSetPackCapacity*10;   
   //Remaining capacity
CAN_CustomerCode.gSurpulsPackCapacity = BMS_config.Pack_RW_config.gSurpulsPackCapacity*10;  
////////////Need to fill in the real fault code////////////////
CAN_CustomerCode.gAlarm[0] = (gBitChgLowTemAlm|gBitChgLowTemAlmPrt|gBitDchgLowTemAlm | gBitDchgLowTemAlmPrt)|\
((gBitChgHighTemAlm | gBitChgHighTemAlmPrt|gBitDchgHighTemAlm | gBitDchgHighTemAlmPrt)<<1) |\
((gBitChgOverCurrentAlm|gBitChgOverCurrentAlmPrt<<2)) |\
((gBitDchgOverCurrentAlm|gBitDchgOverCurrentAlmPrt)<<3) |\
((gBitVoltDiff1MaxAlm) | (gBitVoltDiff1MaxAlmPrt) | (gBitVoltDiff2MaxAlm) |(gBitVoltDiff2MaxAlmPrt)<<6) |\
((gBitOverVoltAlm | gBitOverVoltAlmPrt)<<7) |\
((gBitUnderVoltAlm | gBitUnderVoltAlmPrt)<<8) |\
(gBitChgShortCircuit<<9) | (gBitDchgShortCircuit<<10) | (gBitSOClow<<11) |(gBit_Chg_Error<<12);
CAN_CustomerCode.gAlarm[1] = 0;

/////////////////////////	
memcpy(&CAN_CustomerCode.gXUHAO,&BMS_config.CustomerCode.gBatCodeNumber,
		sizeof(CAN_CustomerCode.gXUHAO)); 							
CCITT_CRC16Init((u8 *)(&CAN_CustomerCode.gBatCode),(sizeof(CAN_CustomerCode)-2)); 
CAN_CustomerCode.CRC16 = CCITT_CRC16;

//Put the payload to be sent into the sending array		
memcpy(CAN_Tx_payload,&CAN_CustomerCode,sizeof(CAN_CustomerCode));  

CAN_T_LEN_SUM = sizeof(CAN_CustomerCode);
gCAN_flag = 1;	

CAN_Tx_Flag = 1;

CAN_Node_Id =CAN_ID2_OUT; //Load the 29-bit ID of the data packet	

```

}  
//250ms send a complete frame once, 1ms send a packet (\<=8byte)  
u8 CAN\_TX\_BcmuMsgHandle(void)  
{  
static CanTxMsg TxMessage;  
static u8 can\_pack = 0;  
static u8 can\_send\_cnt = 0;   
u8 temp\_i = 0;  
if(CAN\_T\_LEN\_SUM \< 240)  
{   
if(CAN\_Tx\_Flag == 1)  
{  
for(temp\_i = 0;temp\_i \< 7;)  
{  
TxMessage.Data[temp\_i] = CAN\_T[can\_send\_cnt++];  
temp\_i++;  
if(can\_send\_cnt \>= CAN\_T\_LEN\_SUM)//发送到了最后一个 字节  
break;   
}   
if(can\_send\_cnt \>= CAN\_T\_LEN\_SUM)  
TxMessage.Data[temp\_i] = 0x40 | can\_pack | ((can\_pack%2) \<\< 5);  
else  
{  
TxMessage.Data[temp\_i] = can\_pack|((can\_pack%2) \<\< 5);  
}

```
		if(can_pack == 0) ///第一包数据处理
		{
			if(can_send_cnt >= CAN_T_LEN_SUM)
				TxMessage.Data[temp_i] = 0xc0;//装载尾字节
			else
				TxMessage.Data[temp_i] = 0x80;//装载尾字节
		}	

		TxMessage.DLC = temp_i+1;
		TxMessage.IDE = CAN_ID_EXT;			

		TxMessage.ExtId = CAN_Node_Id;
		CAN_Transmit(CAN, &TxMessage);	
		can_pack++;
		if(can_send_cnt >= CAN_T_LEN_SUM) //Data transmission complete flag
		{
			can_pack = 0;
			can_send_cnt = 0;
			CAN_T_LEN_SUM = 0;
			CAN_Tx_Flag = 0;
			/*If the UAVCAN transmission is over, clear the UAVCAN transmission setting*/
			if(gCAN_flag)
				gCAN_flag = 0;
		}

	}
}
return 1;

```

}  
//Check function  
void CCITT\_CRC16Init(uint8\_t const \* bytes, uint16\_t len)   
{  
uint16\_t j;  
uint8\_t i=0;  
CCITT\_CRC16 =CRC\_CCITT\_INIT;   
while (len–)   
{  
CCITT\_CRC16 ^= ((uint16\_t)bytes[i++] \<\< 8);  
for (j = 0; j \< 8; j++)  
{  
CCITT\_CRC16=(CCITT\_CRC16 & 0x8000U)?((CCITT\_CRC16 \<\< 1) ^ CRC\_CCITT\_POLY):(CCITT\_CRC16 \<\< 1);  
}  
}  
}

> [@Standard UAV Intelligent Battery UAVCAN Communication Protocol](https://discuss.cubepilot.org/t/standard-uav-intelligent-battery-uavcan-communication-protocol/6986):
>
> [BMS-UAVCAN\_Communication.zip](https://discuss.cubepilot.org/uploads/short-url/yrxA2I3sk4KNQno3EzVIw0qTJcm.zip) (244.9 KB)
