试验平台:Digi MF开发板

关于网络通信方面,Digi提供了两个程序,一个是TCP Server运行在Digi的开发板上,一个是TCP Client程序,运行在PC上,通过网络,上位机很容易控制Digi开发的IO信号。客户端程序运行后的界面如下:

 

 .Net Micro Framework研究—TCP/IP通信_TCP


(图MF071029004.jpg)

如果仅仅运行一下示例程序,那显然不过瘾!既然串口实现了Modbus Rtu协议,那么网口就实现Modbus Tcp协议吧,实现的Modbus Tcp协议比我们用串口实现Modbus Rtu的指令要多一个,不仅实现了3号命令,也实现了16号命令,这样我们就可以通过Modbus Tcp读写Digi开发板的数据了。这次我们操作的是Digi开发板上的5个LED灯。用OutputPort对象去操作。

操作GPIO的相关代码如下:

  1. //读GPIO信号  
  2.  
  3. DataBuff[0] = 0;  
  4.  
  5. DataBuff[1] = (byte)((output[0].Read() ? 1 : 0) | (output[1].Read() ? 2 : 0) | (output[2].Read() ? 4 : 0) | (output[3].Read() ? 8 : 0) | (output[4].Read() ? 16 : 0));  
  6.  
  7. //写GPIO信号  
  8.  
  9. bool[] bFlag = new bool[5];  
  10.  
  11. bFlag[0]=(DataBuff[1] & 0x01)>0 ? true:false;  
  12.  
  13. bFlag[1]=(DataBuff[1] & 0x02)>0 ? true:false;  
  14.  
  15. bFlag[2]=(DataBuff[1] & 0x04)>0 ? true:false;  
  16.  
  17. bFlag[3]=(DataBuff[1] & 0x08)>0 ? true:false;  
  18.  
  19. bFlag[4]=(DataBuff[1] & 0x10)>0 ? true:false;  
  20.  
  21. for (i = 0; i < 5; i++)  
  22.  
  23. {  
  24.  
  25.    output[i].Write(bFlag[i]);   
  26.  
  27. }  
  28.  
  29.    
  30.  

