807 lines
28 KiB
C
807 lines
28 KiB
C
#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 <stdio.h>
|
||
#include <string.h>
|
||
#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 enable_data[7] = {
|
||
0x03, // Byte 0: 蓝牙 + WIFI
|
||
0x00, // Byte 1: 预留
|
||
0xFF, // Byte 2: 恒压输出 + 模拟输出(全使能)
|
||
0x0F, // Byte 3: 电磁阀1-3 + IO扩展2
|
||
0x00, // Byte 4: 预留
|
||
0x00, // Byte 5: 预留
|
||
0x00 // Byte 6: 预留
|
||
};
|
||
uint8_t adc_read_data[22] = {
|
||
|
||
0x0C,0x80,// 恒压输出1高字节, 恒压输出1低字节,
|
||
0x0C,0x80,// 恒压输出2高字节, 恒压输出2低字节,
|
||
0x0C,0x80,// 模拟输出1高字节, 模拟输出1低字节,
|
||
0x0C,0x80,// 模拟输出2高字节, 模拟输出2低字节,
|
||
0x0C,0x80,// 模拟输出3高字节, 模拟输出3低字节,
|
||
0x0C,0x80,// 模拟输出4高字节, 模拟输出4低字节,
|
||
0x0C,0x80,// 模拟输出5高字节, 模拟输出5低字节,
|
||
0x0C,0x80,// 模拟输出6高字节, 模拟输出6低字节,
|
||
0x0C,0x80,// 输出目标设备4 - 20mA高字节, 输出目标设备4 - 20mA低字节,
|
||
0x0C,0x80,// 比例阀1输出高字节, 比例阀1输出低字节,
|
||
0x0C,0x80,// 比例阀2输出高字节, 比例阀2输出低字节
|
||
};
|
||
uint8_t adc_set_data[22] = {
|
||
|
||
0x0D,0xF0,// 恒压输出1高字节, 恒压输出1低字节,
|
||
0x0D,0xF0,// 恒压输出2高字节, 恒压输出2低字节,
|
||
0x0D,0xF0,// 模拟输出1高字节, 模拟输出1低字节,
|
||
0x0D,0xF0,// 模拟输出2高字节, 模拟输出2低字节,
|
||
0x0D,0xF0,// 模拟输出3高字节, 模拟输出3低字节,
|
||
0x0D,0xF0,// 模拟输出4高字节, 模拟输出4低字节,
|
||
0x0D,0xF0,// 模拟输出5高字节, 模拟输出5低字节,
|
||
0x0D,0xF0,// 模拟输出6高字节, 模拟输出6低字节,
|
||
0x0D,0xF0,// 输出目标设备4 - 20mA高字节, 输出目标设备4 - 20mA低字节,
|
||
0x0D,0xF0,// 比例阀1输出高字节, 比例阀1输出低字节,
|
||
0x0D,0xF0,// 比例阀2输出高字节, 比例阀2输出低字节
|
||
};
|
||
// 假设数据按高字节到低字节排列
|
||
// 定义数组存放数据,总字节数根据表格计算为:2 + 4×18 = 74 字节
|
||
uint8_t test_adc_read_data[74] = {
|
||
// IO扩展1高字节, IO扩展1低字节
|
||
0x12, 0x34,
|
||
// ADC(通道1)高字节1, ADC(通道1)高字节2, ADC(通道1)低字节1, ADC(通道1)低字节2
|
||
0x01, 0x02, 0x03, 0x04,
|
||
// ADC(通道2)高字节1, ADC(通道2)高字节2, ADC(通道2)低字节1, ADC(通道2)低字节2
|
||
0x05, 0x06, 0x07, 0x08,
|
||
// ADC(通道3)高字节1, ADC(通道3)高字节2, ADC(通道3)低字节1, ADC(通道3)低字节2
|
||
0x09, 0x0A, 0x0B, 0x0C,
|
||
// ADC(通道4)高字节1, ADC(通道4)高字节2, ADC(通道4)低字节1, ADC(通道4)低字节2
|
||
0x0D, 0x0E, 0x0F, 0x10,
|
||
// ADC(通道5)高字节1, ADC(通道5)高字节2, ADC(通道5)低字节1, ADC(通道5)低字节2
|
||
0x11, 0x12, 0x13, 0x14,
|
||
// ADC(通道6)高字节1, ADC(通道6)高字节2, ADC(通道6)低字节1, ADC(通道6)低字节2
|
||
0x15, 0x16, 0x17, 0x18,
|
||
// ADC(通道7)高字节1, ADC(通道7)高字节2, ADC(通道7)低字节1, ADC(通道7)低字节2
|
||
0x19, 0x1A, 0x1B, 0x1C,
|
||
// ADC(通道8)高字节1, ADC(通道8)高字节2, ADC(通道8)低字节1, ADC(通道8)低字节2
|
||
0x1D, 0x1E, 0x1F, 0x20,
|
||
// ADC(通道9)高字节1, ADC(通道9)高字节2, ADC(通道9)低字节1, ADC(通道9)低字节2
|
||
0x21, 0x22, 0x23, 0x24,
|
||
// ADC(通道10)高字节1, ADC(通道10)高字节2, ADC(通道10)低字节1, ADC(通道10)低字节2
|
||
0x25, 0x26, 0x27, 0x28,
|
||
// ADC(通道11)高字节1, ADC(通道11)高字节2, ADC(通道11)低字节1, ADC(通道11)低字节2
|
||
0x29, 0x2A, 0x2B, 0x2C,
|
||
// ADC(通道12)高字节1, ADC(通道12)高字节2, ADC(通道12)低字节1, ADC(通道12)低字节2
|
||
0x2D, 0x2E, 0x2F, 0x30,
|
||
// ADC(通道13)高字节1, ADC(通道13)高字节2, ADC(通道13)低字节1, ADC(通道13)低字节2
|
||
0x31, 0x32, 0x33, 0x34,
|
||
// ADC(通道14)高字节1, ADC(通道14)高字节2, ADC(通道14)低字节1, ADC(通道14)低字节2
|
||
0x35, 0x36, 0x37, 0x38,
|
||
// ADC(通道15)高字节1, ADC(通道15)高字节2, ADC(通道15)低字节1, ADC(通道15)低字节2
|
||
0x39, 0x3A, 0x3B, 0x3C,
|
||
// ADC(通道16)高字节1, ADC(通道16)高字节2, ADC(通道16)低字节1, ADC(通道16)低字节2
|
||
0x3D, 0x3E, 0x3F, 0x40,
|
||
// 比例阀1输入高字节1, 比例阀1输入高字节2, 比例阀1输入低字节1, 比例阀1输入低字节2
|
||
0x41, 0x42, 0x43, 0x44,
|
||
// 比例阀2输入高字节1, 比例阀2输入高字节2, 比例阀2输入低字节1, 比例阀2输入低字节2
|
||
0x45, 0x46, 0x47, 0x48
|
||
};
|
||
// 校验和函数
|
||
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)
|
||
{
|
||
// 检查 body_len 是否为7,如果不是则返回错误(可选)
|
||
if (body_len != 7) {
|
||
return 0; // 或返回错误码
|
||
}
|
||
|
||
uint16_t total_len = 2 + 2 + 2 + 2 + 1 + 7 + 2; // 帧头+帧长+源+目标+类型+7字节使能+校验
|
||
|
||
// 帧头
|
||
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;
|
||
|
||
// 7字节使能状态(直接复制 body 到 tx[9]~tx[15])
|
||
memcpy(&tx[9], body, 7); // 确保 body 是7字节
|
||
|
||
// 校验和(累加源地址到7字节使能数据)
|
||
uint16_t checksum = 0;
|
||
for (int i = 4; i < 16; ++i) // 4~15(源地址+目标地址+类型+7字节使能)
|
||
{
|
||
checksum += tx[i];
|
||
}
|
||
|
||
// 校验和2字节(大端,只取低8位)
|
||
tx[total_len - 2] = 0x00; // 高8位强制为0(如果协议要求)
|
||
tx[total_len - 1] = checksum & 0xFF;
|
||
|
||
return total_len;
|
||
}
|
||
uint16_t handle_type_84(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;
|
||
// 报文体
|
||
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_85(const uint8_t *body, uint16_t body_len, uint8_t *tx)
|
||
{
|
||
|
||
|
||
uint16_t total_len = 2 + 2 + 2 + 2 + 1 + 22 + 2; // 帧头+帧长+源+目标+类型+22字节输出读取+校验
|
||
|
||
// 帧头
|
||
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;
|
||
|
||
// 7字节使能状态(直接复制 body 到 tx[9]~tx[15])
|
||
memcpy(&tx[9], body, 22); // 确保 body 是22字节
|
||
|
||
// 校验和
|
||
uint16_t checksum = 0;
|
||
for (int i = 4; i < 32; ++i) // 4~32(源地址+目标地址+类型+22字节)
|
||
{
|
||
checksum += tx[i];
|
||
}
|
||
|
||
// 校验和2字节(大端,只取低8位)
|
||
tx[total_len - 2] = 0x00; // 高8位强制为0(如果协议要求)
|
||
tx[total_len - 1] = checksum & 0xFF;
|
||
|
||
return total_len;
|
||
}
|
||
uint16_t handle_type_86(const uint8_t *body, uint16_t body_len, uint8_t *tx)
|
||
{
|
||
uint16_t total_len = 2 + 2 + 2 + 2 + 1 + 22 + 2; // 帧头+帧长+源+目标+类型+22字节输出读取+校验
|
||
|
||
// 帧头
|
||
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;
|
||
|
||
// 7字节使能状态(直接复制 body 到 tx[9]~tx[15])
|
||
memcpy(&tx[9], body, 22); // 确保 body 是22字节
|
||
|
||
// 校验和
|
||
uint16_t checksum = 0;
|
||
for (int i = 4; i < 32; ++i) // 4~31(源地址+目标地址+类型+22字节)
|
||
{
|
||
checksum += tx[i];
|
||
}
|
||
|
||
// 校验和2字节(大端,只取低8位)
|
||
tx[total_len - 2] = 0x00; // 高8位强制为0(如果协议要求)
|
||
tx[total_len - 1] = checksum & 0xFF;
|
||
|
||
return total_len;
|
||
}
|
||
uint16_t handle_type_87(const uint8_t *body, uint16_t body_len, uint8_t *tx)
|
||
{
|
||
uint16_t total_len = 2 + 2 + 2 + 2 + 1 + 74 + 2; // 帧头+帧长+源+目标+类型+74字节输出读取+校验
|
||
|
||
// 帧头
|
||
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;
|
||
|
||
// 7字节使能状态(直接复制 body 到 tx[9]~tx[15])
|
||
memcpy(&tx[9], body, 74); // 确保 body 是74字节
|
||
|
||
// 校验和
|
||
uint16_t checksum = 0;
|
||
for (int i = 4; i < 84; ++i) // 4~83(源地址+目标地址+类型+74字节)
|
||
{
|
||
checksum += tx[i];
|
||
}
|
||
|
||
// 校验和2字节(大端,只取低8位)
|
||
tx[total_len - 2] = 0x00; // 高8位强制为0(如果协议要求)
|
||
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://读取模块使能状态
|
||
{
|
||
uint16_t body_len = 7; //7个字节表示的是各个模块的使能状态
|
||
reply_type = tcp_rx_data[8];
|
||
tx_data_len = handle_type_83(enable_data, body_len, tcp_tx_data);
|
||
}
|
||
break;
|
||
case 0x84://设置模块使能状态
|
||
{
|
||
uint16_t body_len = 7; //7个字节表示的是各个模块的使能状态
|
||
reply_type = tcp_rx_data[8];
|
||
tx_data_len = handle_type_84(tcp_rx_data + 9, body_len, tcp_tx_data);
|
||
}
|
||
break;
|
||
case 0x85://读取读取配置参数
|
||
{
|
||
uint16_t body_len = 22; //22个字节表示的是输出参数
|
||
reply_type = tcp_rx_data[8];
|
||
tx_data_len = handle_type_85(adc_read_data, body_len, tcp_tx_data);
|
||
}
|
||
break;
|
||
case 0x86://设置配置参数
|
||
{
|
||
uint16_t body_len = 22; //22个字节表示的是设置的参数
|
||
reply_type = tcp_rx_data[8];
|
||
tx_data_len = handle_type_86(adc_set_data, body_len, tcp_tx_data);
|
||
}
|
||
break;
|
||
case 0x87://读取测试数据
|
||
{
|
||
uint16_t body_len = 74; //22个字节表示的是设置的参数
|
||
reply_type = tcp_rx_data[8];
|
||
tx_data_len = handle_type_87(test_adc_read_data, body_len, tcp_tx_data);
|
||
}
|
||
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);
|
||
}
|
||
}
|