Files

418 lines
14 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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;
}