controller-pcba/User/application/src/tcpserverc.c

548 lines
18 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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 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);
}
}