C#通过 MX Component的dll文件读写PLC寄存器的D区和M区的值

C#的串口通过 MX Component的dll文件读写PLC寄存器的D区和M区的值

PLC寄存器的M区,比如M300 寄存器是一个bit位,一般用于PLC信号,表示有无1or0 。

PLC寄存器的D区,比如D100 寄存器是16个bit位,一般用于PLC存数据的。

PLC 的站点 配置和串口,参考 MX Component 软件的配置。

运行工程,需要安装 .net35 ,不宜直接下载.net3.5 这个会很慢。参考 win10安装包文件夹里面的sxs文件夹的安装

注意添加这两个引用,在MX Component 软件里面找,放在工程的bin目录下
在这里插入图片描述

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using AxActUtlTypeLib;
using System.Threading;
using System.IO;

namespace read_plc_region
{
public partial class Form1 : Form
{

    private AxActUtlTypeLib.AxActUtlType axActUtlType = null;


    // PLC 站点号
    public static int PLC_STATUE = 2;

    /*
    以下是 需要采集数据的 PLC寄存器的起始编号
      */


    // 完成一次作业信号
    public string ok_num_regionNum = "M5146";

    // 暂停信号
    public string ng_num_regionNum = "M5047";

   
    public string ng_xin_regionNum = "M6001";  


    
    public string transfer_down_regionNum = "D1261";  


    // 报错的错误说明
    string[] arr_ng_state = new string[] {
        "1报警", "2报警","报警"
    };

    // 报错的PLC寄存器站位
    string[] arr_ng_plc_zhan = new string[] {
        "M444", "M444",
    };

    public Form1()
    {
        InitializeComponent();
        this.axActUtlType = new AxActUtlTypeLib.AxActUtlType();
        this.Controls.Add(this.axActUtlType);     
    }

    //
    private void Form1_Load(object sender, EventArgs e)
    {
        Control.CheckForIllegalCrossThreadCalls = false;

        label1.BeginInvoke(new Action(() => { label1.Text = "PLC站号:"; }));
        label2.BeginInvoke(new Action(() => { label2.Text = "2"; }));
        label3.BeginInvoke(new Action(() => { label3.Text = "连接"; }));
        label4.BeginInvoke(new Action(() => { label4.Text = "断开"; }));
       
        textBox1.BeginInvoke(new Action(() => { textBox1.Text = "0"; }));
        textBox2.BeginInvoke(new Action(() => { textBox2.Text = "0"; }));
        textBox3.BeginInvoke(new Action(() => { textBox3.Text = "0"; }));
        textBox4.BeginInvoke(new Action(() => { textBox4.Text = "0"; }));
        textBox5.BeginInvoke(new Action(() => { textBox5.Text = "0"; }));
        textBox6.BeginInvoke(new Action(() => { textBox6.Text = "0"; }));

       // label2.Text = "2";
        bool rt = true;
        rt = openPLC();

        if (rt)
        {
            label3.ForeColor = Color.Red;
            //连接PLC成功,开始读取
            // 完成一次作业监听
            ThreadPool.QueueUserWorkItem(state => monitor_ok());
            // 暂停 故障信号监听
            ThreadPool.QueueUserWorkItem(state => monitor_bad());
        }




    }

    public bool openPLC()
    {
        try
        {

            this.axActUtlType.ActLogicalStationNumber = PLC_STATUE;
            this.axActUtlType.ActPassword = "1";  // 密码,字符串随便
            int rtn = this.axActUtlType.Open();
            if (rtn == 0)
            {
                label3.ForeColor = Color.Red;
                MTWFile.WriteLine("PLC的2站位连接成功!");
            }
            else
            {
                label3.ForeColor = Color.Black;
                MTWFile.WriteLine("PLC的2站位连接失败!");
                return false;
            }
        }
        catch (Exception ex)
        {
            MTWFile.WriteLine("PLC的2站位连接报错:" + ex.Message);
        }
        return true;
    }

