#include <stdio.h>
#include <main.h>
/******************************************************************************************************************************
帧序号 Data1 Data2 Data3 Data4 Data5 Data6 Data7 Data8
1 当前报文帧序号 包序号 报文有效数据长度低字节 报文有效数据长度高字节 有效数据01 有效数据02 有效数据03 有效数据04
2 当前报文帧序号 有效数据05 有效数据06 有效数据07 有效数据08 ... ... ...
... ... ... ... ... ... ... ... ...
... ... ... ... 有效数据N 校验码低字节 校验码高字节 00H 00H
******************************************************************************************************************************/
/*
函数说明: 累加和校验
@param 1: uint8_t *recv_buf 需要校验的数据
@param 2: uint16_t buff_len 数据长度
返回值: uint16_t 2个字节的校验码
*/
static uint16_t u16_check_sum(uint8_t *recv_buf, uint16_t buff_len)
{
uint16_t i, ret = 0;
for (i = 0; i < buff_len; i++) {
ret += *(recv_buf++);
}
return ret;
}
//多包数据
typedef struct
{
uint8_t recv_data[7]; // 数据
uint8_t recv_flag; // 包标记,0:未接收或未发送,1:己接收或己发送
} packet_t;
/* can应用层数据结构体定义,整个数据包 */
typedef struct
{
uint8_t total_frames; // 报文总帧数
uint16_t data_len; // 有效数字长度
packet_t recv_packet[TCU_PACKET_MAX_NUM];
} can_mult_pack_t;
/*
函数说明: 多包CAN 接收数据
@param 1: can_mult_pack_t *p_msg 多包的缓存区
@param 2: uint8_t *pdata CAN的8个字节数据
@param 3: uint8_t *pbuff 有效数据的存储地址
返回值: 0:接收失败 大于0:接收成功
*/
int mult_pack_read_can_data(can_mult_pack_t *p_msg, uint8_t *pdata, uint8_t *pbuff)
{
uint16_t i = 0;
uint16_t sum_check_code = 0;
uint16_t data_len; //有效数据长度
uint8_t recv_buff[1300] = {0}; //临时缓冲区
if ((pdata == NULL) || (p_msg == NULL)) {
return 0;
}
if (((pdata[0]-1) >= TCU_PACKET_MAX_NUM) || ((pdata[0]-1) < 0)) {
return 0;
}
p_msg->recv_packet[pdata[0]-1].recv_flag = true;
memcpy(p_msg->recv_packet[pdata[0]-1].recv_data, &pdata[1], 7);
/*第一包数据*/
if (pdata[0] == 1) {
p_msg->total_frames = pdata[1]; //报文总帧数
p_msg->data_len = (pdata[2] | (pdata[3] << 8)); //取有效长度
if (p_msg->data_len > (TCU_PACKET_MAX_NUM * 7)) {
memset(p_msg, 0, sizeof(can_mult_pack_t));
return 0; //长度非法
}
for (i = 0; i < p_msg->total_frames-1; i++) {
p_msg->recv_packet[i+1].recv_flag = false; //保证除了第一包数据标志,都为0
return 0;
}
}
for (i = 0; i < p_msg->total_frames; i++) {
if (p_msg->recv_packet[i].recv_flag == false) {
return 0; //没收到完整数据,继续接收
}
}
/*接收到完整数据*/
memset(recv_buff, 0, sizeof(recv_buff));
for (i = 0; i < p_msg->data_len+MULT_PACK_OTHER_LEN; i++) {
recv_buff[i] = p_msg->recv_packet[i/7].recv_data[i%7]; //取出数据放在临时缓冲区里
}
//取出校验码
sum_check_code = recv_buff[3+p_msg->data_len] | (recv_buff[3+p_msg->data_len+1] << 8);
/*报文总帧数到有效数据,进行校验*/
if (u16_check_sum(recv_buff, p_msg->data_len+3) != sum_check_code) {
//校验码不对,数据错误
memset(p_msg, 0, sizeof(can_mult_pack_t));
printf("校验没通过\n"); //
return 0;
}
printf("接收完整\n"); //
data_len = p_msg->data_len;
memcpy(pbuff, &recv_buff[3], p_msg->data_len); //取出有效数据
memset(p_msg, 0, sizeof(can_mult_pack_t)); //清空CAN多包缓存区
return data_len;
}
/******************************************************************/
/*
函数说明: 多包 CAN 发送数据
@param 1: int can_fd 文件描述符
@param 2: uint8_t dest_addr 目的地址
@param 3: uint8_t *pdata 发送数据
@param 4: uint16_t data_len 数据长度
返回值: false:失败 true:成功
*/
bool mult_pack_write_can_data(int can_fd, uint32_t can_id, uint8_t *pdata, uint16_t data_size)
{
uint16_t frame_count = 0; //多包帧数
uint16_t total_size = 0; //多包总长度,除了序号
uint16_t write_size = 0; //已写入的大小
uint16_t sum_check_code = 0; //累计和校验码
uint16_t i = 0;
uint8_t send_data[1300] = {0}; //发送缓冲区
can_msg_t tx_msg;
if (pdata == NULL) {
return false;
}
total_size = data_size + MULT_PACK_OTHER_LEN;
frame_count = FRAME_COUNT(total_size);
//将数据组好,放在缓冲区
send_data[0] = frame_count; //总帧数
send_data[1] = data_size & 0xFF; //有效长度低字节
send_data[2] = data_size >> 8; //有效长度高字节
memcpy(&send_data[3], pdata, data_size); //有效数据
sum_check_code = u16_check_sum(send_data, data_size+3); //获取累计和校验码,有效数据+报文总帧数+有效长度低+有效长度高
send_data[3+data_size] = sum_check_code; //校验低字节
send_data[3+data_size+1] = sum_check_code >> 8; //校验高字节
/*CAN数据*/
memset(&tx_msg, 0, sizeof(tx_msg));
tx_msg.id.can_id = can_id;
tx_msg.len = CAN_SEND_LEN;
tx_msg.ch = 0;
tx_msg.format = 1;
tx_msg.type = 0;
for (i = 0; i < frame_count; i++) {
memset(&tx_msg.data[1], 0, 7);
tx_msg.data[0]++; //序号
/*总长度减去已经发送的长度,剩余长度,大于或等于7*/
if ((total_size-write_size) >= 7) {
memcpy(&tx_msg.data[1], &send_data[write_size], 7);
} else {
/*最后一包,剩多少没发*/
memcpy(&tx_msg.data[1], &send_data[write_size], total_size-write_size);
}
write_size += 7;
single_pack_write_can_data(can_fd, &tx_msg); //数据发送
usleep(5000); //防止长时间占用CPU
}
}
仅供参考。。。。。。。