倍福PLC和C#上位机读写数据

        此测试工具用到了胡工科技的HslCommunication测试软件,GItHub:GitHub - dathlin/HslCommunication: A very popular industrial Internet of Things communication plug-in. Using this dll can be very convenient, stable, and fast to obtain data from PLC equipment of multiple brands, and also supports redis, mqtt, websocket, etc., which can let your data on the network Free transmission, reducing enterprise development costs.

此贴源代码已上传Gitee:(倍福、欧姆龙PLC测试工具)上位机和PLC通讯工具: 上位机和倍福PLC读写数据的测试工具 (gitee.com)       

 

HslCommunication里有倍福PLC的虚拟服务器用于模拟与倍福PLC的通讯,如图:

    以下是我查询官方文档查阅网络资料编写两种的读写数据的代码(第一种直接读写,第二种用到了特性),希望各大网友指点指点:

        From1.cs

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 HslCommunication.Profinet.Beckhoff;
using HslCommunication;
using TwinCAT.Ads;

namespace 倍福PLC
{
    public partial class Form1 : Form
    {
        private static BeckhoffAdsNet beckhoffAdsNet = new BeckhoffAdsNet();
        private static OperateResult write;
        private static plcAddress data;
        private static OperateResult<plcAddress> readBool;
        private static OperateResult<plcAddress> readFloat;
        private static OperateResult<plcAddress> readDouble;
        private static OperateResult<plcAddress> readByte;
        public Form1()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 连接倍福PLC
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnConnect_Click(object sender, EventArgs e)
        {
            try
            {
                //设置IP和Port
                string Ip = ipTxt.Text;
                int port = Convert.ToInt32(portTxt.Text);
                beckhoffAdsNet = new BeckhoffAdsNet(Ip, port);
                beckhoffAdsNet.SetTargetAMSNetId("192.168.182.131.1.1:801");
                beckhoffAdsNet.SetSenderAMSNetId("192.168.235.128.1.1");

                targetTxt.Text = "192.168.182.131.1.1:801";
                senderTxt.Text = "192.168.235.128.1.1";


                OperateResult connect = beckhoffAdsNet.ConnectServer();
                if (connect.IsSuccess)//连接成功
                {
                    MessageBox.Show("连接成功", "提示信息");

                    //(写死了,在plcAddress里配置的特性 [HslDeviceAddress("M100")] )
                    addressTxt1.Text = "M100";
                    addressTxt2.Text = "M100";

                    //打开按钮
                    readBoolBtn.Enabled = true;
                    readFloatBtn.Enabled = true;
                    readDoubleBtn.Enabled = true;
                    readByteBtn.Enabled = true;
                    writeBoolBtn.Enabled = true;
                    writeFloatBtn.Enabled = true;
                    writeDoubleBtn.Enabled = true;
                    writeByteBtn.Enabled = true;
                }
                else    //连接失败
                {
                    MessageBox.Show($"连接失败", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"连接失败,错误信息:{ex}", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }
        /// <summary>
        /// 窗口加载事件,打开窗体时会执行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            //设置窗体名称
            this.Text = "倍福PLC测试工具";

            //设置为只读
            targetTxt.ReadOnly = true;
            senderTxt.ReadOnly = true;

            //默认为本地地址 不用改,直接可以用
            ipTxt.Text = "127.0.0.1";
            portTxt.Text = "48898";

            //连接PLC之前应该关闭的按钮
            readBoolBtn.Enabled = false;
            readFloatBtn.Enabled = false;
            readDoubleBtn.Enabled = false;
            readByteBtn.Enabled = false;
            writeBoolBtn.Enabled = false;
            writeFloatBtn.Enabled = false;
            writeDoubleBtn.Enabled = false;
            writeByteBtn.Enabled = false;

            //加入addressList
            addressTxt1.Items.Add("M100");
            addressTxt2.Items.Add("M100");
            addressTxt1.Items.Add("s=MAIN.bool1");
            addressTxt2.Items.Add("s=MAIN.bool1");
            addressTxt1.Items.Add("s=MAIN.dd");
            addressTxt2.Items.Add("s=MAIN.dd");
            addressTxt1.Items.Add("s=MAIN.double");
            addressTxt2.Items.Add("s=MAIN.double");
            addressTxt1.Items.Add("s=MAIN.byte");
            addressTxt2.Items.Add("s=MAIN.byte");

            //开启缓冲功能(据说可以实现缓存功能,加速标签的读写速度)
            beckhoffAdsNet.UseTagCache = true;

        }
        /// <summary>
        /// 读取Bool值
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void readBoolBtn_Click(object sender, EventArgs e)
        {
            #region 方法1
            OperateResult<bool> read = beckhoffAdsNet.ReadBool(addressTxt1.Text.Trim());
            if (read.IsSuccess)
            {
                resultTxt.Text += read.Content + "\r\n";
                resultTxt.SelectionStart = resultTxt.Text.Length; //在文本框中的选定文本的起始位置
                resultTxt.ScrollToCaret(); //将控件内容滚动到当前插入符号位置
            }
            else
            {
                MessageBox.Show($"读取失败,错误原因:{read.Message}", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
            } 
            #endregion

            #region 方法2
            //readBool = beckhoffAdsNet.Read<plcAddress>();
            //if (readBool.IsSuccess)
            //{
            //    resultTxt.Text += readBool.Content.Bool + "\r\n";
            //    resultTxt.SelectionStart = resultTxt.Text.Length; //在文本框中的选定文本的起始位置
            //    resultTxt.ScrollToCaret(); //将控件内容滚动到当前插入符号位置
            //}
            //else
            //{
            //    MessageBox.Show($"读取失败,错误原因:{readBool.Message}", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
            //}
            #endregion
        }
        /// <summary>
        /// 读取Float值
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void readFloatBtn_Click(object sender, EventArgs e)
        {
            #region 方法1
            OperateResult<Single> read = beckhoffAdsNet.ReadFloat(addressTxt1.Text.Trim());
            if (read.IsSuccess)
            {
                resultTxt.Text += read.Content + "\r\n";
                resultTxt.SelectionStart = resultTxt.Text.Length; //在文本框中的选定文本的起始位置
                resultTxt.ScrollToCaret(); //将控件内容滚动到当前插入符号位置
            }
            else
            {
                MessageBox.Show($"读取失败,错误原因:{read.Message}", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
            } 
            #endregion

            #region 方法2
            //readFloat = beckhoffAdsNet.Read<plcAddress>();
            //if (readFloat.IsSuccess)
            //{
            //    resultTxt.Text += readFloat.Content.Float + "\r\n";
            //    resultTxt.SelectionStart = resultTxt.Text.Length; //在文本框中的选定文本的起始位置
            //    resultTxt.ScrollToCaret(); //将控件内容滚动到当前插入符号位置
            //}
            //else
            //{
            //    MessageBox.Show($"读取失败,错误原因:{readFloat.Message}", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
            //} 
            #endregion
        }
        /// <summary>
        /// 读取Double值
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void readDoubleBtn_Click(object sender, EventArgs e)
        {
            #region 方法1
            OperateResult<Double> read = beckhoffAdsNet.ReadDouble(addressTxt1.Text.Trim());
            if (read.IsSuccess)
            {
                resultTxt.Text += read.Content + "\r\n";
                resultTxt.SelectionStart = resultTxt.Text.Length; //在文本框中的选定文本的起始位置
                resultTxt.ScrollToCaret(); //将控件内容滚动到当前插入符号位置
            }
            else
            {
                MessageBox.Show($"读取失败,错误原因:{read.Message}", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
            } 
            #endregion

            #region 方法2
            //readDouble = beckhoffAdsNet.Read<plcAddress>();
            //if (readDouble.IsSuccess)
            //{
            //    resultTxt.Text += readDouble.Content.Double + "\r\n";
            //    resultTxt.SelectionStart = resultTxt.Text.Length; //在文本框中的选定文本的起始位置
            //    resultTxt.ScrollToCaret(); //将控件内容滚动到当前插入符号位置
            //}
            //else
            //{
            //    MessageBox.Show($"读取失败,错误原因:{readDouble.Message}", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
            //}
            #endregion
        }
        /// <summary>
        /// 读取Byte值
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void readByteBtn_Click(object sender, EventArgs e)
        {

            #region 方法1
            OperateResult<byte> read = beckhoffAdsNet.ReadByte(addressTxt1.Text.Trim());
            if (read.IsSuccess)
            {
                resultTxt.Text += read.Content + "\r\n";
                resultTxt.SelectionStart = resultTxt.Text.Length; //在文本框中的选定文本的起始位置
                resultTxt.ScrollToCaret(); //将控件内容滚动到当前插入符号位置
            }
            else
            {
                MessageBox.Show($"读取失败,错误原因:{readByte.Message}", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
            } 
            #endregion

            #region 方法2
            //readByte = beckhoffAdsNet.Read<plcAddress>();
            //if (readByte.IsSuccess)
            //{
            //    resultTxt.Text += readByte.Content.Byte + "\r\n";
            //    resultTxt.SelectionStart = resultTxt.Text.Length; //在文本框中的选定文本的起始位置
            //    resultTxt.ScrollToCaret(); //将控件内容滚动到当前插入符号位置
            //}
            //else
            //{
            //    MessageBox.Show($"读取失败,错误原因:{readByte.Message}", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
            //} 
            #endregion

        }
        /// <summary>
        /// 写入Bool值
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void wirteBoolBtn_Click(object sender, EventArgs e)
        {
            try
            {
                #region 方法1
                string str = writeTxt.Text;
                switch (writeTxt.Text)
                {
                    case "1":
                        str = "true"; break;
                    case "0":
                        str = "false"; break;

                }

                OperateResult writeBool = beckhoffAdsNet.Write(addressTxt2.Text, Convert.ToBoolean(str));
                if (writeBool.IsSuccess)
                {
                    MessageBox.Show("写入成功");
                }
                else
                {
                    MessageBox.Show($"写入成功失败,错误信息:{writeBool.Message}");
                } 
                #endregion

                #region 方法2
                //string str = writeTxt.Text;
                //switch (writeTxt.Text)
                //{
                //    case "1":
                //        str = "true"; break;
                //    case "0":
                //        str = "false"; break;

                //}
                //data = new plcAddress()
                //{
                //    Bool = Convert.ToBoolean(str)
                //};
                //write = beckhoffAdsNet.Write(data);
                //if (write.IsSuccess)
                //{
                //    MessageBox.Show("写入成功");
                //}
                //else
                //{
                //    MessageBox.Show($"写入成功失败:{write }");
                //} 
                #endregion
            }
            catch (Exception ex)
            {
                MessageBox.Show($"写入失败,错误信息:{ex}");
            }

        }
        /// <summary>
        /// 写入Float值
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void writeFloatBtn_Click(object sender, EventArgs e)
        {
            try
            {

                #region 方法1
                OperateResult writeFloat = beckhoffAdsNet.Write(addressTxt2.Text, Convert.ToSingle(writeTxt.Text.Trim()));
                if (writeFloat.IsSuccess)
                {
                    MessageBox.Show("写入成功");
                }
                else
                {
                    MessageBox.Show($"写入成功失败,错误信息:{writeFloat.Message}");
                } 
                #endregion

                #region 方法2
                //data = new plcAddress()
                //{
                //    Float = Convert.ToSingle(writeTxt.Text)
                //};
                //write = beckhoffAdsNet.Write(data);
                //if (write.IsSuccess)
                //{
                //    MessageBox.Show("写入成功");
                //}
                //else
                //{
                //    MessageBox.Show($"写入成功失败:{write }");
                //} 
                #endregion
            }
            catch (Exception ex)
            {
                MessageBox.Show($"写入失败,错误信息:{ex}");
            }

        }
        /// <summary>
        /// 写入Double值
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void writeDoubleBtn_Click(object sender, EventArgs e)
        {
            try
            {
                #region 方法1
                OperateResult writeDouble = beckhoffAdsNet.Write(addressTxt2.Text, Convert.ToDouble(writeTxt.Text.Trim()));
                if (writeDouble.IsSuccess)
                {
                    MessageBox.Show("写入成功");
                }
                else
                {
                    MessageBox.Show($"写入成功失败,错误信息:{writeDouble.Message}");
                } 
                #endregion

                #region 方法2
                //data = new plcAddress()
                //{
                //    Double = Convert.ToDouble(writeTxt.Text)
                //};
                //write = beckhoffAdsNet.Write(data);
                //if (write.IsSuccess)
                //{
                //    MessageBox.Show("写入成功");
                //}
                //else
                //{
                //    MessageBox.Show($"写入成功失败:{write }");
                //} 
                #endregion

            }
            catch (Exception ex)
            {
                MessageBox.Show($"写入失败,错误信息:{ex}");
            }

        }
        /// <summary>
        /// 写入Byte值
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void writeByteBtn_Click(object sender, EventArgs e)
        {

            try
            {
                #region 方法2
                OperateResult writeByte = beckhoffAdsNet.Write(addressTxt2.Text, Convert.ToByte(writeTxt.Text.Trim()));
                if (writeByte.IsSuccess)
                {
                    MessageBox.Show("写入成功");
                }
                else
                {
                    MessageBox.Show($"写入成功失败,错误信息:{writeByte.Message}");
                }
                #endregion
                #region 方法2
                //data = new plcAddress()
                //{
                //    Byte = Convert.ToByte(writeTxt.Text)
                //};
                //write = beckhoffAdsNet.Write(data);
                //if (write.IsSuccess)
                //{
                //    MessageBox.Show("写入成功");
                //}
                //else
                //{
                //    MessageBox.Show($"写入成功失败:{write }");
                //} 
                #endregion
            }
            catch (Exception ex)
            {
                MessageBox.Show($"写入失败,错误信息:{ex}");
            }

        }
    }
}

plcAddress.cs

using HslCommunication.Reflection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 倍福PLC
{
    class plcAddress
    {
        /// <summary>
        /// 设备是否启动
        /// </summary>
        [HslDeviceAddress("M100")]
        public double Double { get; set; }

        /// <summary>
        /// 产量信息
        /// </summary>
        [HslDeviceAddress("M100")]
        public bool Bool { get; set; }

        /// <summary>
        /// 温度信息
        /// </summary>
        [HslDeviceAddress("M100")]
        public float Float { get; set; }

        /// <summary>
        /// 连续的位报警信息
        /// </summary>
        [HslDeviceAddress("M100")]
        public byte Byte { get; set; }
    }
}


 

  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 倍福(Phytec倍福电子技术(上海)有限公司)是一家专业从事嵌入式系统的设计、开发和制造的公司,其ADS(Advanced Development System)是一套基于C++语言开发的通用控制面板软件开发工具包。 倍福的ADS和上位机的通信方式,可以通过TCP/IP协议或者串口通信实现。在TCP/IP协议下,ADS会作为一个服务器的角色(监听一个指定的端口),当上位机连接到ADS时,ADS会创建一个新的套接字来处理与该上位机的通信;在串口通信下,ADS将串口配置为指定的波特率、校验方式、数据位和停止位等参数,通过串口收发数据来实现与上位机的通信。 在具体实现过程中,可以采用socket编程实现TCP/IP通信,或者使用串口库实现串口通信。同时,ADS可定制化配置,可根据客户的需求,选择合适的通信方案,并进行相应的编程实现,以实现ADS与上位机之间的高效、稳定的通信。 ### 回答2: 倍福是一种智能硬件系统,可以在工业控制和自动化等领域中应用。在工作过程中,倍福需要通过串口与上位机进行通信。而在实际应用中,具体的ADS通信和上位机通信步骤如下: 首先,用户需要连接倍福上位机所在的串口,然后运行ADS软件,确保ADS已经连接上了硬件设备。在建立通信之前,需要首先给硬件系统进行编程,然后把编程代码上传到硬件设备中,这样才可以使设备与ADS软件相互通信。 接下来,用户需要在ADS中选择相应的端口、波特率等配置,并设置相应的命令。这些命令可以包括读取传感器数据、设定倍福输出信号等。在设置完成之后,用户可以通过ADS界面操作,并通过串口与硬件系统进行交互。 在整个通信过程中,硬件系统需要实现以下功能:处理ADS发送的命令信息,根据命令信息进行相应的操作,例如读取数据、处理数据等。在数据处理完成之后,硬件系统需要将结果通过串口返回给上位机。 总的来说,ADS和上位机通信是一个重要的功能,它能够让倍福智能硬件系统与用户进行数据交互,实现更多的工业控制和自动化应用。 ### 回答3: 倍福的ADS(Active Dual Sensor)是一种基于MEMS制造技术的高精度角度测量传感器,它可以通过串行外设接口(SPI)与上位机进行通信。具体来说,通过ADS的SPI接口可以向上位机发送传感器采集的数据,比如角度值、温度值等等。同时,ADS也可以接收来自上位机的指令,比如配置传感器的采样率、滤波器、校准等参数。通过这样的通信方式,上位机可以实时地获取倍福传感器的输出数据,进而进行更加精细的算法计算和控制应用。 在硬件接口方面,倍福的ADS可以与各种MCU(Micro Controller Unit)进行接口。一些常用的开发板包括STM32F系列,Arduino,Raspberry Pi等等。同时,倍福也提供了Windows下的GUI(Graphical User Interface)软件,可以对ADS进行配置和数据读取。值得一提的是,ADS的SPI接口通信速率可以高达10MHz,保证了高效率的数据传输。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值