diff --git a/Public/PCBA测试需求说明书 V1.1.docx b/Public/PCBA测试需求说明书 V1.1.docx new file mode 100644 index 0000000..766562f Binary files /dev/null and b/Public/PCBA测试需求说明书 V1.1.docx differ diff --git a/Public/~$BA测试需求说明书 V1.1.docx b/Public/~$BA测试需求说明书 V1.1.docx new file mode 100644 index 0000000..06dbef6 Binary files /dev/null and b/Public/~$BA测试需求说明书 V1.1.docx differ diff --git a/User/application/src/tcpserverc.c b/User/application/src/tcpserverc.c index 107dd62..e76d803 100644 --- a/User/application/src/tcpserverc.c +++ b/User/application/src/tcpserverc.c @@ -39,6 +39,152 @@ extern uint8_t uart_echo_flags_hart2; extern uint8_t uart_echo_flags_ble1; extern uint8_t uart_echo_flags_ble2; +#define head_00 0xD5 // 帧头1 +#define head_01 0xC8 // 帧头2 +uint16_t data_len = 0; // 帧体长度 +#define source_addr_h 0x01 // 源地址高 +#define source_addr_l 0x02 // 源地址低 +#define target_addr_h 0x0A // 目标地址高 +#define target_addr_l 0x0B // 目标地址低 +uint16_t reply_type = 0x00;// 报文类型_应答 + +// 校验和函数 +uint8_t calc_checksum(const uint8_t *data, uint8_t start, uint8_t end) { + uint8_t checksum = 0; + for (uint8_t i = start; i <= end; i++) { + checksum += data[i]; + } + return checksum; +} + +// body: 报文体指针, body_len: 报文体长度, tx: 返回帧缓冲区, 返回帧总长度 +uint16_t handle_type_80(const uint8_t *body, uint16_t body_len, uint8_t *tx) +{ + uint16_t total_len = 2 + 2 + 2 + 2 + 1 + body_len + 2; // 帧头+帧长+源+目标+类型+体+校验 + // 帧头 + tx[0] = head_00; + tx[1] = head_01; + // 帧长度(大端) + tx[2] = (total_len >> 8) & 0xFF; + tx[3] = total_len & 0xFF; + // 源地址 + tx[4] = source_addr_h; + tx[5] = source_addr_l; + // 目标地址 + tx[6] = target_addr_h; + tx[7] = target_addr_l; + // 报文类型 + tx[8] = reply_type; + // 报文体 + tx[9] = 0x01;//执行成功 + //memcpy(&tx[9], body, body_len); + // 校验和(累加源地址到报文体) + uint16_t checksum = 0; + for (int i = 4; i < 9 + body_len; ++i) + { + checksum += tx[i]; + } + // 校验和2字节(大端) + tx[total_len - 2] = 0x00;//校验和只取低八位 + tx[total_len - 1] = checksum & 0xFF; + return total_len; +} +uint16_t handle_type_81(const uint8_t *body, uint16_t body_len, uint8_t *tx) +{ +uint16_t total_len = 2 + 2 + 2 + 2 + 1 + body_len + 2; // 帧头+帧长+源+目标+类型+体+校验 + // 帧头 + tx[0] = head_00; + tx[1] = head_01; + // 帧长度(大端) + tx[2] = (total_len >> 8) & 0xFF; + tx[3] = total_len & 0xFF; + // 源地址 + tx[4] = source_addr_h; + tx[5] = source_addr_l; + // 目标地址 + tx[6] = target_addr_h; + tx[7] = target_addr_l; + // 报文类型 + tx[8] = reply_type; + // 报文体 + tx[9] = 0x01;//主版本号1.0 + tx[10] = 0x00;//次版本号0.0 + //memcpy(&tx[9], body, body_len); + // 校验和(累加源地址到报文体) + uint16_t checksum = 0; + for (int i = 4; i < 9 + body_len; ++i) + { + checksum += tx[i]; + } + // 校验和2字节(大端) + tx[total_len - 2] = 0x00;//校验和只取低八位 + tx[total_len - 1] = checksum & 0xFF; + return total_len; +} +uint16_t handle_type_82(const uint8_t *body, uint16_t body_len, uint8_t *tx) +{ + uint16_t total_len = 2 + 2 + 2 + 2 + 1 + body_len + 2; // 帧头+帧长+源+目标+类型+体+校验 + // 帧头 + tx[0] = head_00; + tx[1] = head_01; + // 帧长度(大端) + tx[2] = (total_len >> 8) & 0xFF; + tx[3] = total_len & 0xFF; + // 源地址 + tx[4] = source_addr_h; + tx[5] = source_addr_l; + // 目标地址 + tx[6] = target_addr_h; + tx[7] = target_addr_l; + // 报文类型 + tx[8] = reply_type; + // 报文体 + tx[9] = 0xBC;//心跳回复 + + // 校验和(累加源地址到报文体) + uint16_t checksum = 0; + for (int i = 4; i < 9 + body_len; ++i) + { + checksum += tx[i]; + } + // 校验和2字节(大端) + //tx[total_len - 2] = (checksum >> 8) & 0xFF; + tx[total_len - 2] =0x00;//校验和只取低八位 + tx[total_len - 1] = checksum & 0xFF; + return total_len; +} +uint16_t handle_type_83(const uint8_t *body, uint16_t body_len, uint8_t *tx) +{ + uint16_t total_len = 2 + 2 + 2 + 2 + 1 + body_len + 2; // 帧头+帧长+源+目标+类型+体+校验 + // 帧头 + tx[0] = head_00; + tx[1] = head_01; + // 帧长度(大端) + tx[2] = (total_len >> 8) & 0xFF; + tx[3] = total_len & 0xFF; + // 源地址 + tx[4] = source_addr_h; + tx[5] = source_addr_l; + // 目标地址 + tx[6] = target_addr_h; + tx[7] = target_addr_l; + // 报文类型 + tx[8] = reply_type; + // 报文体 + tx[9] = 0x00;//7个字节表示的使能状态 + + // 校验和(累加源地址到报文体) + uint16_t checksum = 0; + for (int i = 4; i < 9 + body_len; ++i) + { + checksum += tx[i]; + } + // 校验和2字节(大端) + //tx[total_len - 2] = (checksum >> 8) & 0xFF; + tx[total_len - 2] =0x00;//校验和只取低八位 + tx[total_len - 1] = checksum & 0xFF; + return total_len; +} /*接收回调函数*/ static err_t tcpecho_recv_hart1(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { // 对应接收数据连接的控制块 接收到的数据 @@ -142,11 +288,11 @@ static err_t tcpecho_recv_ble2(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, static err_t tcpecho_recv_control(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { - uint8_t tcp_rx_data[128] = {0}; // 接收数据缓存区 - uint8_t tcp_tx_data[128] = {0}; // 发送数据缓存区 + uint8_t tcp_rx_data[128] = {0}; + uint8_t tcp_tx_data[128] = {0}; uint8_t rx_data_len = 0; - uint8_t tx_data_len = 0; - + uint8_t tx_data_len = 0; + if (p != NULL) { tcp_echo_flags_control = 1; @@ -154,47 +300,85 @@ static err_t tcpecho_recv_control(void *arg, struct tcp_pcb *tpcb, struct pbuf * server_pcb_control = tpcb; memcpy(tcp_rx_data, (uint8_t *)p->payload, p->tot_len); rx_data_len = p->tot_len; - - // 判断是否为指定格式的命令帧 - if (rx_data_len == 10 && - tcp_rx_data[0] == 0xD5 && - tcp_rx_data[1] == 0xC8 && - tcp_rx_data[2] == 0x0A && - tcp_rx_data[3] == 0x01 && - tcp_rx_data[4] == 0x01 && - tcp_rx_data[5] == 0x0A && - tcp_rx_data[6] == 0x0A && - tcp_rx_data[7] == 0x00 && - tcp_rx_data[8] == 0x00 && - tcp_rx_data[9] == 0x17) + + // 基本帧头校验,帧长和固定帧头 + if (rx_data_len == tcp_rx_data[3] && tcp_rx_data[0] == 0xD5 && tcp_rx_data[1] == 0xC8) { - // 构造返回帧 - tcp_tx_data[0] = 0xD5; // 帧头1 - tcp_tx_data[1] = 0xC8; // 帧头2 - tcp_tx_data[2] = 0x0A; // 帧长度 - tcp_tx_data[3] = 0x01; // 源地址 - tcp_tx_data[4] = 0x01; - tcp_tx_data[5] = 0x0A; // 目标地址 - tcp_tx_data[6] = 0x0A; - tcp_tx_data[7] = 0x01; // 报文类型改为01 - tcp_tx_data[8] = 0x00; // 报文体 - - // 计算校验和(从目标地址到报文体的累加和) - uint8_t checksum = 0; - for (int i = 5; i <= 8; i++) { - checksum += tcp_tx_data[i]; + uint8_t calc_sum = 0; // 改用uint8_t,自动取低8位 + for (int i = 4; i < rx_data_len - 1; i++) + { + calc_sum += tcp_rx_data[i]; } - tcp_tx_data[9] = checksum; - tx_data_len = 10; - + uint8_t recv_sum = tcp_rx_data[rx_data_len - 1]; // 只取最后一个字节作为校验和 + if (calc_sum != recv_sum) + { + pbuf_free(p); + return ERR_OK; + } + + // 根据报文类型分发 + switch (tcp_rx_data[8]) + { + case 0x80: //复位 + { + uint16_t body_len = rx_data_len - 11; //报文体长度 = 总长度 - 2(帧头) - 2(帧长) - 2(源) - 2(目标) - 1(类型) - 2(校验) + reply_type = tcp_rx_data[8]; + tx_data_len = handle_type_80(tcp_rx_data + 9, body_len, tcp_tx_data); + break; + } + case 0x81://查询版本号 + { + uint16_t body_len = 2; //报文体有主次2个字节 + reply_type = tcp_rx_data[8]; + tx_data_len = handle_type_81(tcp_rx_data + 9, body_len, tcp_tx_data); + break; + } + case 0x82://心跳请求 + { + uint16_t body_len = 1; //心跳报文体有1个字节 + reply_type = tcp_rx_data[8]; + tx_data_len = handle_type_82(tcp_rx_data + 9, body_len, tcp_tx_data); + break; + } + case 0x83://读取模块使能状态 + { + + } + break; + case 0x84://设置模块是能状态 + + break; + case 0x85://读取读取配置参数 + + break; + case 0x86://设置配置参数 + + break; + case 0x87://读取测试数据 + + break; + case 0x88://透传数据 + + break; + + default: + pbuf_free(p); + return ERR_OK; + } + + // 发送返回帧 - if(tcp_write(tpcb, tcp_tx_data, tx_data_len, 1) != ERR_OK) { - // 发送失败处理 - return ERR_MEM; + if (tx_data_len > 0) + { + if (tcp_write(tpcb, tcp_tx_data, tx_data_len, 1) != ERR_OK) + { + pbuf_free(p); + return ERR_MEM; + } + tcp_output(tpcb); } - tcp_output(tpcb); // 确保数据立即发送 + pbuf_free(p); } - pbuf_free(p); } else if (err == ERR_OK) {