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); } } } }
欢迎讨论,相互学习。
cdtxw@foxmail.com

浙公网安备 33010602011771号