esp8266模拟modbus TCP-SDK版本:2.3.0

esp8266模拟modbus TCP

#include <ESP8266WiFi.h>

const char* ssid = "xxxx";
const char* password = "xxdfdf@";
const char* host = "112.12.130.23";

#define MAX_SRV_CLIENTS 1
WiFiServer server(60001);
WiFiClient serverClients[MAX_SRV_CLIENTS];

// ModbusTCP从站服务
WiFiServer mbServer(502);
WiFiClient mbClient;

// 线圈状态:线圈1~4,对应索引0‑3
bool coils[4] = {false, false, false, false};
#define PIN_D5 D5   // 线圈1
#define PIN_D6 D6   // 线圈2
#define PIN_D7 D7   // 线圈3
#define PIN_D8 D8   // 线圈4 【警告:上电必须低电平】

int LED6 = D6;
int pinD2 = 2;
int pinD0 = 0;
int senVal = 0;

// 将线圈状态同步输出到硬件引脚
void syncCoilOutput()
{
    digitalWrite(PIN_D5, coils[0] ? HIGH : LOW);
    digitalWrite(PIN_D6, coils[1] ? HIGH : LOW);
    digitalWrite(PIN_D7, coils[2] ? HIGH : LOW);
    digitalWrite(PIN_D8, coils[3] ? HIGH : LOW);
    Serial.printf("Coil1:%d Coil2:%d Coil3:%d Coil4:%d | D5:%d D6:%d D7:%d D8:%d\n",
        coils[0], coils[1], coils[2], coils[3],
        digitalRead(PIN_D5), digitalRead(PIN_D6), digitalRead(PIN_D7), digitalRead(PIN_D8));
}

// 处理ModbusTCP报文,只实现FC01读线圈、FC05写单线圈
void handleModbusTcp(uint8_t *req, uint16_t len, WiFiClient &client)
{
    if(len < 12) return;
    uint16_t transId = (req[0] << 8) | req[1];
    uint16_t protoId = (req[2] << 8) | req[3];
    uint8_t  slaveId = req[6];
    uint8_t  func    = req[7];

    if(protoId != 0 || slaveId != 1) return;

    uint8_t resp[256];
    memset(resp,0,sizeof(resp));
    // Modbus TCP头部
    resp[0] = transId >> 8;
    resp[1] = transId & 0xFF;
    resp[2] = 0x00;
    resp[3] = 0x00;

    if(func == 0x01) // FC01 读线圈
    {
        uint16_t startAddr = (req[8] << 8) | req[9];
        uint16_t qty       = (req[10] << 8) | req[11];
        if(startAddr + qty > 4) return;
        uint8_t byteCnt = (qty + 7)/8;
        resp[4] = 0;
        resp[5] = 3 + byteCnt;
        resp[6] = 1;
        resp[7] = 0x01;
        resp[8] = byteCnt;
        uint8_t bitPos = 0;
        for(uint16_t i=0; i<qty; i++)
        {
            uint16_t coilIdx = startAddr + i;
            if(coils[coilIdx])
            {
                resp[9 + (bitPos/8)] |= (1 << (bitPos%8));
            }
            bitPos++;
        }
        // 强制转指针,修复2.3.0编译bug
        client.write((const uint8_t*)resp, 9 + byteCnt);
    }
    else if(func == 0x05) // FC05 写单线圈
    {
        uint16_t coilAddr = (req[8] << 8) | req[9];
        uint16_t value    = (req[10] << 8) | req[11];
        if(coilAddr >=4) return;
        coils[coilAddr] = (value == 0xFF00);
        syncCoilOutput();
        // 回显原请求作为应答
        resp[4] = 0;
        resp[5] = 6;
        memcpy(resp+6, req+6, 6);
        // 强制转指针,修复2.3.0编译bug
        client.write((const uint8_t*)resp, 12);
    }
}

void setup()
{
    Serial.begin(115200);
    WiFi.mode(WIFI_STA);

    pinMode(pinD2, OUTPUT);
    pinMode(PIN_D5, OUTPUT);
    pinMode(PIN_D6, OUTPUT);
    pinMode(PIN_D7, OUTPUT);
    pinMode(PIN_D8, OUTPUT);
    digitalWrite(PIN_D5, LOW);
    digitalWrite(PIN_D6, LOW);
    digitalWrite(PIN_D7, LOW);
    digitalWrite(PIN_D8, LOW);

    WiFi.begin(ssid, password);
    Serial.print("\n连接WiFi:");
    Serial.println(ssid);
    uint8_t i = 0;
    while (WiFi.status() != WL_CONNECTED && i++ < 20) {
        delay(500);
        Serial.print(".");
    }
    if (i == 21) {
        Serial.println("\nWiFi连接失败!");
        return;
    }

    // ============打印本机IP MAC============
    Serial.println("\n========================");
    Serial.print("本机IP: ");
    Serial.println(WiFi.localIP());
    Serial.print("本机MAC: ");
    Serial.println(WiFi.macAddress());
    Serial.println("========================");

    server.begin();
    server.setNoDelay(true);
    mbServer.begin();

    Serial.println("ModbusTCP端口:502 从站ID=1");
    Serial.println("自定义TCP端口: 60001");
}