网络操作相关源码如下:

  1. using System;  
  2.  
  3. using Microsoft.SPOT;  
  4.  
  5. using System.Net;  
  6.  
  7. using System.Net.Sockets;  
  8.  
  9. using System.Text;  
  10.  
  11. using System.Threading;  
  12.  
  13. using Microsoft.SPOT.Hardware;  
  14.  
  15.    
  16.  
  17. namespace MFModbusTcp  
  18.  
  19. {  
  20.  
  21.     public class ModbusTcpSlave  
  22.  
  23.     {  
  24.  
  25.         //MF开发板 IO灯  
  26.  
  27.         private OutputPort[] output=new OutputPort[5];  
  28.  
  29.         Cpu.Pin[] pin = new Cpu.Pin[5] { (Cpu.Pin)0, (Cpu.Pin)1, (Cpu.Pin)2, (Cpu.Pin)5, (Cpu.Pin)6 };  
  30.  
  31.         private Socket socketServer;  
  32.  
  33.         private Socket s = null;  
  34.  
  35.    
  36.  
  37.         //变量缓冲区  
  38.  
  39.         private byte[] m_bytData = new byte[256];  
  40.  
  41.         private byte[] m_InputTCPBuf = new byte[1024];  
  42.  
  43.         private byte[] m_OutputTCPBuf = new byte[1024];  
  44.  
  45.         public byte[] DataBuff = new byte[1024];  
  46.  
  47.           
  48.  
  49.         //启动Modbus Tcp服务  
  50.  
  51.         public void Run()  
  52.  
  53.         {  
  54.  
  55.             //初始化 GPIO  
  56.  
  57.             for (int i = 0; i < 5; i++)  
  58.  
  59.             {  
  60.  
  61.                 output[i] = new OutputPort(pin[i], false);  
  62.  
  63.             }  
  64.  
  65.             socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  
  66.  
  67.             socketServer.Bind(new IPEndPoint(DottedDecimalToIp(0, 0, 0, 0), 502));  
  68.  
  69.             socketServer.Listen(1);  
  70.  
  71.             Debug.Print("Modbus Tcp Slave Started");  
  72.  
  73.             while (true)  
  74.  
  75.             {  
  76.  
  77.                 s = socketServer.Accept();  
  78.  
  79.                 while (s != null)  
  80.  
  81.                 {  
  82.  
  83.                     if ((int)s.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Error) != 0) goto ExitServer;  
  84.  
  85.                     if (s.Available > 0)  
  86.  
  87.                     {  
  88.  
  89.                         TCP_DealwithCommand();  
  90.  
  91.                     }               
  92.  
  93.                     Thread.Sleep(10);  
  94.  
  95.                 }  
  96.  
  97.             }  
  98.  
  99.          ExitServer:  
  100.  
  101.             s.Close();  
  102.  
  103.             s = null;  
  104.  
  105.             Debug.Print("Modbus Tcp Slave Exit");  
  106.  
  107.         }  
  108.  
  109.    
  110.  
  111.         //数据解析  
  112.  
  113.         private void TCP_DealwithCommand()  
  114.  
  115.         {  
  116.  
  117.             int i = 0;  
  118.  
  119.             int lngSendNum = 0;  
  120.  
  121.             int lngDataNum = 0;  
  122.  
  123.             int lngDataAddr = 0;  
  124.  
  125.    
  126.  
  127.             //接收数据  
  128.  
  129.             int intRet=s.Receive(m_InputTCPBuf);  
  130.  
  131.             //Debug.Print("Receive Num:" + intRet.ToString());  
  132.  
  133.             for (i = 0; i < 12; i++) m_OutputTCPBuf[i] = m_InputTCPBuf[i];  
  134.  
  135.             //---------------------------------------------------------------  
  136.  
  137.             //Modbus 读命令  
  138.  
  139.             if (m_InputTCPBuf[7] == 3)  
  140.  
  141.             {  
  142.  
  143.                 … …  
  144.  
  145.             }  
  146.  
  147.             //---------------------------------------------------------------  
  148.  
  149.             //Modbus 写命令  
  150.  
  151.             if (m_InputTCPBuf[7] == 16)  
  152.  
  153.             {  
  154.  
  155.                 … …  
  156.  
  157.             }  
  158.  
  159.         }  
  160.  
  161.         //IP地址转化  
  162.  
  163.         private long DottedDecimalToIp(byte a1, byte a2, byte a3, byte a4)  
  164.  
  165.         {  
  166.  
  167.             return (long)((ulong)a4 << 24 | (ulong)a3 << 16 | (ulong)a2 << 8 | (ulong)a1);  
  168.  
  169.         }  
  170.  
  171.     }  
  172.  
  173. }  
  174.  

程序部署运行后,我们就可以用标准的Modbus Tcp Client程序测试了,我使用的是YFIOServer。

1、  先配置Modbus Tcp驱动程序

 

 .Net Micro Framework研究—TCP/IP通信_通信_02


(图MF071029001.jpg)

2、  再配置IO连接变量

 

 .Net Micro Framework研究—TCP/IP通信_TCP_03


(图MF071029001.jpg)

3、  开始读写GPIO,此时GPIO灯的亮灭,完全被写入的数据控制了。

 

 .Net Micro Framework研究—TCP/IP通信_Framework_04


(图MF071029001.jpg)

 

总论:很难想像,操作TCP的代码比C#的代码还要简洁高效,不到十几分钟,就把一个C#代码改造为MF代码,并且在很短的时间内就调试成功。微软的下一个战略看来马上就成为现实:全世界的每一个智能设备都用MF上网J。