    /// <summary>
    /// 完成一次动作监听
    /// </summary>
    public void monitor_ok()
    {
        while (true)
        {
            // 这个 300毫秒 一次读
            Thread.Sleep(300);

            int ok_num = 2;
            int ok_num2 = 2;
            int read_create = 2;
            // 检测  完成一次作业信号
            ok_num = read_PLC_M(ok_num_regionNum);
            Thread.Sleep(20);
            // 再检测一次 ,20毫秒以后,避免意外信号
            ok_num2 = read_PLC_M(ok_num_regionNum);
            if ((1 == ok_num) && (1 == ok_num2))
            {
                // 读PLC的数据
                read_create = read_plc_write_upfile();
                if(1 == read_create)
                {
                    // 读取PLC寄存器成功,写入上传数据成功,将 完成一次信号寄存器置0
                    write_W_PLC(ok_num_regionNum, 0);
                }
                else
                {
                    // 
                    // 待考虑
                    MTWFile.WriteLine("读取PLC寄存器失败,写入上传数据失败");
                }
            }

        }//while
    }

    /// <summary>
    ///  暂停,故障动作监听
    /// </summary>
    public void monitor_bad()
    {
        int flag = 0;
       
        while (true)
        {
            // 这个 300毫秒 一次读
            Thread.Sleep(300);

            int ng_num = 2;
            int ng_num2 = 2;
            List<string> ng_code = new List<string>();

            // 检测  暂停信号
            ng_num = read_PLC_M(ng_num_regionNum);
            Thread.Sleep(20);
            ng_num2 = read_PLC_M(ng_num_regionNum);
            if ((flag == 0) &&(1 == ng_num2) && (1 == ng_num2))
            {
                // 遍历 PLC 的 故障位寄存器
               int aa =  arr_ng_plc_zhan.Length;
                for (int i = 0; i < aa; i++)
                {
                    int index = 2;
                    index = read_PLC_M(arr_ng_plc_zhan[i]);
                    if(1 == index)
                    {
                        // 把报警信息加入集合
                        ng_code.Add(arr_ng_state[i]);
                    }
                }
                flag = 1;
            }
            else if((flag == 1) && (0 == ng_num2) && (0 == ng_num2))
            {
                flag = 0;
            }

            // 如果有报错信息
            if(0 != ng_code.Count)
            {
                create_ng_up_file(ng_code);
            }
           
        }
    }

    // PLC 读M区 寄存器的数据,一个bit位一个寄存器
    private int read_PLC_M(string num)
    {

        int asd = 3;
        short[] dates = new short[1];

        try
        {
            int rtn = this.axActUtlType.ReadDeviceRandom2(num, 1,out dates[0]);
            if (rtn == 0)
            {
                // 这个是PLC里一个数用一个寄存器表示
                asd = dates[0];
                MTWFile.WriteLine("读PLC的M区寄存器数据" + num + "成功=" + asd);
            }
            else
            {
                MTWFile.WriteLine("读PLC的M区数据失败");
            }

        }

        //Exception processing
        catch (Exception ex)
        {
            MTWFile.WriteLine("写入PLC数据失败原因:" + ex.ToString());
            return 3;
        }
        return asd;
    }

	// 往一个bit位的寄存器写值  0 or 1
    private void write_W_PLC(string plc_num,int das)
    {    
        short[] dates = new short[1];
        dates[0] = (short)das;

        try
        {
            int ret  = this.axActUtlType.WriteDeviceRandom2(plc_num,1,ref dates[0]);
            if( 0 == ret )
            {
                MTWFile.WriteLine("写PLC的M区寄存器数据" + plc_num + "成功=" + das);
            }
            else
            {
                MTWFile.WriteLine("写PLC的M区寄存器数据" + plc_num + "失败");
               
            }
        }		
        catch (Exception ex)
        {
            MTWFile.WriteLine("写PLC的M区寄存器数据" + plc_num + "失败:"+ex.ToString());
          
        }
      
    }


