Snap7写入S7-1200 PLC [英] Snap7 writing to a 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屋!