Snap7写入S7-1200 PLC [英] Snap7 writing to a S7-1200 PLC

查看:1183
本文介绍了Snap7写入S7-1200 PLC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用C ++ / CLI应用程式为我的西门子 PLC 写一些东西。



阅读正常(除了第一次读取它给出奇数值)。



但是写作完全不同于我想要的。



下面你可以找到代码: / p>

  private:void WriteSiemensDB()
{
byte *

if(ConnectToSiemensPLC())//检查是否已连接到PLC
{
String ^ msg;
int DBNumber = 2;
bool NDR;

//获取值1次,以便缓冲区有一个值
buffer = sPLC-> ReadDB(DBNumber);

//给变量一个值写入PLC
NDR = true;

sPLC-> SetBitAt(buffer,0,0,NDR); //将bool转换为位

msg = sPLC-> WriteDB(DBNumber,buffer); // write to the Datablock in Siemens

MessageBox :: Show(msg); //显示它是否工作
}
}

sPLC- > SetBitAt方法:

  void SiemensPLC :: SetBitAt(byte buffer [],int Pos,int Bit,bool Value)
{
byte Mask [] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
if(Bit< 0)Bit = 0;
if(Bit> 7)Bit = 7;

if(Value)
{
buffer [Pos] =(byte)(buffer [Pos] | Mask [Bit]);
}
else
{
buffer [Pos] =(byte)(buffer [Pos]&〜Mask [Bit]);
}
}

WriteDB方法:

  System :: String ^ SiemensPLC :: WriteDB(int DBnumber,byte buffer [])
{
int Result;
String ^ msg;
Result = MyClient-> DBWrite(DBnumber,0,80,buffer);

if(Result == 0)
{
msg =Gelukt! // success
}
else
{
msg =Mislukt,error:+ Result; // failed
}
return msg;
}



我真的得到了消息Gelukt,但它仍然写入rwong值。因此填充我的缓冲区出了问题。



在C#中我有同样的应用程序,除了缓冲区是一个字节缓冲区[];



我的问题是:




  • C#中的字节*缓冲区; 和C#中的字节缓冲区[]; 之间的差异b $ b
  • 当我在调试时将鼠标悬停在我的缓冲区上,它表示 buffer * = 0''。这是否意味着它是空的?如果是,为什么它仍然发送随机数字到我的PLC?


解决方案


C#中的字节*缓冲区; 和C ++中的字节缓冲区[];


假设你有 typedef unsigned char byte;



在C ++ / CLI中, byte * buffer; 声明一个 buffer 它是一个指向字节的指针。在C#中,将它写为: byte * buffer; 在 unsafe 上下文中。在C#, byte []缓冲区中; 声明一个语法是一样的



< buffer
变量,它是 byte 值的管理数组。 C ++ / CLI语法为 array< byte> 字节缓冲区[N]; 是C ++语法一个原生数组,这是不是同一件事。一个可以衰减到 byte * 指针。



看起来你的代码使用本机内存缓冲区,没有办法肯定没有 ReadDB 的来源。


鼠标悬停在我的缓冲区上,当我调试,它说 buffer * = 0''。这是否意味着它是空的?如果是,为什么它仍然发送随机数字到我的PLC?


这意味着您的缓冲区的第一个字节 0 。如果你的缓冲区应该包含C字符串数据,这意味着它包含空字符串。



最有可能。但我不能确切说明是什么问题,因为你没有发布 ReadDB 的来源。



是一对夫妇的红旗:




  • 缓冲区大小是多少?你的代码不知道 ReadDB 返回了什么,那么你应该如何确保你不会溢出呢?

  • 谁是缓冲区的所有者,意思是:谁应该释放它?可能是存在于堆上,所以你的代码泄漏了内存。如果它存在 ReadDB 的堆栈,你有一个内存损坏问题。无论哪种方式,此代码都是错误的。


I'm trying to write something to my Siemens PLC with a C++/CLI application.

Reading is ok (except the first time it reads it gives odd values).

But writing is doing something completely different then what I want.

below you can find the code:

    private: void WriteSiemensDB()
    {
        byte* buffer;

        if (ConnectToSiemensPLC()) //Check if you are connected to PLC
        {
        String^ msg;
        int DBNumber = 2;
        bool NDR;

        //Getting the values 1 time so buffer has a value
        buffer = sPLC->ReadDB(DBNumber);

        //give variables a value to write it to the PLC
        NDR = true;

        sPLC->SetBitAt(buffer, 0, 0, NDR); //Convert a bool to a bit

        msg = sPLC->WriteDB(DBNumber, buffer); //write to the Datablock in Siemens

        MessageBox::Show(msg); //Show if it worked or not
    }
}

The sPLC->SetBitAt method:

void SiemensPLC::SetBitAt(byte buffer[], int Pos, int Bit, bool Value)
{
    byte Mask[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
    if (Bit < 0) Bit = 0;
    if (Bit > 7) Bit = 7;

    if (Value)
    {
        buffer[Pos] = (byte)(buffer[Pos] | Mask[Bit]);
    }
    else
    {
        buffer[Pos] = (byte)(buffer[Pos] & ~Mask[Bit]);
    }
}

WriteDB method:

System::String^ SiemensPLC::WriteDB(int DBnumber, byte buffer[])
{
    int Result;
    String^ msg;
    Result = MyClient->DBWrite(DBnumber, 0, 80, buffer);

    if (Result == 0)
    {
        msg = "Gelukt!"; //success
    }
    else
    {
        msg = "Mislukt, error:" + Result; //failed
    }
    return msg;
}

I actually get the message "Gelukt", but it still writes the rwong values. So something goes wrong with filling my buffer. Am I doing something wrong in with the buffer?

In C# I have the same kind of application except the buffer is a byte buffer[];

My questions are:

  • Whats the difference between a byte* buffer;in C++ and a byte buffer[]; in C#?
  • When I mouse over on my buffer when I'm debugging, it says buffer* = 0 ''. Does that mean it's empty? if so, why does it still send random numbers to my PLC?

解决方案

Whats the difference between a byte* buffer;in C++ and a byte buffer[]; in C#?

Assuming you have typedef unsigned char byte;:

In C++/CLI, byte* buffer; declares a buffer variable which is a pointer to a byte. In C# you write it as: byte* buffer; in an unsafe context. The syntax is the same.

In C#, byte[] buffer; declares a buffer variable which is a managed array of byte values. The C++/CLI syntax for this is array<byte> buffer;.

Note that byte buffer[N]; is C++ syntax for a native array, which is not the same thing. That one can decay to a byte* pointer.

Looks like your code uses a native memory buffer, but there's no way to tell that for sure without the source of ReadDB.

When I mouse over on my buffer when I'm debugging, it says buffer* = 0 ''. Does that mean it's empty? if so, why does it still send random numbers to my PLC?

It means the first byte in your buffer is 0. If your buffer is supposed to contain C string data, it means it contains the empty string.

Am I doing something wrong in with the buffer?

Most probably. But I can't say exactly what's wrong, because you didn't post the source of ReadDB.

There are a couple of red flags though:

  • What's the buffer size? Your code doesn't know what ReadDB returns, so how are you supposed to ensure you're not overflowing it?
  • Who's the owner of the buffer, meaning: who's supposed to free it? It presumably lives on the heap, so your code is leaking memory. If it lives on ReadDB's stack you have a memory corruption issue. Either way, this code is wrong.

这篇关于Snap7写入S7-1200 PLC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