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

浙公网安备 33010602011771号