Initial commit: CCU621_M firmware project with BLE debug link support.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-08 17:28:36 +08:00
commit 9ceb218f80
1597 changed files with 724159 additions and 0 deletions
+417
View File
@@ -0,0 +1,417 @@
#include "bms/sae1939.h"
/*
缩写 全称 翻译
DLL data link layer 数据链路层
*/
#define TIMEOUT_T1 750 //750ms
#define TIMEOUT_T2 1250 //1250ms
#define TIMEOUT_T3 1250 //1250ms
#define TIMEOUT_T4 1050 //1050ms
#define TP_CM_PGN 0x00EC00 //CM-多包传输的连接管理
#define TP_DT_PGN 0x00EB00 //DT-多包数据传输
#define TP_CM_RTS 16 //RTS-请求发送
#define TP_CM_CTS 17 //CTS-允许发送
#define TP_CM_ENDOFMSGACK 19 //结束应答
#define TP_CM_ABORT 255 //放弃连接
static U16_T u16_timer_count = 0; //定时其计数值
/**
* ************************************************************************
* @brief - 用于上层清除底层的多包状态
*
* @param[in] pt_dll_data - 1393层数据
*
*
* @author jiankalka
* @date 2025-08-12
* ************************************************************************
*/
void v_sae1393_clear_multi_pacet(DLL_DATA_T *pt_dll_data)
{
pt_dll_data->e_msg_state = NONE;
}
/**
* ************************************************************************
* @brief - SAE1393层发送函数,单包报文直接发送,多包报文此函数只传送RTS,多包传输处理在u32_sae1393_rx内进行
* 注:27930中 不存在多包发送,此处仅考虑发送单包数据
* @param[in] pt_dll_data - 1393层数据
* @param[in] pt_can_data - 要送的报文
*
* @return U32_T - 0:发送成功,1:发送失败
*
* @author jiankalka
* @date 2025-08-12
* ************************************************************************
*/
U32_T u32_sae1393_tx(DLL_DATA_T *pt_dll_data, CAN_DATA_T *pt_can_data)
{
CAN_DATA t_msg;
U32_T i;
U8_T SendCmd = ((pt_can_data->u32_pgn & 0x0000FF00) >> 8);
memset(&t_msg, 0, sizeof(CAN_DATA));
if (pt_can_data->u16_len <= 8)
{
//单包发送
t_msg.ID = u32_get_can_ID(pt_can_data->u8_pri,SendCmd,pt_can_data->u8_dest_addr,pt_can_data->u8_src_addr); //组帧ID
t_msg.Len = pt_can_data->u16_len;
for (i=0; i<t_msg.Len; i++)
t_msg.Data[i] = pt_can_data->u8_data[i];
return pt_dll_data->u32_can_tx(&t_msg); //这样定义有助于多个can口复用
}
return 1;
}
void v_delay_set_tymer_val(void)
{
u16_timer_count ++;
}
U32_T u32_delay_get_timer_val()
{
return u16_timer_count;
}
//计算时间间隔(单位:ms) (b+MAX-a)%MAX
U32_T u32_delay_time_elapse(U32_T tim3_cnt_start, U32_T tim3_cnt_end)
{
if(tim3_cnt_end >= tim3_cnt_start)
return (tim3_cnt_end-tim3_cnt_start)*10;
else
return (65535-tim3_cnt_end+tim3_cnt_start-1)*10;
}
/**
* ************************************************************************
* @brief - SAE1393层接收函数,接收到多包请求后 发送cts应答报文
*
* @param[in] ExtId - 帧ID
* @param[in] Pgn - 多包帧pgn
* @param[in] pack_num - 包总数
* @param[in] pack_cnt - 请求包数
* @param[in] t_tx_msg - 组帧报文内容
*
*
* @author jiankalka
* @date 2025-08-13
* ************************************************************************
*/
void v_sae1939_cts_send(U32_T ExtId,U32_T Pgn, U8_T pack_num , U8_T pack_cnt, CAN_DATA *t_tx_msg)
{
t_tx_msg->ID = (ExtId & 0xFFFF0000);
t_tx_msg->ID |= ((ExtId & 0xFF00) >> 8 ); //帧ID目标地址 源地址转换
t_tx_msg->ID |= ((ExtId & 0x00FF) << 8 );
t_tx_msg->ID = (t_tx_msg->ID & 0xFF00FFFF)|(TP_CM_PGN << 8); //将帧ID PGN赋值为0xEC
t_tx_msg->Len = 8;
t_tx_msg->Data[0] = TP_CM_CTS;
t_tx_msg->Data[1] = pack_num;
t_tx_msg->Data[2] = pack_cnt;
t_tx_msg->Data[3] = 0xFF;
t_tx_msg->Data[4] = 0xFF;
t_tx_msg->Data[5] = ((Pgn >> 16) & 0xFF);
t_tx_msg->Data[6] = ((Pgn >> 8 ) & 0xFF);
t_tx_msg->Data[7] = ((Pgn ) & 0xFF);
}
/**
* ************************************************************************
* @brief - sae1939 放弃连接发送
*
* @param[in] ExtID - 帧ID
* @param[in] Pgn - 多包帧报文对应 PGN
* @param[in] t_tx_msg - 发送can数据组包
*
*
* @author jiankalka
* @date 2025-08-13
* ************************************************************************
*/
void v_sae1939_abort_send(U32_T ExtID, U32_T Pgn, CAN_DATA *t_tx_msg)
{
t_tx_msg->ID = (ExtID & 0xFFFF0000);
t_tx_msg->ID |= ((ExtID & 0xFF00) >> 8 ); //帧ID目标地址 源地址转换
t_tx_msg->ID |= ((ExtID & 0x00FF) << 8 );
t_tx_msg->Len = 8;
t_tx_msg->Data[0] = TP_CM_ABORT;
t_tx_msg->Data[1] = 0xFF;
t_tx_msg->Data[2] = 0xFF;
t_tx_msg->Data[3] = 0xFF;
t_tx_msg->Data[4] = 0xFF;
t_tx_msg->Data[5] = ((Pgn >> 16) & 0xFF);
t_tx_msg->Data[6] = ((Pgn >> 8 ) & 0xFF);
t_tx_msg->Data[7] = ((Pgn ) & 0xFF);
}
/*************************************************************
函数名称: v_sae1939_EndofMsgACK_send
函数功能: SAE1393层接收函数,放弃连接函数
输入参数: pt_dll_data 接收报文
输出参数: t_tx_msg 发送报文
返回值 void
**************************************************************/
/**
* ************************************************************************
* @brief - 多包完成接收 发送结束应答帧
*
* @param[in] pt_dll_data - sae1939 控制数据
* @param[in] t_tx_msg - 发送组包CAN数据
*
*
* @author jiankalka
* @date 2025-08-13
* ************************************************************************
*/
void v_sae1939_EndofMsgACK_send(DLL_DATA_T *pt_dll_data, CAN_DATA *t_tx_msg)
{
t_tx_msg->ID = ((U32_T)(pt_dll_data->u8_pri & 0x07) << 26);
t_tx_msg->ID |= ((TP_CM_PGN & 0x0000FF00) << 8);
t_tx_msg->ID |= ((pt_dll_data->u8_dest_addr & 0xFF) );
t_tx_msg->ID |= ((pt_dll_data->u8_src_addr & 0x00FF) << 8 );
t_tx_msg->Len = 8;
t_tx_msg->Data[0] = TP_CM_ENDOFMSGACK;
t_tx_msg->Data[1] = (U8_T)(pt_dll_data->u16_len);
t_tx_msg->Data[2] = (U8_T)(pt_dll_data->u16_len>>8);
t_tx_msg->Data[3] = (pt_dll_data->u16_len+6)/7;
t_tx_msg->Data[4] = 0xFF;
t_tx_msg->Data[5] = (U8_T)(pt_dll_data->u32_pgn);
t_tx_msg->Data[6] = (U8_T)(pt_dll_data->u32_pgn>>8);
t_tx_msg->Data[7] = (U8_T)(pt_dll_data->u32_pgn>>16);
}
/*************************************************************
函数名称: u32_sae1393_rx
函数功能: SAE1393层接收函数,此函数需要在BMS处理层主循环内调用,
处理报文的接收和多包报文的发送,也处理1393层的超时事件
输入参数: pt_dll_data -- 1393层数据, rxMsg -- 待解析的报文
输出参数: pt_can_data -- 保存接收到的完整报文
返回值 0:接收成功,pt_can_data指向的报文可用;1:接收失败,pt_can_data指向的报文不可用
**************************************************************/
/**
* ************************************************************************
* @brief - SAE1393层接收函数,此函数需要在BMS处理层主循环内调用,处理报文的接收和多包报文的发送,也处理1393层的超时事件
*
* @param[in] pt_dll_data - 1393层控制数据
* @param[in] pt_can_data - CAN解析存储数据
* @param[in] t_rx_msg - 接收CAN数据-原报文数据
*
* @return U32_T - 1说明接收完整帧 0未接收完整帧
*
* @author jiankalka
* @date 2025-08-13
* ************************************************************************
*/
U32_T u32_sae1393_rx(DLL_DATA_T *pt_dll_data, CAN_DATA_T *pt_can_data, CAN_DATA t_rx_msg)
{
CAN_DATA t_tx_msg;
U32_T u32_ret = 0;
U32_T i, u32_pgn,u32_data;
S32_T j;
U8_T u8_src_addr, u8_dest_addr, u8_pri, u8_r_dp, u8_data_len;
u8_pri = ((t_rx_msg.ID & 0x1C000000) >> 26); //优先级
u8_r_dp = ((t_rx_msg.ID & 0x03000000) >> 24); //0
u32_pgn = ((t_rx_msg.ID & 0x00FF0000) >> 8); //pgn - 是分辨多包使用,而不是bms数据内的bgn
u8_src_addr = t_rx_msg.ID & 0xFF; //源地址
u8_dest_addr = ((t_rx_msg.ID & 0x0000FF00) >> 8); //目标
u8_data_len = t_rx_msg.Len; //数据长度
(void)u8_r_dp;
if (u32_pgn == TP_CM_PGN) //接收帧为多包连接管理帧
{
if(u8_data_len != 8) //管理帧帧长度都为8
return u32_ret;
switch(t_rx_msg.Data[0])
{
case TP_CM_RTS: //接收到对方发送的请求发送报文,回复CTS(允许发送)
if ((pt_dll_data->e_msg_state == NONE) || //一级 状态为空闲时,直接接收
(((pt_dll_data->e_msg_state == RX_WAIT_DATA_T2) || (pt_dll_data->e_msg_state == RX_WAIT_DATA_T1)) && //一级 接收状态下 重复接收相同帧
(pt_dll_data->u32_pgn == ((t_rx_msg.Data[7]<<16) | (t_rx_msg.Data[6]<<8) | t_rx_msg.Data[5])) && //二级 接受帧pgn与正在接受的数据相同
(pt_dll_data->u8_src_addr == u8_src_addr) && (pt_dll_data->u8_dest_addr == u8_dest_addr))) //二级 接收帧 目标地址和发送地址相同
{
//回复CTS
u32_data = (U32_T)((t_rx_msg.Data[7]<<16) | (t_rx_msg.Data[6]<<8) | t_rx_msg.Data[5]);
v_sae1939_cts_send(t_rx_msg.ID ,u32_data, t_rx_msg.Data[3],1, &t_tx_msg);
if (pt_dll_data->u32_can_tx(&t_tx_msg) == 0) //发送成功
{
pt_dll_data->e_msg_state = RX_WAIT_DATA_T2;
pt_dll_data->u32_time = u32_delay_get_timer_val();
pt_dll_data->u32_pgn = (t_rx_msg.Data[7]<<16) | (t_rx_msg.Data[6]<<8) | t_rx_msg.Data[5]; //记录接收多包报文的pgn,有多个多包时也先收此pgn
pt_dll_data->u8_src_addr = u8_src_addr;
pt_dll_data->u8_dest_addr = u8_dest_addr;
pt_dll_data->u8_pri = u8_pri;
pt_dll_data->u16_len = ((U16_T)(t_rx_msg.Data[2])<<8) | t_rx_msg.Data[1];
pt_dll_data->u8_packet_cnt = t_rx_msg.Data[3];
pt_dll_data->u8_retry = 0;
//等待接收数据,将缓存区置0xFF
for (i=0; i<SAE1939_MULTI_PACKET_MAX_NUM; i++)
{
memset(pt_dll_data->t_packet[i].u8_data, 0xFF, 7);
pt_dll_data->t_packet[i].u8_flag = 0;
}
}
}
else //放弃连接
{
//回复Abort
u32_data = (U32_T)((t_rx_msg.Data[7]<<16) | (t_rx_msg.Data[6]<<8) | t_rx_msg.Data[5]);
v_sae1939_abort_send(t_rx_msg.ID , u32_data, &t_tx_msg);
pt_dll_data->u32_can_tx(&t_tx_msg);
pt_dll_data->e_msg_state = NONE;
}
break;
case TP_CM_ABORT: //结束应答
if ((pt_dll_data->e_msg_state == RX_WAIT_DATA_T2) ||
(pt_dll_data->e_msg_state == RX_WAIT_DATA_T1))
{
if ((u8_src_addr == pt_dll_data->u8_src_addr) &&
(pt_dll_data->u8_dest_addr == u8_dest_addr) &&
(pt_dll_data->u32_pgn == ((t_rx_msg.Data[7]<<16) | (t_rx_msg.Data[6]<<8) | t_rx_msg.Data[5])))
{
pt_dll_data->e_msg_state = NONE;
}
}
break;
default:
break;
}
}
else if (u32_pgn == TP_DT_PGN) //接收多包数据帧
{
if ((t_rx_msg.Len == 8) && //长度为8
(pt_dll_data->u8_src_addr == u8_src_addr) && (pt_dll_data->u8_dest_addr == u8_dest_addr) && //接收报文目标、发送地址与报存的一致
((pt_dll_data->e_msg_state == RX_WAIT_DATA_T2) || (pt_dll_data->e_msg_state == RX_WAIT_DATA_T1)) && //正在接收多包数据状态下
(t_rx_msg.Data[0] != 0)) //包序号不为0
{
pt_dll_data->e_msg_state = RX_WAIT_DATA_T1;
pt_dll_data->u32_time = u32_delay_get_timer_val();
pt_dll_data->t_packet[t_rx_msg.Data[0]-1].u8_flag = 1;
memcpy(pt_dll_data->t_packet[t_rx_msg.Data[0]-1].u8_data, &(t_rx_msg.Data[1]), 7);
for (i=0; i<pt_dll_data->u8_packet_cnt; i++) //找到未接收的包,即下一个要求上送的包
{
if (pt_dll_data->t_packet[i].u8_flag == 0)
break;
}
//多包数据接收完成
if (i >= pt_dll_data->u8_packet_cnt)
{
pt_dll_data->e_msg_state = NONE;
u32_ret = 1;
pt_can_data->u32_pgn = pt_dll_data->u32_pgn;
pt_can_data->u8_src_addr = u8_src_addr;
pt_can_data->u8_dest_addr = u8_dest_addr;
pt_can_data->u8_pri = u8_pri;
pt_can_data->u16_len = pt_dll_data->u16_len;
if (pt_can_data->u16_len > (SAE1939_MULTI_PACKET_MAX_NUM*7))
pt_can_data->u16_len = (SAE1939_MULTI_PACKET_MAX_NUM*7);
for (i=0; i<pt_can_data->u16_len; i++)
pt_can_data->u8_data[i] = pt_dll_data->t_packet[i/7].u8_data[i%7];
//发送EndofMsgACK
v_sae1939_EndofMsgACK_send(pt_dll_data,&t_tx_msg);
pt_dll_data->u32_can_tx(&t_tx_msg);
}
else if (pt_dll_data->t_packet[pt_dll_data->u8_packet_cnt-1].u8_flag == 1) //有包未接收,但是最后一包接收了,说明有丢包的 则重新申请丢的包
{
pt_dll_data->e_msg_state = RX_WAIT_DATA_T2;
pt_dll_data->u32_time = u32_delay_get_timer_val();
for (j=pt_dll_data->u8_packet_cnt-1; j>=0; j--)
{
if (pt_dll_data->t_packet[j].u8_flag == 0)
break;
}
//回复CTS
u32_data = pt_dll_data->u32_pgn;
t_rx_msg.ID = (t_rx_msg.ID & 0xFF00FFFF)|(TP_CM_PGN << 8); //将帧ID PGN赋值为0xEC
v_sae1939_cts_send(t_rx_msg.ID ,u32_data, j-i+1,i+1, &t_tx_msg);
pt_dll_data->u32_can_tx(&t_tx_msg);
}
}
}
else //单包数据
{
u32_ret = 1; //返回解析成功
pt_can_data->u32_pgn = u32_pgn;
pt_can_data->u8_src_addr = u8_src_addr;
pt_can_data->u8_dest_addr = u8_dest_addr;
pt_can_data->u8_pri = u8_pri;
pt_can_data->u16_len = t_rx_msg.Len;
for (i=0; i<t_rx_msg.Len; i++)
pt_can_data->u8_data[i] = t_rx_msg.Data[i];
}
#if 1
//超时处理
switch (pt_dll_data->e_msg_state)
{
case RX_WAIT_DATA_T2:
if (u32_delay_time_elapse(pt_dll_data->u32_time, u32_delay_get_timer_val()) > TIMEOUT_T2)
{
//回复Abort
u32_data = ((U32_T)(pt_dll_data->u8_pri & 0x07) << 26);
u32_data |= ((TP_CM_PGN & 0x0000FF00) << 8);
u32_data |= ((U32_T)(pt_dll_data->u8_src_addr) <<8 );
u32_data |= pt_dll_data->u8_dest_addr;
v_sae1939_abort_send(u32_data , pt_dll_data->u32_pgn, &t_tx_msg);
pt_dll_data->u32_can_tx(&t_tx_msg);
pt_dll_data->e_msg_state = NONE;
}
break;
case RX_WAIT_DATA_T1:
if (u32_delay_time_elapse(pt_dll_data->u32_time, u32_delay_get_timer_val()) > TIMEOUT_T1)
{
//回复Abort
u32_data = ((U32_T)(pt_dll_data->u8_pri & 0x07) << 26);
u32_data |= ((TP_CM_PGN & 0x0000FF00) << 8);
u32_data |= ((U32_T)(pt_dll_data->u8_src_addr) <<8 );
u32_data |= pt_dll_data->u8_dest_addr;
v_sae1939_abort_send(u32_data , pt_dll_data->u32_pgn, &t_tx_msg);
pt_dll_data->u32_can_tx(&t_tx_msg);
pt_dll_data->e_msg_state = NONE;
}
break;
default:
break;
}
#endif
return u32_ret;
}