当前位置:   article > 正文

C#使用libmodbus库与工业设备进行读写测试_c# modbus库

c# modbus库

一.编译libmodbus库供C#使用

如何编译?请移步:https://blog.csdn.net/weixin_42205408/article/details/119530811

上面博主的文章除了所写的modbus.cs内的代码有点问题外(可能上面博主和我的Win 10 64位 Visual Studio 2019平台不一样吧),其他写的很详细。

二.实际应用

把编译得到的modbus.dll文件添加到C#项目中

我在他的基础上更改了modbus.cs(我的是libmodbus.cs),其实类名可以自己定义。

1.libmodbus.cs类如下:
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace Robotics_Studio
  8. {
  9. class libmodbus
  10. {
  11. ///[modbus.h]MODBUS_API int modbus_set_slave(modbus_t *ctx, int slave);
  12. [DllImport("modbus.dll", EntryPoint = "modbus_set_slave", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  13. public static extern int modbus_set_slave(IntPtr ctx, int slave);
  14. ///[modbus.h]MODBUS_API int modbus_get_slave(modbus_t *ctx);
  15. [DllImport("modbus.dll", EntryPoint = "modbus_get_slave", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  16. public static extern int modbus_get_slave(IntPtr ctx);
  17. ///[modbus.h]MODBUS_API int modbus_set_socket(modbus_t *ctx, int s);
  18. [DllImport("modbus.dll", EntryPoint = "modbus_set_socket", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  19. public static extern int modbus_set_socket(IntPtr ctx, int s);
  20. ///[modbus.h]MODBUS_API int modbus_get_socket(modbus_t *ctx);
  21. [DllImport("modbus.dll", EntryPoint = "modbus_get_socket", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  22. public static extern int modbus_get_socket(IntPtr ctx);
  23. ///[modbus.h]MODBUS_API int modbus_get_response_timeout(modbus_t* ctx, uint32_t* to_sec, uint32_t* to_usec);
  24. [DllImport("modbus.dll", EntryPoint = "modbus_get_response_timeout", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  25. public static extern int modbus_get_response_timeout(IntPtr ctx, UInt32[] to_sec, UInt32[] to_usec);
  26. ///[modbus.h]MODBUS_API int modbus_set_response_timeout(modbus_t* ctx, uint32_t to_sec, uint32_t to_usec);
  27. [DllImport("modbus.dll", EntryPoint = "modbus_set_response_timeout", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  28. public static extern int modbus_set_response_timeout(IntPtr ctx, UInt32 to_sec, UInt32 to_usec);
  29. ///[modbus-rtu.h]MODBUS_API modbus_t *modbus_new_rtu(const char *device, int band, char parity, int data_bit, int stop_bit);
  30. [DllImport("modbus.dll", EntryPoint = "modbus_new_rtu", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  31. public static extern IntPtr modbus_new_rtu(string device, int baud, char parity, int data_bit, int stop_bit);
  32. ///[modbus-tcp.h]MODBUS_API modbus_t *modbus_new_tcp(const char *ip_address, int port);
  33. [DllImport("modbus.dll", EntryPoint = "modbus_new_tcp", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  34. public static extern IntPtr modbus_new_tcp(string ip_address, int port);
  35. ///[modbus-tcp.h]MODBUS_API int modbus_tcp_listen(modbus_t *ctx, int nb_connection);
  36. [DllImport("modbus.dll", EntryPoint = "modbus_tcp_listen", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  37. public static extern IntPtr modbus_tcp_listen(IntPtr ctx, int nb_connection);
  38. ///[modbus-tcp.h]MODBUS_API int modbus_tcp_accept(modbus_t *ctx, int *s);
  39. [DllImport("modbus.dll", EntryPoint = "modbus_tcp_accept", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  40. public static extern IntPtr modbus_tcp_accept(IntPtr ctx, int[] s);
  41. ///[modbus.h]MODBUS_API int modbus_connect(modbus_t *ctx);
  42. [DllImport("modbus.dll", EntryPoint = "modbus_connect", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  43. public static extern int modbus_connect(IntPtr ctx);
  44. ///[modbus.h]MODBUS_API void modbus_close(modbus_t *ctx);
  45. [DllImport("modbus.dll", EntryPoint = "modbus_close", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  46. public static extern void modbus_close(IntPtr ctx);
  47. ///[modbus.h]MODBUS_API void modbus_free(modbus_t *ctx);
  48. [DllImport("modbus.dll", EntryPoint = "modbus_free", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  49. public static extern void modbus_free(IntPtr ctx);
  50. ///[modbus.h]MODBUS_API void modbus_flush(modbus_t *ctx);
  51. [DllImport("modbus.dll", EntryPoint = "modbus_flush", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  52. public static extern void modbus_flush(IntPtr ctx);
  53. ///[modbus.h]MODBUS_API int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);
  54. [DllImport("modbus.dll", EntryPoint = "modbus_read_bits", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  55. public static extern int modbus_read_bits(IntPtr ctx, int addr, int nb, byte[] dest);
  56. ///[modbus.h]MODBUS_API int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);
  57. [DllImport("modbus.dll", EntryPoint = "modbus_read_input_bits", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  58. public static extern int modbus_read_input_bits(IntPtr ctx, int addr, int nb, byte[] dest);
  59. ///[modbus.h]MODBUS_API int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
  60. [DllImport("modbus.dll", EntryPoint = "modbus_read_registers", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  61. public static extern int modbus_read_registers(IntPtr ctx, int addr, int nb, UInt16[] dest);
  62. ///[modbus.h]MODBUS_API int modbus_read_input_registers(modbus_t* ctx, int addr, int nb, uint16_t* dest);
  63. [DllImport("modbus.dll", EntryPoint = "modbus_read_input_registers", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  64. public static extern int modbus_read_input_registers(IntPtr ctx, int addr, int nb, UInt16[] dest);
  65. ///[modbus.h]MODBUS_API int modbus_write_bit(modbus_t *ctx, int coil_addr, int status);
  66. [DllImport("modbus.dll", EntryPoint = "modbus_write_bit", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  67. public static extern int modbus_write_bit(IntPtr ctx, int coil_addr, int status);
  68. ///[modbus.h]MODBUS_API int modbus_write_register(modbus_t *ctx, int reg_addr, const uint16_t value);
  69. [DllImport("modbus.dll", EntryPoint = "modbus_write_register", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  70. public static extern int modbus_write_register(IntPtr ctx, int reg_addr, UInt16 value);
  71. ///[modbus.h]MODBUS_API int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *data);
  72. [DllImport("modbus.dll", EntryPoint = "modbus_write_bits", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  73. public static extern int modbus_write_bits(IntPtr ctx, int addr, int nb, byte[] data);
  74. ///[modbus.h]MODBUS_API int modbus_write_registers(modbus_t* ctx, int addr, int nb, const uint16_t* data);
  75. [DllImport("modbus.dll", EntryPoint = "modbus_write_registers", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  76. public static extern int modbus_write_registers(IntPtr ctx, int addr, int nb, UInt16[] data);
  77. ///[modbus.h]MODBUS_API int modbus_write_and_read_registers(modbus_t *ctx, int write_addr, int write_nb, const uint16_t* src, int read_addr, int read_nb, uint16_t *dest);
  78. [DllImport("modbus.dll", EntryPoint = "modbus_write_and_read_registers", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  79. public static extern int modbus_write_and_read_registers(IntPtr ctx, int write_addr, int write_nb, UInt16[] scr, int read_addr, int read_nb, UInt16[] dest);
  80. }
  81. }
2.C#逻辑主程序

注意事项:

2.1 假设你的类名叫 libmodbus.cs

需注意类中的引用部分,例如

[DllImport("modbus.dll", EntryPoint = "modbus_new_tcp", CharSet = CharSet.Ansi)]

全部都需要加上: CallingConvention = CallingConvention.Cdecl

即:

[DllImport("modbus.dll", EntryPoint = "modbus_new_tcp", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]

否则出现:原因可能是托管的PInvoke签名与非托管的目标签名不匹配

上面的libmodbus.cs就是已经改好过来的。

2.2 使用类时需注意

  1. libmodbus modbus_tcp = new libmodbus();
  2. modbus_tcp.modbus_set_slave(modbus_tcp.modbus_new_tcp(ip1, 502),2);//此行会报错,无法使用实例引用来访问成员,请改用类型名来限定它

应改为
 

  1. //libmodbus modbus_tcp = new libmodbus();//注释掉此行
  2. libmodbus.modbus_set_slave(modbus_tcp.modbus_new_tcp(ip1, 502),2);//更改后

2.3 已测试好的例子如下:

  1. private void button_Connect_Click(object sender, EventArgs e)
  2. {
  3. if (button_Connect.Text == "连接")
  4. {
  5. string RobotIP = this.textBox_IP.Text.Trim();
  6. //by libmodbus
  7. IntPtr Machine = libmodbus.modbus_new_tcp(RobotIP, 502);//创建TCP连接
  8. libmodbus.modbus_set_slave(Machine, 2);
  9. int connectSta = 0;
  10. int connectCnt = 0;
  11. while (true)
  12. {
  13. connectSta = libmodbus.modbus_connect(Machine);
  14. if (connectSta == 0)//连接状态
  15. {
  16. break;
  17. }
  18. connectCnt += 1;
  19. if(connectCnt == 4)//连接失败次数计数
  20. {
  21. connectSta = -1;
  22. break;
  23. }
  24. }
  25. if (connectSta == -1)
  26. {
  27. MessageBox.Show("Try many times were failed,Try again please!", "Info:");
  28. return;
  29. }
  30. try
  31. {
  32. //读单个保持寄存器
  33. ushort[] servoSta = { 0 };//伺服状态
  34. libmodbus.modbus_read_registers(Machine, 0x0006, 1, servoSta);
  35. Console.WriteLine("read servo status: {0}", servoSta[0]);
  36. //读多个保持寄存器
  37. ushort[] current_pos = new ushort[12];//位置坐标
  38. libmodbus.modbus_read_registers(Machine, 0x00F0, 12, current_pos);
  39. Console.WriteLine("read xH,xL: {0},{1}", current_pos[0], current_pos[1]);
  40. Console.WriteLine("read yH,yL: {0},{1}", current_pos[2], current_pos[3]);
  41. Console.WriteLine("read zH,zL: {0},{1}", (Int16)current_pos[4], (Int16)current_pos[5]);//(Int16)是把无符号16位整型转有符号16位整型
  42. Console.WriteLine("read cH,cL: {0},{1}", current_pos[10], current_pos[11]);
  43. Console.WriteLine("read x: {0}", Two16Int_2_One32Int(current_pos[0], current_pos[1]));
  44. Console.WriteLine("read y: {0}", Two16Int_2_One32Int(current_pos[2], current_pos[3]));
  45. Console.WriteLine("read z: {0}", Two16Int_2_One32Int(current_pos[4], current_pos[5]));
  46. Console.WriteLine("read c: {0}", Two16Int_2_One32Int(current_pos[10], current_pos[11]));
  47. //写单个保持寄存器
  48. ushort value1 = 32767;//write Int16 (2^15)-1 = 32767
  49. libmodbus.modbus_write_register(Machine, 0x2000, value1);
  50. //写单个保持寄存器
  51. ushort[] value2 = { 32767 };//write Int16 (2^15)-1 = 32767
  52. libmodbus.modbus_write_registers(Machine, 0x2002, 1, value2);
  53. //写多个保持寄存器
  54. ushort[] value3 = { 65535,32767 };//write Int32 (2^31)-1 = 2147483647
  55. libmodbus.modbus_write_registers(Machine, 0x2004, 2, value3);
  56. }
  57. catch(Exception ex)
  58. {
  59. MessageBox.Show("Read error!\n" + ex.Message, "Info:");
  60. }
  61. }
  62. }

运行结果如下:

工业设备端:

 

 完结

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/566182
推荐阅读
相关标签
  

闽ICP备14008679号