F103 modbus TCP

Dependencies:   BufferedSerial BufferedSoftSerial CRC16 Nucleo_F103RB_W5500HelloWorld MessageQueue WIZnet_Library Watchdog eeprom mbed-rtos mbed

Fork of Nucleo_F103RB_W5500HelloWorld by WIZnet

Revision:
2:2541ce0cc63e
Parent:
1:9a6af61c5eb4
--- a/main.cpp	Sun May 17 11:12:56 2015 +0000
+++ b/main.cpp	Tue Nov 01 14:28:23 2016 +0000
@@ -1,86 +1,684 @@
 #include "mbed.h"
 #include "WIZnetInterface.h"
+#include <string>
+#include "Serial.h"
+#include "eeprom.h"
+#include "CRC16.h"
+#include "Watchdog.h"
+#include "rtos.h"
+//Serial mdb232(PA_9,PA_10);
+//Serial mdb485(PA_2,PA_3);
+Serial *pc;//
+DigitalOut pcSendRev(PB_0);//0 rev  1 send
+Watchdog wd;
+bool reset_soft = false;// 控制停止喂狗使设备复位
+struct CONFIG{
+    char ipAddr[16];
+    char ipSubnet[16];
+    char ipGateway[16];
+    int16_t port;
+    unsigned char MAC_Addr[6] ;
+    
+    int8_t RTUChoice;       //1:RTU模式 0:ascii
+    int8_t bits;            //5-8bit
+    SerialBase::Parity parity;        //  SerialBase::Odd , SerialBase::Even  SerialBase::None    分别用int 1,2,3代表
+    int8_t stop_bits;       //1-2bit
+    int16_t baud;
+    int16_t frameTimeOut;
+    int16_t timeOut;
+    int16_t RS  ;              //485 232
+    }Config_t = {             //默认值
+        "192.168.31.3",
+        "255.255.255.0",
+        "192.168.31.1",
+        (int16_t)502,       //port
+        {0x00,0x08,0xDC,0x12,0x34,0x56},//mac地址
+        1,                  //choice RTU mode
+        8,                  //数据位8位
+        SerialBase::None,
+        1,                  //stop
+        (int16_t)19200,      //baud
+        7 ,                  //帧超时7ms
+        1500  ,                 //等待超时1500ms
+        485
+        }; 
+CONFIG Config = Config_t;//备份一个配置信息。         
+static  char buffer[256] ;           //接收或者发送用的临时buffer
+uint16_t buffer_num = 6;
+struct TCP_BUFFER{          //
+    char xid[2];
+    char pid[2];
+    int16_t length;
+    char serialAddr;
+    char data[255];
+    }tcp_buffer;
+    
+struct SERIAL_BUFFER{
+    char serialAddr;        //地址
+    char funCode;           //功能码
+    char data[252];
+    char crc[2];            //低位前高位后
+    }serial_buffer;
+    
+enum flagThread1{
+    waitThead1,
+    connectedThead1,
+    tcpRecvThead1,
+    serialRecvThead1,
+    tcpSendThead1
+    }flagThread1;            //状态机标识  thread1
+    
+enum FlagThead2{
+     waitThead2,
+     connectedThead2,
+     handleDataThead2,
+     getReguestThead2,
+     postReguestThead2
+     }flagThread2;           //状态机标识 thread2
+char readline[200];    //解析提交的表单 读取一行数据 再存在这 
+SPI spi(PA_7, PA_6, PA_5); // mosi, miso, sclk
+WIZnetInterface ethernet(&spi, PB_6, PB_7);//scs(PB_6), nRESET(PB_7); // reset pin is dummy, don't affect any pin of WIZ550io
+EEPROM memory(I2C_SDA,I2C_SCL,0,EEPROM::T24C02);     
+   
+TCPSocketServer webserver;
+TCPSocketConnection webclient;
+TCPSocketServer server;
+TCPSocketConnection client;  
+int rev_num;//tcp收到的直接数     
+  
+/*****************************计算超时用到的函数及变量*************************************************/
+bool flagT35 = false; //是否接受了串口数据标志  ture 接收到串口数据
+Timer timeout; //1s 超时
+Timer timeoutT35;//t3.5超时
+void timeoutTest();    //串口中断服务程序
 
