测试环境:
1、CODESYS 3.5.13.0(新建Codesys_ShareMemory项目)
2、SharedMemoryCommunication.package(Codesysy共享内存库)
链接:https://pan.baidu.com/s/1JM0RXUR8h1L5UE2pVhY4BQ
提取码:ql7w
3、Visual Studio2015(新建C#_ShareMemory项目)
一、共享内存概念
1、顾名思义,共享内存就是建立一块供协作进程共享的内存区域,多个进程可以透过此共享区域读取或者写入数据来交换信息;
2、通信示意图:
二、CoDeSys程序
1、添加库文件
· SysShm,3.5.8.0 (System)
· SysTypes2 Interfaces,3.5.4.0 (System)
1)打开库管理器(Library Manager),选择“添加库(Add Library)”,点“高级(Advanced...)”;
2)在搜索框(String for a fulltext search...)中分别输入SysShm和SysTypes搜索添加SysShm,3.5.8.0 和SysTypes2 Interfaces,3.5.4.0 ,
选中搜索到的库,点“OK”确认添加,
添加完成即可在库管理器(Library Manager)中查看到。
库文件介绍:
共享内存进行数据共享交互需要通过数据结构来进行。
选中应用(Application)右键添加对象(Add Object),选择“DUT”,
创建数据结构,输入数据结构名称,选择类型(Type),点“Add”
本例分别创建两个数据结构,Str_ParaFromHMI和Str_ParaToHMI
3、创建ShareMemory
新建ST(结构文本)程序,创建共享内存。
程序页面概览:
1)声明变量、共享内存名和功能函数等
PROGRAM ShareMemory
VAR
bStart: BOOL:= FALSE;
ReadHandle: RTS_IEC_HANDLE:= RTS_INVALID_HANDLE;
WriteHandle: RTS_IEC_HANDLE:= RTS_INVALID_HANDLE;
szNameRead: STRING:= 'CODESYS_MEMORY_READ'; //声明共享内存的读取内存名称
szNameWrite: STRING:= 'CODESYS_MEMORY_WRITE'; //声明共享内存的写入内存名称
ulPhysicalAddressRead: __UXINT:= 0;
ulPhysicalAddressWrite: __UXINT:= 0;
ulSizeRead: __UXINT:= 1024;
ulSizeWrite: __UXINT:= 1024;
ResultRead: ARRAY[0..2] OF RTS_IEC_RESULT; //返回运行错误码
ResultWrite: ARRAY[0..2] OF RTS_IEC_RESULT;
SMRead: __UXINT;
SMWrite: __UXINT;
ulOffsetRead: __UXINT:= 0;
ulOffsetWrite: __UXINT:= 0;
END_VAR
2)程序具体实现
//Init Memory
IF NOT bStart THEN
ReadHandle:= SysSharedMemoryCreate(pszName:= szNameRead, ulPhysicalAddress:= ulPhysicalAddressRead, pulSize:= ADR(ulSizeRead), pResult:= ADR(ResultRead[0]));
WriteHandle:= SysSharedMemoryCreate(pszName:= szNameWrite, ulPhysicalAddress:= ulPhysicalAddressWrite, pulSize:= ADR(ulSizeWrite), pResult:= ADR(ResultWrite[0]));
IF RTS_INVALID_HANDLE <> ReadHandle AND RTS_INVALID_HANDLE <> WriteHandle THEN
bStart:= TRUE;
END_IF
END_IF
//读取数据
IF RTS_INVALID_HANDLE <> ReadHandle THEN
SMRead:= SysSharedMemoryRead(
hShm:= ReadHandle, //读取内存的设备句柄
ulOffset:= ulOffsetRead, //读取数据的偏移地址
pbyData:= ADR(GVL.GetPara), //指向读取数据的缓冲区
ulSize:= SIZEOF(Str_ParaFromHMI), //读取数据的字节大小
pResult:= ADR(ResultRead[1])); //返回执行的错误码
END_IF
//写入数据
IF RTS_INVALID_HANDLE <> WriteHandle THEN
SMWrite:= SysSharedMemoryWrite(
hShm:= WriteHandle, //写入内存的设备句柄
ulOffset:= ulOffsetWrite, //写入数据的偏移地址
pbyData:= ADR(GVL.SetPara), //指向写入数据的缓冲区
ulSize:= SIZEOF(Str_ParaToHMI), //写入数据的字节大小
pResult:= ADR(ResultWrite[2])); //返回执行的错误码
END_IF
三、C#程序
1、引用命名空间
using System.IO.MemoryMappedFiles; //引用共享内存命名空间
using System.Threading;
using System.Runtime.InteropServices;
2、定义数据结构
数据结构中的变量名不一定非要与Codesys的数据结构变量名保持相同(建议定义一致,便于查看和管理),但数据结构内的数据类型和数据总数必须保持一致。
struct StrFromCodesys
{
internal bool bOut;
internal int iOut;
internal double fOut;
}
struct StrToCodesys
{
internal bool bIn;
internal int iIn;
internal double fIn;
}
3、创建ShareMemory
1)声明定义共享内存使用的API
2)共享内存初始化,注意检查MappedFile的内存名与Codesys内存名一致,这样才能确保访问同一块内存地址
private void InitMemory()
{
try
{
MMF_Write = MemoryMappedFile.CreateOrOpen("CODESYS_MEMORY_READ", 1024); //打开Codesys_Read内存区域,意思就是说Codesys的读取区域是C#的写入区域
AccessorWrite = MMF_Write.CreateViewAccessor(0, Marshal.SizeOf(typeof(StrToCodesys)), MemoryMappedFileAccess.Write);
MMF_Read = MemoryMappedFile.CreateOrOpen("CODESYS_MEMORY_WRITE", 1024); //打开Codesys_Write内存区域,意思就是说Codesys的写入区域是C#的读取区域
AccessorRead = MMF_Read.CreateViewAccessor(0, Marshal.SizeOf(typeof(StrFromCodesys)), MemoryMappedFileAccess.Read);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
3)读取数据
private void ReadData()
{
while(true)
{
try
{
Thread.Sleep(5);
AccessorRead.Read(0, out ParaFromCodesys); //读取Codesys的数据
Thread.Sleep(5);
if(ParaFromCodesys.bOut == true)
picbox_bRead.BackColor = Color.Red;
else
picbox_bRead.BackColor = Color.Gray;
textbox_iRead.Text = ParaFromCodesys.iOut.ToString("0");
textbox_fRead.Text = ParaFromCodesys.fOut.ToString("0.000");
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
4)写入数据
private void btnWriteB(object sender, EventArgs e)
{
ParaToCodesys.bIn = !ParaToCodesys.bIn;
AccessorWrite.Write(0, ref ParaToCodesys);
if(ParaToCodesys.bIn == true)
{
picbox_bWrite.BackColor = Color.Red;
}
else
{
picbox_bWrite.BackColor = Color.Gray;
}
}
四、通信测试
运行CoDeSys和C#程序,通过读取和写入数据测试通信结果
1)通信测试图片
2)通信测试动图
源码地址: https://download.csdn.net/download/m0_37846617/12440773