void array_to_string(byte array[], unsigned int len, char buffer[])
{
    for (unsigned int i = 0; i < len; i++)
    {
        byte nib1 = (array[i] >> 4) & 0x0F;
        byte nib2 = (array[i] >> 0) & 0x0F;
        buffer[i * 2 + 0] = nib1 < 0xA ? '0' + nib1 : 'A' + nib1 - 0xA;
        buffer[i * 2 + 1] = nib2 < 0xA ? '0' + nib2 : 'A' + nib2 - 0xA;
    }
    buffer[len * 2] = '\0';
}

void loop() {
    // ========= ModbusTCP处理 =========
    if(mbServer.hasClient())
    {
        if(mbClient.connected()) mbClient.stop();
        mbClient = mbServer.available();
    }
    if(mbClient.connected() && mbClient.available() >=12)
    {
        uint8_t buf[128];
        int rlen = mbClient.readBytes(buf, mbClient.available());
        handleModbusTcp(buf, rlen, mbClient);
    }

    // ========= 原有60001 TCP服务逻辑,完全保留 =========
    uint8_t i;
    if (server.hasClient())
    {
        for (i = 0; i < MAX_SRV_CLIENTS; i++)
        {
            if (!serverClients[i] || !serverClients[i].connected())
            {
                if (!serverClients[i])
                {
                    serverClients[i].stop();
                }
                serverClients[i] = server.available();
                Serial.print("1个新的客户端: ");
                Serial.println(i);
                Serial.println(666);
                break;
            }
        }
        if (i == MAX_SRV_CLIENTS)
        {
            WiFiClient client = server.available();
            client.stop();
            Serial.println("连接被拒绝 ");
        }
    }

    for (i = 0; i < MAX_SRV_CLIENTS; i++)
    {
        if (serverClients[i] && serverClients[i].connected())
        {
            char recv_msg[1024];
            String recv_str_from_client = "";
            int index2 = 0;
            if (serverClients[i].available())
            {
                while (serverClients[i].available())
                {
                    char recv_word = serverClients[i].read();
                    recv_str_from_client = recv_str_from_client + recv_word;
                    recv_msg[index2] = recv_word;
                    index2++;
                }
                recv_msg[index2] = '\0';
                Serial.println("string type print");
                Serial.println(recv_str_from_client);
                Serial.write("\n------------------\n");
                const byte sbuf2[] = "recv_success";
                const byte sbuf_error[] = "recv_error";
                const char original_open[] = "c11_open";
                String original_open2 = "c11_open";
                byte recv_str[1024];
                String aa = "123";
                if (recv_str_from_client.compareTo(original_open2) == 0)
                {
                    Serial.println("相等");
                }
                else
                {
                    Serial.println("不相等");
                    Serial.println("recv_str_from_client:" + recv_str_from_client);
                    Serial.println("original_open:" + original_open2);
                }
                for (int i = 0; i < index2; i++)
                {
                    recv_str[i] = recv_msg[i];
                }
                recv_str[index2] = 0x0;
                char recv_str_2[1024] = "";
                array_to_string(recv_str, 36, recv_str_2);
                recv_str_2[index2] = '\0';
                int ori_length = strlen(recv_msg);
                aa = "ori_length=";
                aa = aa + ori_length;
                Serial.println(aa);
                aa = "index2=";
                aa = aa + index2;
               // serverClients[i].write((const uint8_t*)sbuf2, sizeof(sbuf2) / sizeof(sbuf2[0]));
               // serverClients[i].write((const uint8_t*)sbuf_error, sizeof(sbuf_error) / sizeof(sbuf_error[0]));
            }
        }
    }

    if (Serial.available())
    {
        size_t len = Serial.available();
        uint8_t sbuf[len];
        Serial.readBytes(sbuf, len);
        String aa;
        for (int i = 0; i < sizeof(sbuf); i++)
        {
            aa = aa + sbuf[i];
        }
        if (aa == "abc")
        {
            digitalWrite(pinD2, HIGH);
        }
        else
        {
            digitalWrite(pinD2, LOW);
        }
        for (i = 0; i < MAX_SRV_CLIENTS; i++)
        {
            if (serverClients[i] && serverClients[i].connected())
            {
                serverClients[i].write((const uint8_t*)sbuf, len);
                delay(1);
            }
        }
    }
}

 

posted @ 2026-08-30 20:41  txwtech  阅读(2)  评论(0)    收藏  举报