-#define USE_DHCP    1
+/*********************状态机处理函数*************************************/
+
+void InitDefault(void);
+void InitEEprom(void);
 
-#define LOOPBACKPORT    5000
+
+void TcpRecvThead1(void);
+void SerialRecvThead1(void);
+void TcpSendThead1(void);
 
-const char * IP_Addr    = "192.168.11.194";
-const char * IP_Subnet  = "255.255.255.0";
-const char * IP_Gateway = "192.168.11.1";
-unsigned char MAC_Addr[6] = {0x00,0x08,0xDC,0x12,0x34,0x56};
+int webclientReadline();
+int readSubmit( char *d,char a);
+void webServerHandleData (void const *args)
+{
+    string sbuffer;
+    char *cbuffer = new char[100];
+    int numRev;
+    string sget = "GET";
+    string spost = "POST";
+    while(true) {
+        Thread::signal_wait(0x2);
+        if ( flagThread2 ==  handleDataThead2 ) {
+            sbuffer.clear();
+            numRev= webclient.receive(cbuffer,3);
+            if (numRev == 3) {
+                sbuffer.append(cbuffer,3);
+                if (sbuffer == sget) {
+                    printf("get\r\n");
+                    flagThread2 = getReguestThead2;
+                    do {
+                        numRev = webclient.receive(cbuffer,100);
+                    } while(numRev == 100) ;
+                }//清空rev buffer
+                else {
+                    webclient.receive(cbuffer,1);
+                    sbuffer.append(cbuffer,1);
+                    if(sbuffer == spost) {
+                        printf("post\r\n");
+                        flagThread2 = postReguestThead2;
+                    } else {
+                        printf("no\r\n");
+                        flagThread2 = waitThead2;
+                        webclient.close();
+                    }
+                }
+            } else
+                flagThread2 = waitThead2;
+        }
+    }
+}
+
+void webServerGetReguest(void const *args)
+{
+    string sbuffer;
+    char str[10];
+    sbuffer.assign("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n");
+    sbuffer.append("Connection: close\r\n\r\n<!DOCTYPE HTML>\r\n");
+    sbuffer.append("<html>\r\n<form id = \"muForm\"action=\"/config\"method=\"post\">\r\n");
+    sbuffer.append("<table id=\"attfile\">\r\n<tr><td>NETWORK</td></tr>");
+
+    sbuffer.append("<tr><td>IP</td>\r\n<td><input type=\"text\"name=\"IP\"size=\"20\"value=\"");
+    sbuffer.append(ethernet.getIPAddress());
+    sbuffer.append("\"></td><td> e.g. 192.168.1.55</td></tr>");
+
+    sbuffer.append("<tr><td>MASK</td><td><input type=\"text\" name=\"MASK\" size=\"20\"value=\"");
+    sbuffer.append(Config.ipSubnet);
+    sbuffer.append("\"></td><td> e.g. 255.255.255.0</td></tr>");
+
+    sbuffer.append("<tr><td>gateway</td> <td><input type=\"text\" name=\"gateway\" size=\"20\"value=\"");
+    sbuffer.append(Config.ipGateway);
+    sbuffer.append("\"></td><td> e.g. 192.168.1.1</td></tr>");
+
+    sbuffer.append("<tr><td>PORT</td> <td><input type=\"text\" name=\"PORT\" size=\"20\"value=\"");
+    sprintf(str,"%d",Config.port);
+    sbuffer.append(str);
+    sbuffer.append("\"></td><td> e.g. 502</td></tr>");
+
+    sprintf(str,"%d",Config.baud);
+    sbuffer.append("<tr><td>Serial</td> </tr><tr><td>baud</td> <td><input type=\"text\" name=\"baud\"size=\"20\"value=\"");
+    sbuffer.append(str);
+    sbuffer.append("\"></td><td> e.g. 115200 19200 9600</td> </tr>");
+
+
+    sbuffer.append("<tr><td>parity</td> <td><input type=\"text\"name=\"parity\"size=\"20\"value=\"");
+    switch(Config.parity) {
+        case SerialBase::Odd:
+            sbuffer.append("odd");
+            break;
+        case SerialBase::Even:
+            sbuffer.append("even");
+            break;
+        case SerialBase::None:
+            sbuffer.append("none");
+            break;
+    }
+
+    sbuffer.append("\"></td><td> e.g. none even odd</td> </tr>");
+
+    sbuffer.append("<tr><td>bits</td> <td><input type=\"text\"name=\"bits\"size=\"20\"value=\"");
+    int t;
+    if(Config.parity != SerialBase::None)
+       t = Config.bits -1;
+    else 
+        t=Config.bits;
+    sprintf(str,"%d",t);
+    sbuffer.append(str);
+    sbuffer.append("\"></td><td> e.g. 7-8</td> </tr>");
+    
+    
+    sbuffer.append("<tr><td>stop_bits</td> <td><input type=\"text\"name=\"stop_bits\"size=\"20\"value=\"");
+    sprintf(str,"%d",Config.stop_bits);
+    sbuffer.append(str);
+    sbuffer.append("\"></td><td> e.g. 1-2</td> </tr>");
+
+    sbuffer.append("<tr><td>The frame timeout</td> <td><input type=\"text\"name=\"t35\"size=\"20\"value=\"");
+    sprintf(str,"%d",Config.frameTimeOut);
+    sbuffer.append(str);
+    sbuffer.append("\"></td><td> ms</td> </tr>");
+
+    sbuffer.append("<tr><td>timeout</td> <td><input type=\"text\"name=\"timeout\"size=\"20\"value=\"");
+    sprintf(str,"%d",Config.timeOut);
+    sbuffer.append(str);
+    sbuffer.append("\"></td><td> ms</td></tr>");
+
+    sbuffer.append("<tr><td>232 or 485</td> <td><input type=\"text\" name=\"232or485\" size=\"20\"value=\"");
+    sprintf(str,"%d",Config.RS);
+    sbuffer.append(str);
+    sbuffer.append("\"></td><td> e.g. 232 485</td> </tr>");
+
+    sbuffer.append("</table><input type = \"button\"onclick= \"formSubmit()\" value=\"submit\">");
+    sbuffer.append("</form><script type=\"text/javascript\">");
 
-DigitalOut myled1(LED1);
-Serial pc(USBTX, USBRX);
+    sbuffer.append("function formSubmit()");
+    sbuffer.append("{document.getElementById(\"muForm\").submit()}");
+    sbuffer.append("</script></html>");
+
+    while(true) {
+        Thread::signal_wait(0x3);
+        if(flagThread2 == getReguestThead2 ) {
+            webclient.send_all((char *)sbuffer.c_str(),sbuffer.length());
+            webclient.close();
+            flagThread2 = waitThead2;
+        }
+    }
+}
+
+
+void modbus_tcp_rs(void const *args)
+{
+    while(true) {
+
+       if(flagThread1 == connectedThead1) {
+            
+
+          
+            pcSendRev = 1;//send
+            rev_num = client.receive(buffer,6);
+          
+            if(rev_num == 6) {
+                //   client.send_all("connectedThead1",15);
+                tcp_buffer.xid[0] =  buffer[0];
+                tcp_buffer.xid[1] =  buffer[1];
+                tcp_buffer.pid[0] =  buffer[2];
+                tcp_buffer.pid[1] =  buffer[3];
+                tcp_buffer.length =  buffer[4];
+                tcp_buffer.length =  tcp_buffer.length <<8;
+                tcp_buffer.length =  tcp_buffer.length | buffer[5];
+                rev_num = client.receive(buffer,tcp_buffer.length);
+                tcp_buffer.serialAddr =  buffer[0];
+                if (rev_num == tcp_buffer.length){
+                    TcpRecvThead1(); //处理tcp接收到的数据包 串口发送出去
+                    SerialRecvThead1();//等待接收串口数据
+                    if(flagThread1 == tcpSendThead1){
+                        tcp_buffer.length = buffer_num-8;//前面空了6个 后面2个crc去掉
+                        buffer[0] = tcp_buffer.xid[0];
+                        buffer[1] = tcp_buffer.xid[1];
+                        buffer[2] = tcp_buffer.pid[0];
+                        buffer[3] = tcp_buffer.pid[1];
+                        buffer[4] = tcp_buffer.length>>8 & 0xff;
+                        buffer[5] = tcp_buffer.length & 0xff;
+                        client.send_all(buffer,buffer_num-2);//打包发送 mdb tcp
+                        flagThread1 = connectedThead1;
+                    }  
+                }
+            }
+       }
+     Thread::wait(200);
+    }
+}
+
+
+void webServerPost(void const *args)
+{   string spost;
+    char str[10];
+    spost.assign("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n");
+    spost.append("Connection: close\r\n\r\n<!DOCTYPE HTML>\r\n");
+    spost.append("<html>reset now!! Remember !!! IP:");
+    
+    while(1) {
+        Thread::signal_wait(0x05);
+        if(flagThread2 == postReguestThead2) {
+         //-----------读取表单参数--------------------------   
+           
+            while(webclientReadline());//返回 0 结束  后面的就是提交的表单内容 ip=192.168.1.3....
+            
+            readSubmit(readline,'=');//"IP"之类的  
+                  
+            readSubmit(Config.ipAddr,'&');                                                                                    
+            readSubmit(readline,'=');//"mask"之类的            
+            readSubmit(Config.ipSubnet,'&');
+            readSubmit(readline,'=');//"gateway"之类的          
+            readSubmit(Config.ipGateway,'&');
+            readSubmit(readline,'=');//"PORT"
+            readSubmit(readline,'&');           
+            Config.port= (int16_t)atoi(readline);            
+            readSubmit(readline,'=');//"baud"
+            readSubmit(readline,'&');
+            Config.baud= (int16_t)atoi(readline);    
+            readSubmit(readline,'=');//"parity"           
+            readSubmit(readline,'&');
+            string s = readline;            
+            if(s == "none" )
+            Config.parity= SerialBase::None;
+            if(s == "even" )
+            Config.parity= SerialBase::Even;
+            if(s == "odd" )
+            Config.parity= SerialBase::Odd;
+            readSubmit(readline,'=');//"bits"
+            readSubmit(readline,'&');    
+            Config.bits= (int8_t)atoi(readline);
+            readSubmit(readline,'=');//"stop_bits"
+            readSubmit(readline,'&');    
+            Config.stop_bits= (int8_t)atoi(readline);   
+            readSubmit(readline,'=');//"T35"
+            readSubmit(readline,'&');     
+            Config.frameTimeOut= (int16_t)atoi(readline);  
+            readSubmit(readline,'=');//"timeout"
+            readSubmit(readline,'&');     
+            Config.timeOut= (int16_t)atoi(readline); 
+            readSubmit(readline,'=');//"232or485"
+            readSubmit(readline,'&');     
+            Config.RS= (int16_t)atoi(readline); 
+    
 
-#ifdef TARGET_LPC11U68
-    SPI spi(P0_9,P0_8,P1_29);
-    WIZnetInterface ethernet(&spi,P0_2,P1_13);
-#elif defined(TARGET_NUCLEO_F103RB)
-    SPI spi(PA_7, PA_6, PA_5); // mosi, miso, sclk
-    WIZnetInterface ethernet(&spi, PB_6, PA_9);//scs(PB_6), nRESET(PA_9); // reset pin is dummy, don't affect any pin of WIZ550io
-#endif
+//--------------------发送更新后的 页面 ip port-----------------            
+            spost.append(Config.ipAddr);            
+            spost.append("    PORT:");
+            sprintf(str,"%d",Config.port);
+            spost.append(str);
+            spost.append("</html>");
+            webclient.send_all((char *)spost.c_str(),spost.length());
+            webclient.close();
+            
+       //---------- 存进eeprom 参数-----------------------
+          
+          memory.write(1,0xaa);
+          wait_ms(2);
+          memory.write(32,Config.ipAddr,8);
+          
+          wait_ms(2);
+          memory.write(40,Config.ipAddr+8,8);
+          wait_ms(2);
+          memory.write(48,Config.ipSubnet,8);
+          wait_ms(2);
+          memory.write(56,Config.ipSubnet+8,8);
+          wait_ms(2);
+          memory.write(64,Config.ipGateway,8);
+          wait_ms(2);
+          memory.write(72,Config.ipGateway+8,8);
+          wait_ms(2);          
+          memory.write(80,Config.MAC_Addr,6);
+          wait_ms(2);
+          memory.write(2,Config.port);
+          wait_ms(2);
+         
+          memory.write(7,Config.bits);
+          wait_ms(2);
+          if(Config.parity == SerialBase::Odd)           
+          memory.write(4,int8_t(1));
+          if(Config.parity == SerialBase::Even)
+          memory.write(4,int8_t(2));
+          if(Config.parity == SerialBase::None)
+          memory.write(4,int8_t(3)); 
+          wait_ms(2);        
+          memory.write(8,Config.stop_bits);
+          wait_ms(2);
+          memory.write(5,Config.baud); 
+          wait_ms(2);
+          memory.write(10,Config.RS); 
+          wait_ms(2);
+          //memory.write(12,Config.frameTimeOut); 
+         // wait_ms(2);
+          memory.write(14,Config.timeOut);          
+          flagThread2 = waitThead2;         
+          reset_soft = true; //复位
+               
+
+       } 
+    }
+}
+
+//----------------- 以特殊字符结尾的字符串-----------
+int readSubmit(char *d,char a)
+{
+    int num = 0;
+    while(1) {
+        //截取 等号 & 前的字符串
+
+        if(-1 == webclient.receive(&d[num],1)) {
+            d[num] = '\0';
+            return num;
+        }
+        if(d[num] != a)
+            num++;
+        else {
+            d[num] = '\0';
+            return num;
+        }
+
+    }
+}
+
+
+
+
+
+
+
+
+//----------返回一行的字节数--------------
+int webclientReadline()
+{
+    int num=0;
+    while(1) {
+        if( -1 == webclient.receive(&readline[num],1))
+            return -1;
+        if (readline[num] != '\r') 
+        num++;
+        else {
+            if(-1 == webclient.receive(&readline[num],1))
+                return -1;
+            if (readline[num] == '\n') ;
+            return num;
+        }
+    }
+}
+
+
+
+
+//--------------喂狗-----------------------
+
+void wd_server(void const *args) {   
+    while(true){
+    if (!reset_soft)
+            wd.Service();
+     Thread::wait(2000);       
+            }
+}
+
 
 int main() {
-    
-    mbed_mac_address((char *)MAC_Addr); //Use mbed mac addres
+    int16_t t232or485 =0;
+    memory.read(10,t232or485);
+    wait_ms(1);
     
-    //Set serial port baudrate speed: 115200
-    pc.baud(115200);
-    wait(10);
-    pc.printf("W5500 Application Started \r\n");
-
-    char buffer[256];
+    if ((uint16_t)t232or485 == (uint16_t)232)
+        pc = new Serial(PA_9,PA_10);//232
+    else 
+        pc = new Serial(PA_2,PA_3); //485
+        
+    pcSendRev = 1;//send
+    if(wd.WatchdogCausedReset())
+        printf("Watchdog caused reset.\r\n");
+    int8_t initChoice;
+    memory.read(1,initChoice); //查看一下eeprom是否初始化
+    wait_ms(1);
+    printf("%d",t232or485);
+    printf("int:%c\r\n",initChoice);
+    if( 0xAA == (uint8_t)initChoice )//已经初始化
+        {printf("aa\r\n");
+        InitEEprom();}
+    else
+        InitDefault();  
+    
+ //------------listen 502  80  -----------
+    
+    server.bind(Config.port);   //502
+    server.listen();
+    server.set_blocking(false, 0);
+    webserver.bind(80);
+    webserver.listen();
+    webserver.set_blocking(false, 0);
+    client.set_blocking(false, 0); // Timeout=0.
+    webclient.set_blocking(false, 0);
+    flagThread1 = waitThead1;   //状态机 初状态
+    flagThread2 = waitThead2;
+    wd.Configure(4);       // sets the timeout interval 大约6.1s    
+    //Thread thread1(wd_server) ;
+    
+    //---------------thread 开启 -----------------
+    Thread thread2(webServerHandleData,(void *)"2",osPriorityHigh );
+    Thread thread3(webServerGetReguest,(void *)"3",osPriorityHigh );
+    Thread thread4(modbus_tcp_rs,(void *)"4",osPriorityAboveNormal);
+    Thread thread5(webServerPost,(void *)"5",osPriorityRealtime );
     
-    while(1)
-    {
-        #if USE_DHCP
-        int ret = ethernet.init(MAC_Addr);
-        #else
-        int ret = ethernet.init(MAC_Addr,IP_Addr,IP_Subnet,IP_Gateway);
-        #endif
-        
-        
-        printf("SPI Initialized \r\n");
-        wait(1); // 1 second for stable state
-        
-        printf("W5500 Networking Started \r\n");
-        wait(1); // 1 second for stable state
-        
-        
+     //-----------对线程管理----------socket accept-----
+    while(1) {
+        if (client.is_fin_received()) {
+            client.close();
+            flagThread1 = waitThead1;
+        }
+        if(flagThread1 == waitThead1) {
+            server.accept(client);
+            if((client.is_connected() == true)  ) {
+                flagThread1 = connectedThead1;
+            }
+        }
+        if (!reset_soft)
+            wd.Service();
+        Thread::wait(50);
+        if(webclient.is_fin_received()) {
+            webclient.close();
+            flagThread2 = waitThead2;
+        }
+
+        if(flagThread2 == waitThead2) {
+            webserver.accept(webclient);
+            if((webclient.is_connected() == true)  ) {
+                flagThread2 = handleDataThead2;
+                thread2.signal_set(0x2);      //启动线程2 给他一个signal
+            }
+        }
+
+        if (flagThread2 == getReguestThead2)
+            thread3.signal_set(0x3);          //启动线程3 给他一个signal
+        if(flagThread2 == postReguestThead2)
+            thread5.signal_set(0x5);
+        if (!reset_soft)
+            wd.Service();   
+        Thread::wait(50);
+
+
+   
+    }
+}
+
+void InitDefault(void)
+{   pc->format(Config.bits,Config.parity,Config.stop_bits);
+    pc->baud(Config.baud);
+    int ret = ethernet.init(Config.MAC_Addr,Config.ipAddr,Config.ipSubnet,Config.ipGateway);
+    if (!ret) {
+        printf("Initialized, MAC: %s\r\n", ethernet.getMACAddress());
+        ret = ethernet.connect();
         if (!ret) {
-            pc.printf("Initialized, MAC: %s\r\n", ethernet.getMACAddress());
-            ret = ethernet.connect();
-            if (!ret) {
-                pc.printf("IP: %s, MASK: %s, GW: %s\r\n",
-                          ethernet.getIPAddress(), ethernet.getNetworkMask(), ethernet.getGateway());
+            printf("IP: %s, MASK: %s, GW: %s\r\n",
+            ethernet.getIPAddress(), ethernet.getNetworkMask(), ethernet.getGateway());
             } else {
-                pc.printf("Error ethernet.connect() - ret = %d\r\n", ret);
+                printf("Error ethernet.connect() - ret = %d\r\n", ret);
                 exit(0);
             }
         } else {
-            pc.printf("Error ethernet.init() - ret = %d\r\n", ret);
+            printf("Error ethernet.init() - ret = %d\r\n", ret);
             exit(0);
         }
-        
-        TCPSocketServer server;
-        server.bind(LOOPBACKPORT);
-        server.listen();
-        
-        while (1) {
-            pc.printf("\nWait for new connection...\r\n");
-            TCPSocketConnection client;
-            server.accept(client);
-            client.set_blocking(false, 0); // Timeout=0.
-            pc.printf("Connection from: %s\r\n", client.get_address());
-            while (client.is_connected() == true) {
-                int n = client.receive(buffer, sizeof(buffer));
-                if(n > 0)
-                    client.send_all(buffer, n);
-                if(client.is_fin_received())
-                    client.close();
-            }
-            pc.printf("Disconnected.\r\n");
+
+    pc->attach(&timeoutTest);
+    }
+
+
+void InitEEprom(void)
+{
+  
+  int8_t t;
+  memory.read(32,Config.ipAddr,16);
+  wait_ms(2);
+  memory.read(48,Config.ipSubnet,16);
+  wait_ms(2);
+  memory.read(64,Config.ipGateway,16);
+  wait_ms(2);
+  memory.read(80,Config.MAC_Addr,6);
+  wait_ms(2);
+  memory.read(2,Config.port);
+  wait_ms(2);
+  memory.read(7,Config.bits);
+  wait_ms(2);
+  memory.read(4,t);
+    if( t==1 )
+        Config.parity = SerialBase::Odd;
+    if( t==2 )
+        Config.parity = SerialBase::Even;
+    if(t == 3)
+        Config.parity = SerialBase::None;
+    wait_ms(2);
+  memory.read(8,Config.stop_bits);
+  wait_ms(2);
+  memory.read(5,Config.baud);
+  wait_ms(2);
+  memory.read(10,Config.RS);
+  wait_ms(2);
+ // memory.read(12,Config.frameTimeOut);
+ // wait_ms(2);
+  memory.read(14,Config.timeOut);
+  wait_ms(2);
+  InitDefault();
+    }
+
+    
+
+void TcpRecvThead1(void)
+{
+    static CRC16 crc16;
+    int16_t crc;
+    crc = crc16.calculateCRC16(buffer,tcp_buffer.length);
+    buffer[tcp_buffer.length+1] = crc & 0xff;
+    buffer[tcp_buffer.length] = (crc >> 8) & 0xff;
+
+   for (crc =0 ; crc<tcp_buffer.length+2;crc++)
+        pc->putc(buffer[crc]);
+ 
+   
+    
+    flagThread1 = serialRecvThead1;
+    buffer_num = 6;
+    timeout.start();        //开启1s 超时
+    
+    timeoutT35.start();
+    wait_ms(3);
+    }
+
+void SerialRecvThead1(void)
+{
+    static int j = 0;
+    //char t;
+    static CRC16 crc16;
+    int16_t crc;
+    pcSendRev = 0;//Rev
+    while(flagThread1 == serialRecvThead1) {
+        if( Config.timeOut < timeout.read_ms() ) {
+            pcSendRev = 1;//Send
+            timeout.reset();
+            timeout.stop();
+            timeoutT35.reset();
+            timeoutT35.stop();
+            flagThread1 =  connectedThead1;
+          /*  buffer[7] = buffer[1]|0x80;   //存的功能码 上一步
+            buffer[0] = tcp_buffer.xid[0];
+            buffer[1] = tcp_buffer.xid[1];
+            buffer[2] = tcp_buffer.pid[0];
+            buffer[3] = tcp_buffer.pid[1];
+            buffer[4] = 0x0;
+            buffer[5] = 0x3;
+            buffer[6] = tcp_buffer.serialAddr;
+            buffer[8] = 0x4;
+            client.send_all(buffer,9);//报错
+            */
+        }
+        if( Config.frameTimeOut < timeoutT35.read_ms() && flagT35 ) { // 一帧数据结束 7ms超时
+            timeoutT35.reset();
+            timeoutT35.stop();
+            flagT35 = false;
+            //      t = buffer[buffer_num-1];buffer[buffer_num-1]=buffer[buffer_num-2];buffer[buffer_num-2]=t;
+            crc = crc16.calculateCRC16(buffer+6,buffer_num-6) ;  //为0没有crc错误
+            if (!crc ) {    //无crc 提取mdb帧数据
+                serial_buffer.serialAddr = buffer[6];
+                serial_buffer.funCode = buffer[7];
+                for(j = 0; j < buffer_num-4 ; j++)
+                    serial_buffer.data[j] = buffer[j+8];
+                serial_buffer.crc[0] = buffer[buffer_num-2];
+                serial_buffer.crc[1] = buffer[buffer_num-1];
+                //   buffer_num = 0;//提取完一帧数据 计数清零
+                flagThread1 =  tcpSendThead1;   //进入下一个状态
+            } else          //有crc 错误
+                flagThread1 =  connectedThead1;
         }
     }
 }
+
+void timeoutTest()  //串口中断
+{
+    if(flagThread1 !=serialRecvThead1)
+        buffer[245]=pc->getc();//丢弃串口数据包
+    else {
+        buffer[buffer_num++] = pc->getc();
+        flagT35  = true ;      //标志已经接收到串口数据
+        timeoutT35.reset();  //重新及时只看最后一个接受的字符之后的时间 总线空闲检测
+        timeout.stop();
+    }     //1s接受超时停止计时
+
+}