用代码实现N_PDU的四种帧格式(单帧、连续帧、流控帧、首帧)
/ N_PDU类型定义N_PDU_SINGLE_FRAME = 0,// 单帧N_PDU_FIRST_FRAME = 1,// 首帧N_PDU_CONSECUTIVE_FRAME = 2, // 连续帧N_PDU_FLOW_CONTROL = 3// 流控帧// 流控状态FLOW_CONTROL_CONTINUE = 0,// 继续发送FLOW_CONTROL_WAIT = 1,// 等待。
#include <stdio.h> #include <stdint.h> #include <string.h> #include <stdbool.h>
// N_PDU类型定义
typedef enum {
N_PDU_SINGLE_FRAME = 0, // 单帧
N_PDU_FIRST_FRAME = 1, // 首帧
N_PDU_CONSECUTIVE_FRAME = 2, // 连续帧
N_PDU_FLOW_CONTROL = 3 // 流控帧
} N_PDU_TYPE;
// 流控状态
typedef enum {
FLOW_CONTROL_CONTINUE = 0, // 继续发送
FLOW_CONTROL_WAIT = 1, // 等待
FLOW_CONTROL_OVERFLOW = 2 // 溢出
} FLOW_CONTROL_STATUS;
// N_PDU帧结构
typedef struct {
uint8_t pci; // 协议控制信息
uint8_t data[4096]; // 数据域
uint16_t data_length; // 数据长度
N_PDU_TYPE frame_type; // 帧类型
} N_PDU_FRAME;// 多帧传输上下文
typedef struct {
uint8_t sequence_number; // 序列号
uint16_t total_length; // 总数据长度
uint16_t received_bytes; // 已接收字节数
uint8_t buffer[4096]; // 数据缓冲区
bool transmission_active; // 传输是否活跃
} MULTI_FRAME_CONTEXT;
定义以上数据结构。
函数部分:
// 创建单帧
bool create_single_frame(const uint8_t* data, uint16_t data_len, N_PDU_FRAME* frame) {
if (data_len > 7 || data == NULL || frame == NULL) {
return false;
}
// PCI: 高4位为类型(0), 低4位为数据长度
frame->pci = (N_PDU_SINGLE_FRAME << 4) | (data_len & 0x0F);
memcpy(frame->data, data, data_len);
frame->data_length = data_len;
frame->frame_type = N_PDU_SINGLE_FRAME;
return true;
}
// 创建首帧
bool create_first_frame(const uint8_t* data, uint16_t total_len, N_PDU_FRAME* frame) {
if (total_len > 4095 || data == NULL || frame == NULL) {
return false;
}
// PCI: 高4位为类型(1), 低4位为长度的高4位
// 首帧数据前两个字节存储总长度
frame->pci = (N_PDU_FIRST_FRAME << 4) | ((total_len >> 8) & 0x0F);
frame->data[0] = total_len & 0xFF; // 长度低字节
frame->data[1] = (total_len >> 8) & 0xFF; // 长度高字节
// 复制剩余数据(如果有)
uint16_t copy_len = (total_len > 6) ? 6 : total_len;
if (copy_len > 0) {
memcpy(&frame->data[2], data, copy_len);
}
frame->data_length = 2 + copy_len;
frame->frame_type = N_PDU_FIRST_FRAME;
return true;
}
// 创建连续帧
bool create_consecutive_frame(uint8_t sequence_number, const uint8_t* data,
uint16_t data_len, N_PDU_FRAME* frame) {
if (sequence_number > 15 || data_len > 7 || frame == NULL) {
return false;
}
// PCI: 高4位为类型(2), 低4位为序列号
frame->pci = (N_PDU_CONSECUTIVE_FRAME << 4) | (sequence_number & 0x0F);
memcpy(frame->data, data, data_len);
frame->data_length = data_len;
frame->frame_type = N_PDU_CONSECUTIVE_FRAME;
return true;
}
// 创建流控帧
bool create_flow_control_frame(FLOW_CONTROL_STATUS status, uint8_t block_size,
uint8_t separation_time, N_PDU_FRAME* frame) {
if (frame == NULL) return false;
// PCI: 高4位为类型(3), 低4位为流控状态
frame->pci = (N_PDU_FLOW_CONTROL << 4) | (status & 0x0F);
frame->data[0] = block_size;
frame->data[1] = separation_time;
frame->data_length = 2;
frame->frame_type = N_PDU_FLOW_CONTROL;
return true;
}
帧解析与处理
// 解析接收到的帧
bool parse_received_frame(const uint8_t* raw_data, uint16_t raw_len, N_PDU_FRAME* frame) {
if (raw_len < 1 || frame == NULL) return false;
uint8_t pci = raw_data[0];
N_PDU_TYPE frame_type = (pci >> 4) & 0x0F;
frame->pci = pci;
frame->frame_type = frame_type;
switch (frame_type) {
case N_PDU_SINGLE_FRAME: {
uint8_t data_len = pci & 0x0F;
if (raw_len < 1 + data_len) return false;
memcpy(frame->data, &raw_data[1], data_len);
frame->data_length = data_len;
break;
}
case N_PDU_FIRST_FRAME: {
if (raw_len < 3) return false; // 至少需要PCI + 2字节长度
uint16_t total_len = ((pci & 0x0F) << 8) | raw_data[1];
uint16_t data_len = raw_len - 2; // 减去PCI和长度字节
frame->data[0] = raw_data[1]; // 存储长度信息
frame->data[1] = raw_data[2];
memcpy(&frame->data[2], &raw_data[3], data_len - 1);
frame->data_length = data_len + 1;
break;
}
case N_PDU_CONSECUTIVE_FRAME: {
if (raw_len < 2) return false;
uint8_t data_len = raw_len - 1;
memcpy(frame->data, &raw_data[1], data_len);
frame->data_length = data_len;
break;
}
case N_PDU_FLOW_CONTROL: {
if (raw_len < 3) return false;
frame->data[0] = raw_data[1]; // block size
frame->data[1] = raw_data[2]; // separation time
frame->data_length = 2;
break;
}
default:
return false;
}
return true;
}
// 多帧传输接收处理
bool process_multi_frame_reception(const N_PDU_FRAME* frame, MULTI_FRAME_CONTEXT* context) {
if (frame == NULL || context == NULL) return false;
switch (frame->frame_type) {
case N_PDU_FIRST_FRAME: {
// 解析总长度
context->total_length = ((frame->pci & 0x0F) << 8) | frame->data[0];
context->received_bytes = 0;
context->sequence_number = 0;
context->transmission_active = true;
// 复制首帧中的数据
uint16_t copy_len = frame->data_length - 1; // 减去长度字节
if (copy_len > 0) {
memcpy(context->buffer, &frame->data[1], copy_len);
context->received_bytes = copy_len;
}
break;
}
case N_PDU_CONSECUTIVE_FRAME: {
if (!context->transmission_active) return false;
// 检查序列号
uint8_t expected_sn = (context->sequence_number + 1) & 0x0F;
uint8_t received_sn = frame->pci & 0x0F;
if (received_sn != expected_sn) {
// 序列号错误,重置传输
context->transmission_active = false;
return false;
}
// 复制数据
uint16_t copy_len = frame->data_length;
if (context->received_bytes + copy_len > context->total_length) {
copy_len = context->total_length - context->received_bytes;
}
memcpy(&context->buffer[context->received_bytes], frame->data, copy_len);
context->received_bytes += copy_len;
context->sequence_number = received_sn;
// 检查是否接收完成
if (context->received_bytes >= context->total_length) {
context->transmission_active = false;
}
break;
}
default:
return false;
}
return true;
}
示例
// 示例:发送多帧数据
void send_multi_frame_data(const uint8_t* data, uint16_t total_len) {
N_PDU_FRAME frame;
MULTI_FRAME_CONTEXT context = {0};
printf("开始多帧传输,总长度: %d bytes\n", total_len);
// 发送首帧
create_first_frame(data, total_len, &frame);
send_frame(&frame); // 假设的发送函数
uint16_t sent_bytes = 6; // 首帧已发送6字节数据
uint8_t sequence_number = 0;
// 发送连续帧
while (sent_bytes < total_len) {
// 等待流控帧(如果需要)
// receive_flow_control();
uint16_t chunk_size = (total_len - sent_bytes > 7) ? 7 : total_len - sent_bytes;
create_consecutive_frame(sequence_number, &data[sent_bytes], chunk_size, &frame);
send_frame(&frame);
sent_bytes += chunk_size;
sequence_number = (sequence_number + 1) & 0x0F;
printf("发送连续帧 #%d, 已发送: %d/%d bytes\n",
sequence_number, sent_bytes, total_len);
}
printf("多帧传输完成\n");
}
// 示例:打印帧信息
void print_frame_info(const N_PDU_FRAME* frame) {
const char* type_str[] = {"单帧", "首帧", "连续帧", "流控帧"};
printf("帧类型: %s, PCI: 0x%02X\n",
type_str[frame->frame_type], frame->pci);
if (frame->frame_type == N_PDU_SINGLE_FRAME) {
printf("数据长度: %d\n", frame->pci & 0x0F);
} else if (frame->frame_type == N_PDU_FIRST_FRAME) {
uint16_t total_len = ((frame->pci & 0x0F) << 8) | frame->data[0];
printf("总长度: %d\n", total_len);
} else if (frame->frame_type == N_PDU_CONSECUTIVE_FRAME) {
printf("序列号: %d\n", frame->pci & 0x0F);
} else if (frame->frame_type == N_PDU_FLOW_CONTROL) {
const char* status_str[] = {"继续", "等待", "溢出"};
printf("流控状态: %s, 块大小: %d, 间隔时间: %d\n",
status_str[frame->pci & 0x0F], frame->data[0], frame->data[1]);
}
printf("数据: ");
for (int i = 0; i < frame->data_length && i < 8; i++) {
printf("%02X ", frame->data[i]);
}
printf("\n\n");
}
int main() {
// 测试单帧
uint8_t single_frame_data[] = {0x11, 0x22, 0x33, 0x44};
N_PDU_FRAME single_frame;
create_single_frame(single_frame_data, 4, &single_frame);
print_frame_info(&single_frame);
// 测试多帧传输
uint8_t multi_frame_data[20];
for (int i = 0; i < 20; i++) {
multi_frame_data[i] = i + 0x10;
}
send_multi_frame_data(multi_frame_data, 20);
return 0;
}
更多推荐



所有评论(0)