    // 写入PLC 数据,可以写一个16位bit能表示的数字
    private void Write_plc(string plc_num,int statss)
    {
        try
        {

            short[] arr = new short[256];
           
            // 以 INT 的类型写入
            arr[0] = (short)Convert.ToInt32(statss);

            int rtn = this.axActUtlType.WriteDeviceBlock2(plc_num, arr.Length, ref arr[0]);
            if (rtn == 0)
            {
                MTWFile.WriteLine("写入PLC数据成功"); 
             }
            else
            {
                MTWFile.WriteLine("写入PLC数据失败");
            }
        }
        catch (Exception ex)
        {
            MTWFile.WriteLine("写入PLC数据失败原因:"+ex.ToString());
        }
    }



    // 接收到OK 信号后,读取PLC的数据,并写入文件
    // 函数返回1 表示成功,返回0 表示失败
    public int read_plc_write_upfile()
    {
        try
        {

            //读取  ,PLC寄存器 D140,D141,D142,D143
            string pcb_model = "";
           
            
            string flavour_down = "";


           
            string pathway_parameter = "";

            // pcb 
            pcb_model = getPCB_xinghao();

            // 移载位 D104
            transfer_up = readPLC_twoRegion(transfer_up_regionNum);
            

            // 可能会没有  pcb_model
            if ( "".Equals(transfer_up) || "".Equals(transfer_down) || "".Equals(flavour_up) || "".Equals(flavour_down) || "".Equals(pathway_parameter))
            {
                // 读取失败
                MTWFile.WriteLine("读取PLC寄存器失败,请检查PLC寄存器数据是否完整");
                MTWFile.WriteLine("read PLC date NG =pcb_model:"+
                    pcb_model+ "transfer_up:"+ transfer_up+ "transfer_down:"+ 
                    transfer_down+ "flavour_up:" + flavour_up+ "flavour_down:"+ 
                    flavour_down + "pathway_parameter:" + pathway_parameter);
            }
            else
            {
                // 读取成功
                MTWFile.WriteLine("读取PLC寄存器成功");
                MTWFile.WriteLine("read PLC date OK ==pcb_model:" +
                pcb_model + "transfer_up:" + transfer_up + "transfer_down:" +
                transfer_down + "flavour_up:" + flavour_up + "flavour_down:" +
                flavour_down + "pathway_parameter:" + pathway_parameter);

            }

			// 拼接自定义封装参数类
            LogFileUp file_num = new LogFileUp();
            file_num.Pcb_model = pcb_model;
       

           
            create_up_file(file_num);
            return 1;
        }
        catch(Exception ex)
        {
            MTWFile.WriteLine("read_plc_write_upfile FILE,cause:" + ex.ToString());
            return 0;
        }
        
    }


    // 一个数用一个寄存器表示
    private int  read_plc_one(string ok_num)
    {
        int result = 2;
        short asd = 2;
        try
        {
            int num = 1;
            //  定义接收缓冲区;
            short[] arr = new short[num];

            // 这个是从寄存器 strAddr 开始读,读 num 个寄存器
            int rtn = this.axActUtlType.ReadDeviceBlock2(ok_num, num, out arr[0]);


            if (rtn != 0)
            {
                MTWFile.WriteLine("完成信号读取PLC一个寄存器失败,寄存器起始:" + ok_num);
                return result;
            }

            // 这个是PLC里一个数用一个寄存器表示
            asd = arr[0];
            MTWFile.WriteLine("完成信号读取PLC寄存器" + ok_num + "成功=" + asd);
        }
        catch (Exception ex)
        {
            MTWFile.WriteLine("读取PLC一个寄存器失败,寄存器起始:" + ok_num+"原因:"+ex.ToString());
        }

        result = asd;
        return result;
    }



