pile_com_stm32/main/modbus-tcp.c

141 lines
5.1 KiB
C
Raw Normal View History

2024-04-15 18:04:26 +08:00
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <string.h>
#include "lwip/ip_addr.h"
#include "lwip/tcp.h"
#include "lwip/err.h"
#include "lwip/opt.h"
#include "lwip/sockets.h"
#include "stm32/ModbusS.h"
#include "esp_log.h"
// #include "log.h"
#define LOG_TAG "[mb_tcp_sr]: "
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
// static err_t ModBusSlave_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
// static err_t ModBusSlave_accept(void *arg, struct tcp_pcb *pcb, err_t err);
// static void ModBusSlave_conn_err(void *arg, err_t err);
// static err_t ModBusSlave_poll(void *arg, struct tcp_pcb *pcb);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Called when a data is received on the telnet connection
* @param arg the user argument
* @param pcb the tcp_pcb that has received the data
* @param p the packet buffer
* @param err the error value linked with the received data
* @retval error value
*/
int ModBusTcpMonitor;
static err_t ModBusSlave_recv(void *arg, struct tcp_pcb *newpcb, struct pbuf *p, err_t err) {
/* We perform here any necessary processing on the pbuf */
if (p != NULL) {
uint8_t *txbuf;
uint8_t *rxbuf;
int txlen, rxlen;
/* We call this function to tell the LwIp that we have processed the data */
/* This lets the stack advertise a larger window, so more data can be received*/
tcp_recved(newpcb, p->tot_len);
rxbuf = (uint8_t *)p->payload;
rxlen = p->len;
if (rxlen < 6) {
pbuf_free(p);
return tcp_close(newpcb);
}
txbuf = (uint8_t *)mem_malloc(1024 + 16);
if (txbuf == NULL) {
return tcp_close(newpcb);
}
ModBusTcpMonitor = 0;
txlen = ModbusSlaveProcess(&txbuf[6], &rxbuf[6], (rxlen - 6), 0); //以前有 2023年4月24日14:39:11
// log_printf(LINFO, LOG_TAG "[%s] ModbusSlaveProcess (ret=%d)", __FUNCTION__, txlen);
if (txlen > 0) {
int i;
for (i = 0; i < 4; i++) {
txbuf[i] = rxbuf[i];
}
txbuf[4] = (uint8_t)(txlen >> 8);
txbuf[5] = (uint8_t)(txlen & 0xff);
tcp_write(newpcb, txbuf, txlen + 6, 1);
ModBusTcpMonitor = 0;
}
mem_free(txbuf);
/* End of processing, we free the pbuf */
pbuf_free(p);
} else if (err == ERR_OK) {
/* When the pbuf is NULL and the err is ERR_OK, the remote end is closing the connection. */
/* We free the allocated memory and we close the connection */
// log_printf(LWARN, LOG_TAG "remote end is closing the connection\n");
tcp_err(newpcb, NULL);
tcp_recv(newpcb, NULL);
tcp_poll(newpcb, NULL, 120); // 60 second timeout
// return tcp_close(newpcb);
err_t err_p = tcp_close(newpcb);
if (ERR_OK != err_p) {
// log_printf(LERROR, LOG_TAG "close error. err:%d\n", err_p);
}
return err_p;
}
return ERR_OK;
}
/**
* @brief This function is called when an error occurs on the connection
* @param arg
* @parm err
* @retval None
*/
static void ModBusSlave_conn_err(void *arg, err_t err) {
// log_printf(LERROR, LOG_TAG "connection error, err:%d\n", err);
}
static err_t ModBusSlave_poll(void *arg, struct tcp_pcb *newpcb) {
// if (newpcb) {
// // log_printf(LERROR, LOG_TAG "close pcb\n");
// tcp_close(newpcb);
// newpcb = NULL;
// }
ESP_LOGI(LOG_TAG, "HELLO!");
return ERR_OK;
}
/**
* @brief This function when the Telnet connection is established
* @param arg user supplied argument
* @param pcb the tcp_pcb which accepted the connection
* @param err error value
* @retval ERR_OK
*/
static err_t ModBusSlave_accept(void *arg, struct tcp_pcb *pcb, err_t err) {
/* Tell LwIP to associate this structure with this connection. */
// tcp_arg(pcb, mem_calloc(sizeof(struct name), 1));
/* Configure LwIP to use our call back functions. */
tcp_err(pcb, ModBusSlave_conn_err);
tcp_recv(pcb, ModBusSlave_recv);
tcp_poll(pcb, ModBusSlave_poll, 1); // 60 second timeout
/* Send out the first message */
// tcp_write(pcb, GREETING, strlen(GREETING), 1);
return ERR_OK;
}
/**
* @brief Initialize the hello application
* @param None
* @retval None
*/
void ModBusTCPSlave_init(void) {
struct tcp_pcb *pcb;
/* Create a new TCP control block */
pcb = tcp_new();
/* Assign to the new pcb a local IP address and a port number */
/* Using IP_ADDR_ANY allow the pcb to be used by any local interface */
tcp_bind(pcb, IP_ADDR_ANY, 502);
/* Set the connection to the LISTEN state */
pcb = tcp_listen(pcb);
/* Specify the function to be called when a connection is established */
tcp_accept(pcb, ModBusSlave_accept);
// LSAPI_Log_Debug("ModBus Tcp server listen port:%d\n", 502);
}
/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/