从C#发送FINS命令到PLC

时间:2012-03-14 03:46:35

标签: c# udp plc fins

我尝试通过UDP从PC(C#.NET)向PLC以太网模块(Omron)发送 FINS 命令,但是没有得到PLC的任何响应,也没有任何线索我可以从哪里开始故障排除。

PLC有一个非常简单的梯形逻辑如下: 如果DM100的值为#0001,则会在输出101.00上触发。 (这里,“触发器”只是存储区域D100的符号名称,“输出”是输出101.00的符号) enter image description here

然后我写了一段C#执行FINS命令“Memory Area Write”,命令代码为01 02,后面跟着起始地址,要写入的项目数和数据。 C#代码应将#0001的值写入PLC的D100区域,以便在101.00上触发ON。

[已删除的代码无效] ..

输出101.00没有被触发,也没有收到任何异常。 我确定了以下内容:

  1. 正确配置的端口,节点和地址,由CX-Programmer中的“在线工作”确认。我还ping每个IP以确保节点已连接。
  2. UdpClient代码有效,因为我编写了一个非常简单的服务器/客户端代码,可以成功发送和接收数据包。
  3. 梯形逻辑没有问题。我将梯子转移到PLC并在监控模式下通过Work Online进行测试并手动设置D100值。
  4. 我怀疑fins_cmnd数组中存在错误,但正如我的代码中所见,我已尽可能详细地评论每个值;我不可能发现自己错过任何东西。我怀疑我可能没有正确解析十六进制,但同样,我也没有例外来指导我。

    我不知道在哪里以及如何排除故障。希望有FINS编程或PLC经验的人可以给我一些帮助。

    [答案]
    感谢 Porge 获取链接 - 这让我发现了问题所在。经过几条路径终于让它发挥作用。请参阅下面的工作代码。

    string SERV_IP_ADDR = "192.168.250.1";
    const int FINS_UDP_PORT = 9600;
    
    byte[] sendPacket = new byte[]
    {
        // Full UDP packet: 80 00 02 00 00 00 00 05 00 19 01 02 82 00 64 00 00 01 00 01
    
        // Header
        0x80, //0.(ICF) Display frame information: 1000 0001
        0x00, //1.(RSV) Reserved by system: (hex)00
        0x02, //2.(GCT) Permissible number of gateways: (hex)02
        0x00, //3.(DNA) Destination network address: (hex)00, local network
        0x00, //4.(DA1) Destination node address: (hex)00, local PLC unit
        0x00, //5.(DA2) Destination unit address: (hex)00, PLC
        0x00, //6.(SNA) Source network address: (hex)00, local network
        0x05, //7.(SA1) Source node address: (hex)05, PC's IP is 192.168.250.5
        0x00, //8.(SA2) Source unit address: (hex)00, PC only has one ethernet
        0x19, //9.(SID) Service ID: just give a random number 19
    
        // Command
        0x01, //10.(MRC) Main request code: 01, memory area write
        0x02, //11.(SRC) Sub-request code: 02, memory area write
    
        // PLC Memory Area
        0x82, //12.Memory area code (1 byte): 82(DM)
    
        // Address information
        0x00, //13.Write start address (2 bytes): D100
        0x64, 
        0x00, //15.Bit address (1 byte): Default 0
        0x00, //16.No. of items (2 bytes): only one address which is D100
        0x01,
    
        // Write Data
        0x00, //18.Data to write (2 bytes): value is 1
        0x01,
    };  
    
    UdpClient client = new UdpClient(); //create a UdpClient instance
    
    try
    {
        client.Send(sendPacket, sendPacket.Length, SERV_IP_ADDR, FINS_UDP_PORT);
    }
    catch (SocketException se)
    {
        Console.WriteLine(se.ErrorCode + ": " + se.Message);
    }
    
    client.Close();
    

1 个答案:

答案 0 :(得分:6)

这些字符串都不会被解析为十六进制。 NumberStyles.AllowHexSpecifier 允许十六进制前缀“0x”,但不会将该数字解析为十六进制,除非它存在。

所以你想要(char)Int16.Parse("0x64", NumberStyles.AllowHexSpecifier)

但是,C#中的数字文字可以是十六进制的,所以您可以只编写0x64而不是完成所有操作。

我刚刚查看了this page as a reference的协议,最好直接创建消息作为字节,而不是指定Unicode代码点并将这些代码点解码为ASCII字节。您还可以使用数组规范语法来消除大量混乱:

var message = new byte[]
{
    // header
    0x80, //(ICF) Display frame information: 1000 0001
    0x00, //(RSV) Reserved by system: (hex)00
    0x02, //(GCT) Permissible number of gateways: (hex)02
    0x00, //(DNA) Destination network address: (hex)00, local network
    0x00, //(DA1) Destination node address: (hex)00, local PLC unit
    0x00, //(DA2) Destination unit address: (hex)00, PLC
    0x00, //(SNA) Source network address: (hex)00, local network
    0x05, //(SA1) Source node address: (hex)05, PC's IP is 192.168.250.5
    0x00, //(SA2) Source unit address: (hex)00, PC only has one ethernet
    0x19, //(SID) Service ID: just give a random number 19

    // command
    0x01, //(MRC) Main request code: 01, memory area write
    0x02, //(SRC) Sub-request code: 02, memory area write

    // data
    0x82, //Memory area code, 2 bytes: 82(DM)
    0x00, //Write start address DM100
    0x64,
    0x00,
    0x00, //Word write: only one address
    0x01,
    0x00, //Write value of 1 to address DM100 (0000 0000 0000 0001)
    0x01, // - this value is 0xaabbccdd -> cc dd aa bb
    0x00, 
    0x00, 
};

您的数据部分看起来也有些问题 - 根据链接文档,内存地址应为4个字节,写入长度为2个字节,每个值为4个字节。这些与你所拥有的不匹配,所以我扩展了那一部分。