    // 一个数用两个寄存器表示 ,正负数都可以
    // 只能以 INT 格式接收数据
    private string readPLC_twoRegion(string regionNum)
    {
        // 移载轴上料位
        long result_date = 0;
        try
        {
            int stu_num = 0;
            int bb_tmp = 0;
            int num = 2;
            //  定义接收缓冲区;
            short[] arr = new short[num];

            // 这个是从寄存器 strAddr 开始读,读 num 个寄存器
            int rtn = this.axActUtlType.ReadDeviceBlock2(regionNum, num, out arr[0]);

            if (rtn != 0)
            {
                MTWFile.WriteLine("读取PLC两个寄存器失败,寄存器起始:" + regionNum);
                return "";
            }
           
            for (int i = 0; i < num; i++)
            {
                if (stu_num == 0)
                {
                    string ND = arr[i].ToString() + "";

                    // int bb = Convert.ToInt32(ND);
                    int cc = Convert.ToInt16(ND);

                    // 这里得到的是十进制数字,在PLC中一个寄存器是16位
                    bb_tmp = cc;
                    stu_num++;
                }
                else
                {
                    string ND = arr[i].ToString() + "";

                    int bb = Convert.ToInt16(ND);

                    // 最终的结果
                    result_date = bb_tmp + (bb << 16);
                    stu_num = 0;
                    bb_tmp = 0;
                }
            }
            MTWFile.WriteLine("读取PLC寄存器"+ regionNum + "成功=" + result_date);
        }
        catch (Exception ex)
        {
            // ShowMsg(ex.Message);
            MTWFile.WriteLine("读取PLC寄存器" + regionNum + "失败:" + ex.ToString());
        }

        return result_date+"";
    }


	// 一个PLC寄存器16位,可以表示两个字母
    public string getPCB_xinghao()
    {
        string rty = "";
        try
        {
            short[] arr = new short[4];
            int rtn = this.axActUtlType.ReadDeviceBlock2(pcb_model_regionNum, 4, out arr[0]);
            if (rtn != 0)
            {
                MTWFile.WriteLine("读取PLC寄存器_PCB型号失败rtn =" + rtn);
                return "";
            }
            
            for (int i = 0; i < 4; i++)
            {
                // 这里得到的是十进制数字,在PLC中一个寄存器是16位
                string ND = arr[i].ToString() + "";
                // 将一个int类型的数字转换成 两个字母
                string res = intToTwoString(ND);
                rty = rty + res;
            }
        }catch(Exception ex)
        {
            rty = "";
            MTWFile.WriteLine("读取PLC寄存器_PCB型号失败=="+ ex.ToString());
        }

        return rty;
    }



    /// <summary>
    /// 将 数字字符串 "16706" 先转数字 16706,再以二进制的形式拆分成前后 8位,
    /// 再转ASCII码变成“AB”,再变成 "BA 返回
    /// </summary>
    /// <param name="ND"></param>
    /// <returns></returns>
    public string intToTwoString(string ND)
    {

        string res = "";

        try
        {
            //    string ND = "16706";
            int tmp_16nd = Convert.ToInt16(ND);
            //十进制转二进制
            string bin16_tmp = Convert.ToString(tmp_16nd, 2);

            // 取前8位
            short firstHalf16 = (short)(tmp_16nd >> 8);
            // 取后8位
            short secondHalf16 = (short)(tmp_16nd & 0xff);

            short[] arr = { firstHalf16, secondHalf16 };

            byte[] RxdBuf1 = BitConverter.GetBytes(arr[0]);
            string res_1 = System.Text.Encoding.ASCII.GetString(RxdBuf1);

            byte[] RxdBuf2 = BitConverter.GetBytes(arr[1]);
            string res_2 = System.Text.Encoding.ASCII.GetString(RxdBuf2);

            string res_num = (res_2 + res_1).Replace("\0", "");
            res = res_num;

        }catch(Exception ex)
        {
            MTWFile.WriteLine("读取PLC寄存器_PCB型号,转换编码失败==" + ex.ToString());
        }

        // 前后位置要反过来
        return res;
    }

