esp32 dev module模拟modbus TCP,SDK版本:2.0.9

esp32 dev module模拟modbus TCP,SDK版本:2.0.9

#include <WiFi.h>

const char* ssid     = "";
const char* password = "dfdde";
const char* host     = "112.12.130.23";

 

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

// ModbusTCP从站 502端口
WiFiServer mbServer(502);
WiFiClient mbClient;

// 线圈状态:线圈1~4,索引0‑3
bool coils[4] = {false, false, false, false};

// ESP32 DevModule 安全输出引脚,避开GPIO12/GPIO15 strapping风险
#define PIN_COIL1  26
#define PIN_COIL2  27
#define PIN_COIL3  14
#define PIN_COIL4  25

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

// WiFi自动重连配置
unsigned long wifiReconnectTimer = 0;
const unsigned long wifiReconnectInterval = 3000; // 断网后3s尝试重连

// 线圈状态同步输出到硬件
void syncCoilOutput()
{
    digitalWrite(PIN_COIL1, coils[0] ? HIGH : LOW);
    digitalWrite(PIN_COIL2, coils[1] ? HIGH : LOW);
    digitalWrite(PIN_COIL3, coils[2] ? HIGH : LOW);
    digitalWrite(PIN_COIL4, coils[3] ? HIGH : LOW);

    Serial.printf("Coil1:%d Coil2:%d Coil3:%d Coil4:%d | PIN26:%d PIN27:%d PIN14:%d PIN25:%d\n",
        coils[0], coils[1], coils[2], coils[3],
        digitalRead(PIN_COIL1),
        digitalRead(PIN_COIL2),
        digitalRead(PIN_COIL3),
        digitalRead(PIN_COIL4));
}

// WiFi非阻塞重连处理,放在loop中调用
void wifiAutoReconnect()
{
    if (WiFi.status() == WL_CONNECTED)
    {
        wifiReconnectTimer = millis();
        return;
    }

    if (millis() - wifiReconnectTimer >= wifiReconnectInterval)
    {
        wifiReconnectTimer = millis();
        Serial.println("WiFi断开,开始尝试重连...");
        // 断开旧连接
        WiFi.disconnect();
        delay(100);
        WiFi.begin(ssid, password);
    }
}

// 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));

    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++;
        }
        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);
        client.write((const uint8_t*)resp, 12);
    }
}

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

    pinMode(pinD2, OUTPUT);
    pinMode(PIN_COIL1, OUTPUT);
    pinMode(PIN_COIL2, OUTPUT);
    pinMode(PIN_COIL3, OUTPUT);
    pinMode(PIN_COIL4, OUTPUT);

    digitalWrite(PIN_COIL1, LOW);
    digitalWrite(PIN_COIL2, LOW);
    digitalWrite(PIN_COIL3, LOW);
    digitalWrite(PIN_COIL4, 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初始连接失败,进入后台自动重连模式!");
    }
    else
    {
        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");

    wifiReconnectTimer = millis();
}

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()
{
    // WiFi断网自动重连
    wifiAutoReconnect();

    // WiFi刚恢复连接打印IP
    static bool lastWifiConnected = false;
    bool nowWifiConnected = (WiFi.status() == WL_CONNECTED);
    if(nowWifiConnected && !lastWifiConnected)
    {
        Serial.println("\n==== WiFi重连成功 ====");
        Serial.print("本机IP:");
        Serial.println(WiFi.localIP());
        Serial.println("======================");
    }
    lastWifiConnected = nowWifiConnected;


    // ModbusTCP 502处理
    WiFiClient newMbClient = mbServer.available();
    if(newMbClient)
    {
        if(mbClient.connected())
        {
            mbClient.stop();
        }
        mbClient = newMbClient;
    }

    if(mbClient.connected() && mbClient.available() >= 12)
    {
        uint8_t buf[128];
        int rlen = mbClient.readBytes(buf, mbClient.available());
        handleModbusTcp(buf, rlen, mbClient);
    }

    // 60001 TCP服务处理
    WiFiClient newClient = server.available();
    if (newClient)
    {
        uint8_t i;
        for (i = 0; i < MAX_SRV_CLIENTS; i++)
        {
            if (!serverClients[i] || !serverClients[i].connected())
            {
                if(serverClients[i])
                {
                    serverClients[i].stop();
                }
                serverClients[i] = newClient;
                Serial.print("1个新的客户端: ");
                Serial.println(i);
                Serial.println(666);
                break;
            }
        }
        if (i == MAX_SRV_CLIENTS)
        {
            newClient.stop();
            Serial.println("连接被拒绝 ");
        }
    }

    for (uint8_t i = 0; i < MAX_SRV_CLIENTS; i++)
    {
        if (serverClients[i] && serverClients[i].connected())
        {
            if (serverClients[i].available())
            {
                char recv_msg[1024];
                String recv_str_from_client = "";
                int index2 = 0;
                while (serverClients[i].available() && index2 < 1023)
                {
                    char recv_word = serverClients[i].read();
                    recv_str_from_client += recv_word;
                    recv_msg[index2++] = recv_word;
                }
                recv_msg[index2] = '\0';

                Serial.println("string type print");
                Serial.println(recv_str_from_client);
                Serial.write("\n------------------\n");

                String original_open2 = "c11_open";
                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);
                }

                byte recv_str[1024];
                for (int k = 0; k < index2; k++)
                {
                    recv_str[k] = recv_msg[k];
                }
                recv_str[index2] = 0x00;

                char recv_str_2[1024] = "";
                array_to_string(recv_str, 36, recv_str_2);

                int ori_length = strlen(recv_msg);
                String aa = "ori_length=";
                aa += ori_length;
                Serial.println(aa);
                aa = "index2=";
                aa += index2;
                Serial.println(aa);
            }
        }
    }

    // 串口输入处理
    if (Serial.available())
    {
        size_t len = Serial.available();
        uint8_t sbuf[len];
        Serial.readBytes(sbuf, len);
        String aa;
        for (size_t i = 0; i < len; i++)
        {
            aa += (char)sbuf[i];
        }
        if (aa == "abc")
        {
            digitalWrite(pinD2, HIGH);
        }
        else
        {
            digitalWrite(pinD2, LOW);
        }
        for (uint8_t 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-31 22:09  txwtech  阅读(2)  评论(0)    收藏  举报