• C#和西门子PLC使用Udp通信


    目录

    一、PLC程序工程创建

    1、硬件配置

    2、程序编程

    3、添加监控表

    二、C#程序工程创建

    1、界面UI

    2、代码编写

    (1)创建本地Udp

    (2)读PLC的线程函数

    (3)定时器

    (4)上位机写寄存器操作

    (5)StringToByte()方法封装

    (6)窗口关闭

    3、C#和PLC测试

    (1)C#上位机写操作1

    (2)C#上位机写操作2

    (3)C#控制PLC中的继电器输出

    (4)C#上位机读操作

     (5)串口调试助手和PLC通信测试

    三、工程合并下载连接


    一、PLC程序工程创建

    1、硬件配置

    2、程序编程

    Main程序

     

     

     "TSEND_C_DB"功能块配置如下:

    "TURCV_DB"功能块不需要配置,ADDR地址和"TSEND_C_DB"相同即可

    3、添加监控表

     双击添加新监控表,在监控表中分别添加MB20-MB29、MB30-MB39寄存器。在监控状态下,可以实时的读取、修改当前寄存器值

     

    二、C#程序工程创建

    1、界面UI

    2、代码编写

    (1)创建本地Udp

    注意的是,本地Udp创建成功后,先给PLC寄存器发送0做数据测试。PLC只有在接收到到一次上位机发送的程序,PLC才会启动对上位机发送功能,因为共用的功能块ADDR中的地址。

    1. private void btnConnect_Click(object sender, EventArgs e)
    2. {
    3. try
    4. {
    5. LocalIp = txtLocalIp.Text;
    6. LocalPort = int.Parse(txtLocalPort.Text);
    7. TargetIp = txtPlcIp.Text;
    8. TargetPort = int.Parse(txtPlcPort.Text);
    9. client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    10. client.Bind(new IPEndPoint(IPAddress.Parse(LocalIp), LocalPort));
    11. Thread.Sleep(50);
    12. MessageBox.Show("本地Udp创建成功");
    13. txtUdpState.Text = "本地Udp创建成功";
    14. isUdpConnected = true;
    15. //本地Udp创建成功后,先给PLC寄存器发送0做数据测试
    16. byte[] sendBytes = new byte[10];
    17. sendBytes[0] = 0x00;
    18. sendBytes[1] = 0x00;
    19. sendBytes[2] = 0x00;
    20. sendBytes[3] = 0x00;
    21. sendBytes[4] = 0x00;
    22. sendBytes[5] = 0x00;
    23. sendBytes[6] = 0x00;
    24. sendBytes[7] = 0x00;
    25. sendBytes[8] = 0x00;
    26. sendBytes[9] = 0x00;
    27. EndPoint point = new IPEndPoint(IPAddress.Parse(TargetIp), TargetPort);
    28. client.SendTo(sendBytes, point);
    29. threadRecv = new Thread(ReciveMsg);
    30. threadRecv.Start();
    31. timer1.Start();
    32. }
    33. catch
    34. {
    35. txtUdpState.Text = "本地Udp创建失败";
    36. }
    37. }

    (2)读PLC的线程函数

    1. void ReciveMsg()
    2. {
    3. while (true)
    4. {
    5. if(isUdpConnected)
    6. {
    7. EndPoint point = new IPEndPoint(IPAddress.Any, 0);//用来保存发送方的ip和端口号
    8. byte[] buffer = new byte[1024];
    9. int length = client.ReceiveFrom(buffer, ref point);//接收数据报
    10. if(length>0)
    11. {
    12. for(int i=0;i<10;i++)
    13. {
    14. byteRecvs[i] = buffer[i];
    15. }
    16. }
    17. }
    18. }
    19. }

    (3)定时器

    1. private void timer1_Tick(object sender, EventArgs e)
    2. {
    3. //将线程中接收到PLC的byte数据,转换成16进制的字符串显示
    4. txtReadMB20.Text = byteRecvs[0].ToString("X");
    5. txtReadMB21.Text = byteRecvs[1].ToString("X");
    6. txtReadMB22.Text = byteRecvs[2].ToString("X");
    7. txtReadMB23.Text = byteRecvs[3].ToString("X");
    8. txtReadMB24.Text = byteRecvs[4].ToString("X");
    9. txtReadMB25.Text = byteRecvs[5].ToString("X");
    10. txtReadMB26.Text = byteRecvs[6].ToString("X");
    11. txtReadMB27.Text = byteRecvs[7].ToString("X");
    12. txtReadMB28.Text = byteRecvs[8].ToString("X");
    13. txtReadMB29.Text = byteRecvs[9].ToString("X");
    14. }

    (4)上位机写寄存器操作

    1. private void btnWriteValue_Click(object sender, EventArgs e)
    2. {
    3. try
    4. {
    5. if(isUdpConnected==false)
    6. {
    7. MessageBox.Show("请先创建本地Udp", "提示");
    8. return;
    9. }
    10. byte[] sendBytes = new byte[10];
    11. //sendBytes[0] = 0x10;
    12. //sendBytes[1] = 0x10;
    13. //sendBytes[2] = 0x10;
    14. //sendBytes[3] = 0x10;
    15. //sendBytes[4] = 0x10;
    16. //sendBytes[5] = 0x10;
    17. //sendBytes[6] = 0x10;
    18. //sendBytes[7] = 0x10;
    19. //sendBytes[8] = 0x10;
    20. //sendBytes[9] = 0x10;
    21. sendBytes[0] = StringToByte(txtWriteMB30.Text);
    22. sendBytes[1] = StringToByte(txtWriteMB31.Text);
    23. sendBytes[2] = StringToByte(txtWriteMB32.Text);
    24. sendBytes[3] = StringToByte(txtWriteMB33.Text);
    25. sendBytes[4] = StringToByte(txtWriteMB34.Text);
    26. sendBytes[5] = StringToByte(txtWriteMB35.Text);
    27. sendBytes[6] = StringToByte(txtWriteMB36.Text);
    28. sendBytes[7] = StringToByte(txtWriteMB37.Text);
    29. sendBytes[8] = StringToByte(txtWriteMB38.Text);
    30. sendBytes[9] = StringToByte(txtWriteMB39.Text);
    31. EndPoint point = new IPEndPoint(IPAddress.Parse(TargetIp), TargetPort);
    32. client.SendTo(sendBytes, point);
    33. MessageBox.Show("发送成功");
    34. }
    35. catch(Exception ex)
    36. {
    37. MessageBox.Show(ex.ToString());
    38. }
    39. }

    (5)StringToByte()方法封装

    封装方法需要注意的是,PLC寄存器最大只能支持两位的16进制FF。所以,需要将测写入的字符串不能超过3两位、同时也不能超过F。

    1. /// <summary>
    2. /// 字符串转byte数据
    3. /// </summary>
    4. /// <param name="s"></param>
    5. /// <returns></returns>
    6. private byte StringToByte(string s)
    7. {
    8. if(s.Length>2)
    9. {
    10. throw new ArgumentNullException("超过两位或者不是16进制字符!");
    11. }
    12. byte b;
    13. try
    14. {
    15. string str;
    16. str = "0x" + s;
    17. b = Convert.ToByte(str, 16);
    18. }
    19. catch
    20. {
    21. throw new ArgumentNullException("不是指定的16进制字符");
    22. }
    23. return b;
    24. }

    (6)窗口关闭

    1. private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    2. {
    3. System.Environment.Exit(0); //强制关闭所有线程
    4. }

    3、C#和PLC测试

    (1)C#上位机写操作1

     

    (2)C#上位机写操作2

    (3)C#控制PLC中的继电器输出

    (4)C#上位机读操作

    在PLC程序中,将M60.0强制TRUE

     PLC即将数据以0.5秒的时间周期发送上位机C#,时间可以调快一点比如50毫秒、100毫秒都可以

     

     (5)串口调试助手和PLC通信测试

    对于不会C#上位机编程的电气工程师来说,也可以使用网络调试助手来做测试。测试方法参加另一篇博客西门子S7-1200 PLC和上位机通信_Big_潘大师的博客-CSDN博客_西门子1200与上位机s7通讯

    三、工程合并下载连接

    https://download.csdn.net/download/panjinliang066333/86508006

  • 相关阅读:
    Linux上部署zabbix 6.x
    Java【多线程】Callable 是什么, 如何使用并理解 Cllable, 和 Runnable 有什么区别?
    IEEE(常用)参考文献引用格式详解 | LaTeX参考文献规范(IEEE Trans、Conf、Arxiv)
    #AngularJS#表达式
    【老生谈算法】matlab实现低通滤波器算法源码——低通滤波器
    网络协议-语义、语法和时序
    spark sql(四)物理计划解析
    6 Processes 下
    微信小程序使用vant weapp报错
    expect脚本中使用scp命令的方法,expect脚本中scp命令获取不了值的问题完美解决方法
  • 原文地址:https://blog.csdn.net/panjinliang066333/article/details/126677574