    public void create_up_file(LogFileUp file_num)
    {
        //string str_data = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"); // 2008-9-4 20:02:10

        // 创建文件
        // 文件夹路径
        string dis_name = "D:\\vision test data\\test data txt";
        // 文件名, 格式 时分秒+扫码数据
        // 时分秒
        string shi = DateTime.Now.Hour.ToString(); //获取小时 // 20
        string fen = DateTime.Now.Minute.ToString(); //获取分钟 // 31
        string miao = DateTime.Now.Second.ToString(); //获取秒数 // 45
        string day = DateTime.Now.Day.ToString();
        //   string week = DateTime.Now.DayOfWeek.ToString();
        //  string year = DateTime.Now.DayOfYear.ToString();
        string month = DateTime.Now.Month.ToString();
        string year = DateTime.Now.Year.ToString();
        string millsecend = DateTime.Now.Millisecond.ToString();
        string time_str = year + "-" + month + "-" + day + "-" + shi + "-" + fen + "-" + miao + "-" + millsecend;

        // 拼接文件名 可使用 StringBuilder的append方法
        string file_name = time_str + "-" + "OK" + ".txt";

        string pcb_model = file_num.Pcb_model;


        // 打开文件夹
        DirectoryInfo dinfo = new DirectoryInfo(dis_name);
        if (dinfo.Exists)
        {
            // 被创建文件全路径名
            string path = dis_name + @"\\" + file_name;
            if (!File.Exists(path))
            {
                FileStream fs1 = new FileStream(path, FileMode.Create, FileAccess.Write);
                // 往文件写入内容
                StreamWriter sw = new StreamWriter(fs1);
                // sw.WriteLine("写入内容");
                sw.WriteLine("Data:" + time_str);
                sw.WriteLine("pcb_model:" + pcb_model);

                sw.Flush();
                sw.Close();
            }
            else
            {
                // 文件已存在就报错
                //  MessageBox.Show("The file is here");
            }
        }
        else
        {
            // 文件夹不存在报错
           // dinfo.Create();
           MessageBox.Show("The Directory is not Exists");
        }

    }



    public void create_ng_up_file(List<string> file_num)
    {
        
        //string str_data = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"); // 2008-9-4 20:02:10

        // 创建文件
        // 文件夹路径
        string dis_name = "D:\\vision test data\\test data txt";
        // 文件名, 格式 时分秒+扫码数据
        // 时分秒
        string shi = DateTime.Now.Hour.ToString(); //获取小时 // 20
        string fen = DateTime.Now.Minute.ToString(); //获取分钟 // 31
        string miao = DateTime.Now.Second.ToString(); //获取秒数 // 45
        string day = DateTime.Now.Day.ToString();
        //   string week = DateTime.Now.DayOfWeek.ToString();
        //  string year = DateTime.Now.DayOfYear.ToString();
        string month = DateTime.Now.Month.ToString();
        string year = DateTime.Now.Year.ToString();
        string millsecend = DateTime.Now.Millisecond.ToString();
        string time_str = year + "-" + month + "-" + day + "-" + shi + "-" + fen + "-" + miao + "-" + millsecend;

        // 拼接文件名 可使用 StringBuilder的append方法
        string file_name = time_str + "-" + "NG" + ".txt";

        StringBuilder ng_code = new StringBuilder();
        foreach (var item in file_num)
        {
            ng_code.Append(","+ item);
        }

        // 打开文件夹
        DirectoryInfo dinfo = new DirectoryInfo(dis_name);
        if (dinfo.Exists)
        {
            // 被创建文件全路径名
            string path = dis_name + @"\\" + file_name;
            if (!File.Exists(path))
            {
                FileStream fs1 = new FileStream(path, FileMode.Create, FileAccess.Write);
                // 往文件写入内容
                StreamWriter sw = new StreamWriter(fs1);
                // sw.WriteLine("写入内容");
                sw.WriteLine("Data:" + time_str);
                sw.WriteLine("错误信息:" + ng_code);
               
                sw.Flush();
                sw.Close();
            }
            else
            {
                // 文件已存在就报错
                //  MessageBox.Show("The file is here");
            }
        }
        else
        {
            // 文件夹不存在报错
            // dinfo.Create();
            MessageBox.Show("The Directory is not Exists");
        }

    }




}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值