共享内存 - C#与CoDeSys通讯

测试环境:

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、通信示意图:

共享内存 - C#与CoDeSys通讯_第1张图片

二、CoDeSys程序
1、添加库文件

· SysShm,3.5.8.0 (System)

· SysTypes2 Interfaces,3.5.4.0 (System)

1)打开库管理器(Library Manager),选择“添加库(Add Library)”,点“高级(Advanced...)”;

共享内存 - C#与CoDeSys通讯_第2张图片

2)在搜索框(String for a fulltext search...)中分别输入SysShm和SysTypes搜索添加SysShm,3.5.8.0 SysTypes2 Interfaces,3.5.4.0 ,

选中搜索到的库,点“OK”确认添加,

共享内存 - C#与CoDeSys通讯_第3张图片

共享内存 - C#与CoDeSys通讯_第4张图片

添加完成即可在库管理器(Library Manager)中查看到。

共享内存 - C#与CoDeSys通讯_第5张图片

库文件介绍:

共享内存 - C#与CoDeSys通讯_第6张图片
2、创建数据结构

共享内存进行数据共享交互需要通过数据结构来进行。

选中应用(Application)右键添加对象(Add Object),选择“DUT”,

共享内存 - C#与CoDeSys通讯_第7张图片

创建数据结构,输入数据结构名称,选择类型(Type),点“Add”

共享内存 - C#与CoDeSys通讯_第8张图片

本例分别创建两个数据结构,Str_ParaFromHMIStr_ParaToHMI

共享内存 - C#与CoDeSys通讯_第9张图片

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)通信测试图片

共享内存 - C#与CoDeSys通讯_第10张图片

2)通信测试动图

共享内存 - C#与CoDeSys通讯_第11张图片

源码地址: https://download.csdn.net/download/m0_37846617/12440773

你可能感兴趣的:(共享内存 - C#与CoDeSys通讯)