#include "tcpserverc.h" #include "lwip/netif.h" #include "lwip/ip.h" #include "lwip/tcp.h" #include "lwip/init.h" #include "netif/etharp.h" #include "lwip/udp.h" #include "lwip/pbuf.h" #include #include #include "usart.h" #include "main.h" #include "ht1200m.h" #include "user_lib.h" #include "communication_protocol.h" #include "user_gpio.h" #include "tim.h" struct tcp_pcb *server_pcb_hart1 = NULL; struct tcp_pcb *server_pcb_hart2 = NULL; struct tcp_pcb *server_pcb_ble1 = NULL; struct tcp_pcb *server_pcb_ble2 = NULL; struct tcp_pcb *server_pcb_control = NULL; communication_di_t *user_communication_di = NULL; communication_do_t *user_communication_do = NULL; communication_ai_t *user_communication_ai = NULL; communication_ao_t *user_communication_ao = NULL; comnmunication_encoder_t *user_communication_encoder = NULL; extern uint8_t tcp_echo_flags_hart1; extern uint8_t tcp_echo_flags_hart2; extern uint8_t tcp_echo_flags_ble1; extern uint8_t tcp_echo_flags_ble2; extern uint8_t tcp_echo_flags_control; extern uint8_t send_data_flag_cmd; extern uint8_t uart_echo_flags_hart1; 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) { // 对应接收数据连接的控制块 接收到的数据 if (p != NULL) { /* 更新窗口*/ tcp_echo_flags_hart1 = 1; tcp_recved(tpcb, p->tot_len); // 读取数据的控制块 得到所有数据的长度 server_pcb_hart1 = tpcb; // 直接赋值 memcpy(hart1_uart5.tx_data, (int *)p->payload, p->tot_len); if (huart5.gState == HAL_UART_STATE_READY) { HART1_RTS_SEND; dma_usart_send(&huart5, hart1_uart5.tx_data, p->tot_len); } pbuf_free(p); } else if (err == ERR_OK) // 检测到对方主动关闭连接时,也会调用recv函数,此时p为空 { // HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3); tcp_echo_flags_hart1 = 0; return tcp_close(tpcb); } return ERR_OK; } static err_t tcpecho_recv_hart2(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { // 对应接收数据连接的控制块 接收到的数据 if (p != NULL) { /* 更新窗口*/ tcp_echo_flags_hart2 = 1; tcp_recved(tpcb, p->tot_len); // 读取数据的控制块 得到所有数据的长度 server_pcb_hart2 = tpcb; // 直接赋值 memcpy(hart2_uart2.tx_data, (int *)p->payload, p->tot_len); if (huart2.gState == HAL_UART_STATE_READY) { HART2_RTS_SEND; dma_usart_send(&huart2, hart2_uart2.tx_data, p->tot_len); } pbuf_free(p); } else if (err == ERR_OK) // 检测到对方主动关闭连接时,也会调用recv函数,此时p为空 { // HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3); tcp_echo_flags_hart2 = 0; return tcp_close(tpcb); } return ERR_OK; } #if (BLE2_USART6 == 1) static err_t tcpecho_recv_ble1(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { // 对应接收数据连接的控制块 接收到的数据 if (p != NULL) { /* 更新窗口*/ tcp_echo_flags_ble1 = 1; tcp_recved(tpcb, p->tot_len); // 读取数据的控制块 得到所有数据的长度 server_pcb_ble1 = tpcb; // 直接赋值 memcpy(ble1_uart6.tx_data, (int *)p->payload, p->tot_len); if (huart6.gState == HAL_UART_STATE_READY) { dma_usart_send(&huart6, ble1_uart6.tx_data, p->tot_len); } pbuf_free(p); } else if (err == ERR_OK) // 检测到对方主动关闭连接时,也会调用recv函数,此时p为空 { return tcp_close(tpcb); } return ERR_OK; } #endif static err_t tcpecho_recv_ble2(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { // 对应接收数据连接的控制块 接收到的数据 if (p != NULL) { /* 更新窗口*/ tcp_echo_flags_ble2 = 1; tcp_recved(tpcb, p->tot_len); // 读取数据的控制块 得到所有数据的长度 server_pcb_ble2 = tpcb; // 直接赋值 memcpy(ble2_uart3.tx_data, (int *)p->payload, p->tot_len); if (huart3.gState == HAL_UART_STATE_READY) { dma_usart_send(&huart3, ble2_uart3.tx_data, p->tot_len); } pbuf_free(p); } else if (err == ERR_OK) // 检测到对方主动关闭连接时,也会调用recv函数,此时p为空 { // HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3); tcp_echo_flags_ble2 = 0; return tcp_close(tpcb); } return ERR_OK; } 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 rx_data_len = 0; uint8_t tx_data_len = 0; if (p != NULL) { tcp_echo_flags_control = 1; tcp_recved(tpcb, p->tot_len); 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 == tcp_rx_data[3] && tcp_rx_data[0] == 0xD5 && tcp_rx_data[1] == 0xC8) { uint8_t calc_sum = 0; // 改用uint8_t,自动取低8位 for (int i = 4; i < rx_data_len - 1; i++) { calc_sum += tcp_rx_data[i]; } 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 (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); } pbuf_free(p); } } else if (err == ERR_OK) { tcp_echo_flags_control = 0; return tcp_close(tpcb); } return ERR_OK; } static err_t tcpecho_accept_hart1(void *arg, struct tcp_pcb *newpcb, err_t err) // 由于这个函数是*tcp_accept_fn类型的,形参的数量和类型必须一致 { tcp_recv(newpcb, tcpecho_recv_hart1); // 当收到数据时,回调用户自己写的tcpecho_recv HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_3); // 停止蜂鸣器PWM输出,用于关闭蜂鸣器发声 return ERR_OK; } static err_t tcpecho_accept_hart2(void *arg, struct tcp_pcb *newpcb, err_t err) // 由于这个函数是*tcp_accept_fn类型的 { tcp_recv(newpcb, tcpecho_recv_hart2); // 当收到数据时,回调用户自己写的tcpecho_recv HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_3); // 停止蜂鸣器PWM输出,用于关闭蜂鸣器发声 return ERR_OK; } #if (BLE2_USART6 == 1) static err_t tcpecho_accept_ble1(void *arg, struct tcp_pcb *newpcb, err_t err) // 由于这个函数是*tcp_accept_fn类型的 { tcp_recv(newpcb, tcpecho_recv_ble1); // 当收到数据时,回调用户自己写的tcpecho_recv HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_3); // 停止蜂鸣器PWM输出,用于关闭蜂鸣器发声 return ERR_OK; } #endif static err_t tcpecho_accept_ble2(void *arg, struct tcp_pcb *newpcb, err_t err) // 由于这个函数是*tcp_accept_fn类型的 { tcp_recv(newpcb, tcpecho_recv_ble2); // 当收到数据时,回调用户自己写的tcpecho_recv HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_3); // 停止蜂鸣器PWM输出,用于关闭蜂鸣器发声 return ERR_OK; } static err_t tcpecho_accept_control(void *arg, struct tcp_pcb *newpcb, err_t err) // 由于这个函数是*tcp_accept_fn类型的 { tcp_recv(newpcb, tcpecho_recv_control); // 当收到数据时,回调用户自己写的tcpecho_recv HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_3); // 停止蜂鸣器PWM输出,用于关闭蜂鸣器发声 return ERR_OK; } void tcp_echo_init(void) { struct tcp_pcb *server_hart1 = NULL; struct tcp_pcb *server_hart2 = NULL; #if (BLE2_USART6 == 1) struct tcp_pcb *server_ble1 = NULL; #endif struct tcp_pcb *server_ble2 = NULL; struct tcp_pcb *server_control = NULL; /* 创建一路HART */ server_hart1 = tcp_new(); /* 绑定TCP控制块 */ tcp_bind(server_hart1, IP_ADDR_ANY, TCP_PORT_HART1); /* 进入监听状态 */ server_hart1 = tcp_listen(server_hart1); /* 处理连接 注册函数,侦听到连接时被注册的函数被回调 */ tcp_accept(server_hart1, tcpecho_accept_hart1); // 侦听到连接后,回调用户编写的tcpecho_accept /* 创建二路HART */ server_hart2 = tcp_new(); /* 绑定TCP控制块 */ tcp_bind(server_hart2, IP_ADDR_ANY, TCP_PORT_HART2); /* 进入监听状态 */ server_hart2 = tcp_listen(server_hart2); /* 处理连接 注册函数,侦听到连接时被注册的函数被回调 */ tcp_accept(server_hart2, tcpecho_accept_hart2); // 侦听到连接后,回调用户编写的tcpecho_accept #if (BLE2_USART6 == 1) /* 创建一路蓝牙 */ server_ble1 = tcp_new(); /* 绑定TCP控制块 */ tcp_bind(server_ble1, IP_ADDR_ANY, TCP_PORT_BLE1); /* 进入监听状态 */ server_ble1 = tcp_listen(server_ble1); /* 处理连接 注册函数,侦听到连接时被注册的函数被回调 */ tcp_accept(server_ble1, tcpecho_accept_ble1); // 侦听到连接后,回调用户编写的tcpecho_accept #endif /* 创建二路蓝牙 */ server_ble2 = tcp_new(); /* 绑定TCP控制块 */ tcp_bind(server_ble2, IP_ADDR_ANY, TCP_PORT_BLE2); /* 进入监听状态 */ server_ble2 = tcp_listen(server_ble2); /* 处理连接 注册函数,侦听到连接时被注册的函数被回调 */ tcp_accept(server_ble2, tcpecho_accept_ble2); // 侦听到连接后,回调用户编写的tcpecho_accept /* 创建控制块 */ server_control = tcp_new(); /* 绑定TCP控制块 */ tcp_bind(server_control, IP_ADDR_ANY, TCP_PORT_CONTROL); /* 进入监听状态 */ server_control = tcp_listen(server_control); /* 处理连接 注册函数,侦听到连接时被注册的函数被回调 */ tcp_accept(server_control, tcpecho_accept_control); // 侦听到连接后,回调用户编写的tcpecho_accept } void user_send_data_hart1(uint8_t *data, uint16_t len) { tcp_write(server_pcb_hart1, data, len, 1); } void user_send_data_hart2(uint8_t *data, uint16_t len) { tcp_write(server_pcb_hart2, data, len, 1); } #if (BLE2_USART6 == 1) void user_send_data_ble1(uint8_t *data, uint16_t len) { tcp_write(server_pcb_ble1, data, len, 1); } #endif void user_send_data_ble2(uint8_t *data, uint16_t len) { tcp_write(server_pcb_ble2, data, len, 1); } void user_send_data_control(uint8_t *data, uint16_t len) { tcp_write(server_pcb_control, data, len, 1); } void uart_forwarding_tcp(void) { if (uart_echo_flags_hart1 == 1) { uart_echo_flags_hart1 = 0; user_send_data_hart1(hart1_uart5.rx_data, hart1_uart5.rx_num); } if (uart_echo_flags_hart2 == 1) { uart_echo_flags_hart2 = 0; user_send_data_hart2(hart2_uart2.rx_data, hart2_uart2.rx_num); } #if (BLE2_USART6 == 1) if (uart_echo_flags_ble1 == 1) { uart_echo_flags_ble1 = 0; user_send_data_ble1(ble1_uart6.rx_data, ble1_uart6.rx_num); } #endif if (uart_echo_flags_ble2 == 1) { uart_echo_flags_ble2 = 0; user_send_data_ble2(ble2_uart3.rx_data, ble2_uart3.rx_num); } }