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

一.编译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类如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;namespace Robotics_Studio
{class libmodbus{///[modbus.h]MODBUS_API int modbus_set_slave(modbus_t *ctx, int slave);[DllImport("modbus.dll", EntryPoint = "modbus_set_slave", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern int modbus_set_slave(IntPtr ctx, int slave);///[modbus.h]MODBUS_API int modbus_get_slave(modbus_t *ctx);[DllImport("modbus.dll", EntryPoint = "modbus_get_slave", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern int modbus_get_slave(IntPtr ctx);///[modbus.h]MODBUS_API int modbus_set_socket(modbus_t *ctx, int s);[DllImport("modbus.dll", EntryPoint = "modbus_set_socket", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern int modbus_set_socket(IntPtr ctx, int s);///[modbus.h]MODBUS_API int modbus_get_socket(modbus_t *ctx);[DllImport("modbus.dll", EntryPoint = "modbus_get_socket", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern int modbus_get_socket(IntPtr ctx);///[modbus.h]MODBUS_API int modbus_get_response_timeout(modbus_t* ctx, uint32_t* to_sec, uint32_t* to_usec);[DllImport("modbus.dll", EntryPoint = "modbus_get_response_timeout", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern int modbus_get_response_timeout(IntPtr ctx, UInt32[] to_sec, UInt32[] to_usec);///[modbus.h]MODBUS_API int modbus_set_response_timeout(modbus_t* ctx, uint32_t to_sec, uint32_t to_usec);[DllImport("modbus.dll", EntryPoint = "modbus_set_response_timeout", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern int modbus_set_response_timeout(IntPtr ctx, UInt32 to_sec, UInt32 to_usec);///[modbus-rtu.h]MODBUS_API modbus_t *modbus_new_rtu(const char *device, int band, char parity, int data_bit, int stop_bit);[DllImport("modbus.dll", EntryPoint = "modbus_new_rtu", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern IntPtr modbus_new_rtu(string device, int baud, char parity, int data_bit, int stop_bit);///[modbus-tcp.h]MODBUS_API modbus_t *modbus_new_tcp(const char *ip_address, int port);[DllImport("modbus.dll", EntryPoint = "modbus_new_tcp", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern IntPtr modbus_new_tcp(string ip_address, int port);///[modbus-tcp.h]MODBUS_API int modbus_tcp_listen(modbus_t *ctx, int nb_connection);[DllImport("modbus.dll", EntryPoint = "modbus_tcp_listen", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern IntPtr modbus_tcp_listen(IntPtr ctx, int nb_connection);///[modbus-tcp.h]MODBUS_API int modbus_tcp_accept(modbus_t *ctx, int *s);[DllImport("modbus.dll", EntryPoint = "modbus_tcp_accept", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern IntPtr modbus_tcp_accept(IntPtr ctx, int[] s);///[modbus.h]MODBUS_API int modbus_connect(modbus_t *ctx);[DllImport("modbus.dll", EntryPoint = "modbus_connect", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern int modbus_connect(IntPtr ctx);///[modbus.h]MODBUS_API void modbus_close(modbus_t *ctx);[DllImport("modbus.dll", EntryPoint = "modbus_close", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern void modbus_close(IntPtr ctx);///[modbus.h]MODBUS_API void modbus_free(modbus_t *ctx);[DllImport("modbus.dll", EntryPoint = "modbus_free", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern void modbus_free(IntPtr ctx);///[modbus.h]MODBUS_API void modbus_flush(modbus_t *ctx);[DllImport("modbus.dll", EntryPoint = "modbus_flush", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern void modbus_flush(IntPtr ctx);///[modbus.h]MODBUS_API int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);[DllImport("modbus.dll", EntryPoint = "modbus_read_bits", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern int modbus_read_bits(IntPtr ctx, int addr, int nb, byte[] dest);///[modbus.h]MODBUS_API int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);[DllImport("modbus.dll", EntryPoint = "modbus_read_input_bits", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern int modbus_read_input_bits(IntPtr ctx, int addr, int nb, byte[] dest);///[modbus.h]MODBUS_API int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);[DllImport("modbus.dll", EntryPoint = "modbus_read_registers", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern int modbus_read_registers(IntPtr ctx, int addr, int nb, UInt16[] dest);///[modbus.h]MODBUS_API int modbus_read_input_registers(modbus_t* ctx, int addr, int nb, uint16_t* dest);[DllImport("modbus.dll", EntryPoint = "modbus_read_input_registers", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern int modbus_read_input_registers(IntPtr ctx, int addr, int nb, UInt16[] dest);///[modbus.h]MODBUS_API int modbus_write_bit(modbus_t *ctx, int coil_addr, int status);[DllImport("modbus.dll", EntryPoint = "modbus_write_bit", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern int modbus_write_bit(IntPtr ctx, int coil_addr, int status);///[modbus.h]MODBUS_API int modbus_write_register(modbus_t *ctx, int reg_addr, const uint16_t value);[DllImport("modbus.dll", EntryPoint = "modbus_write_register", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern int modbus_write_register(IntPtr ctx, int reg_addr, UInt16 value);///[modbus.h]MODBUS_API int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *data);[DllImport("modbus.dll", EntryPoint = "modbus_write_bits", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern int modbus_write_bits(IntPtr ctx, int addr, int nb, byte[] data);///[modbus.h]MODBUS_API int modbus_write_registers(modbus_t* ctx, int addr, int nb, const uint16_t* data);[DllImport("modbus.dll", EntryPoint = "modbus_write_registers", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]public static extern int modbus_write_registers(IntPtr ctx, int addr, int nb, UInt16[] data);///[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);[DllImport("modbus.dll", EntryPoint = "modbus_write_and_read_registers", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]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);}
}
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 使用类时需注意

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

应改为
 

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

2.3 已测试好的例子如下:

        private void button_Connect_Click(object sender, EventArgs e){if (button_Connect.Text == "连接"){string RobotIP = this.textBox_IP.Text.Trim();//by libmodbusIntPtr Machine = libmodbus.modbus_new_tcp(RobotIP, 502);//创建TCP连接libmodbus.modbus_set_slave(Machine, 2);int connectSta = 0;int connectCnt = 0;while (true){connectSta = libmodbus.modbus_connect(Machine);if (connectSta == 0)//连接状态{break;}connectCnt += 1;if(connectCnt == 4)//连接失败次数计数{connectSta = -1;break;}}if (connectSta == -1){ MessageBox.Show("Try many times were failed,Try again please!", "Info:");return;}try{//读单个保持寄存器ushort[] servoSta = { 0 };//伺服状态libmodbus.modbus_read_registers(Machine, 0x0006, 1, servoSta);Console.WriteLine("read servo status: {0}", servoSta[0]);//读多个保持寄存器ushort[] current_pos = new ushort[12];//位置坐标libmodbus.modbus_read_registers(Machine, 0x00F0, 12, current_pos);Console.WriteLine("read xH,xL: {0},{1}", current_pos[0], current_pos[1]);Console.WriteLine("read yH,yL: {0},{1}", current_pos[2], current_pos[3]);Console.WriteLine("read zH,zL: {0},{1}", (Int16)current_pos[4], (Int16)current_pos[5]);//(Int16)是把无符号16位整型转有符号16位整型Console.WriteLine("read cH,cL: {0},{1}", current_pos[10], current_pos[11]);Console.WriteLine("read x: {0}", Two16Int_2_One32Int(current_pos[0], current_pos[1]));Console.WriteLine("read y: {0}", Two16Int_2_One32Int(current_pos[2], current_pos[3]));Console.WriteLine("read z: {0}", Two16Int_2_One32Int(current_pos[4], current_pos[5]));Console.WriteLine("read c: {0}", Two16Int_2_One32Int(current_pos[10], current_pos[11]));//写单个保持寄存器ushort value1 = 32767;//write Int16 (2^15)-1 = 32767libmodbus.modbus_write_register(Machine, 0x2000, value1);//写单个保持寄存器ushort[] value2 = { 32767 };//write Int16 (2^15)-1 = 32767libmodbus.modbus_write_registers(Machine, 0x2002, 1, value2);//写多个保持寄存器ushort[] value3 = { 65535,32767 };//write Int32 (2^31)-1 = 2147483647libmodbus.modbus_write_registers(Machine, 0x2004, 2, value3);}catch(Exception ex){MessageBox.Show("Read error!\n" + ex.Message, "Info:");}}}

运行结果如下:

工业设备端:

 

 完结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/20000.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在群晖nas中使用cpolar内网穿透?

如何在群晖nas中使用cpolar内网穿透 文章目录 如何在群晖nas中使用cpolar内网穿透 今天,我们来为大家介绍,如何在群晖系统中,使用图形化界面的cpolar。 cpolar经过图形化改造后,使用方法已经简便了很多,基本与其他应用…

为什么流程工业需要合适的预测性维护方案?

在当今工业中,预测性维护是一项至关重要的战略,它能够帮助企业预测设备故障并防止代价高昂的停机。然而,对于流程制造和离散制造来说,选择合适的预测性维护解决方案是至关重要的,因为这两类行业在设备运营和维护方面存…

redis缓存

1.什么是缓存 缓存就是数据交换的缓冲区,称为cache,是存储数据的临时地方,一般读写性能较高 典型例子就是在计算机的CPU和内存、磁盘。CPU的运算能力非常强大,运算速度已经远远超过内存或者磁盘读写数据的能力。但是先读到数据才…

【内网穿透】内网穿透应用场景

伴随着科学技术的进步,我们身边出现了越来越多的电子设备,特别是移动电子设备的普及,给我们的生活带来极大的便利,而软件技术的发展,更为这些软件设备带来更多应用的可能。虽然移动设备覆盖了了我们生活的绝大部分场景…

Vue3基础知识(待续)

Vue是什么 构用户界面的js的渐进式框架,基于htlm、css、js,并提供声明式组件化的编程模型,帮你高效开发用户界面。无论简单或复杂的界面Vue都可以胜任。 vue是一个框架,同时也是一个生态。因为有很多程序员支持vue,开…

2023年第四届“华数杯”数学建模思路 - 案例:退火算法

## 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 退火算法原理 1.1 物理背景 在热力学上,退火(annealing)现象指物体逐渐降温的物理现象,温度愈低&#…

Git基础知识:常见功能和命令行

文章目录 1.Git介绍2.安装配置2.1 查看配置信息 3.文件管理3.1 创建仓库3.2 版本回退3.3 工作流程3.4 撤销修改3.5 删除文件 4.远程仓库4.1 连接远程库4.2 本地上传至远程4.3 从远程库克隆到本地 5.分支管理5.1 创建分支5.2 删除分支5.3 合并分支解决冲突 参考: Git…

《Kali渗透基础》12. 无线渗透(二)

kali渗透 1:无线协议栈1.1:ifconfig1.2:iwconfig1.3:iw1.4:iwlist 2:无线网卡配置2.1:查看无线网卡2.2:查看信道频率2.3:扫描附近 AP2.4:侦听接口添加与删除 …

键入网址到网页显示,期间发生了什么

HTTP 浏览器做的第一步工作是解析URL 首先浏览器做的第一步工作就是要对URL进行解析,从而生成发送给 web 服务器的请求信息。 所以图中长长的URL实际上是请求服务器里的文件资源。 如果图中的蓝色部分URL元素省略了,那应该请求哪个文件呢? 当…

ARM裸机-12(GPIO和LED)

1、点亮LED 1.1、硬件工作原理及原理图查阅 1.1.1、LED物理特性 LED本身有2个接线点,一个是LED的正极,一个是LED的负极。LED这个硬件的功能就是点亮或者不亮,物理上想要点亮一颗LED只需要给他的正负极上加正电压即可,要熄灭一颗…

智能化RFID耳机装配系统:提升效率、精准追踪与优化管理

智能化RFID耳机装配系统:提升效率、精准追踪与优化管理 在当今的智能化时代,无线射频识别技术(RFID)被广泛应用于各个行业。本文将介绍一种基于RFID技术的智能耳机装配案例,通过RFID技术实现耳机装配过程的自动化控制…

vue 新学习 04 css样式绑定,渲染,key的重要意义

之前的html文件如何去绑定css样式&#xff1f; 01.首先在html文件中&#xff0c;在<head>标签中&#xff0c;用<style>中去写样式&#xff0c;通过html标签(每一个标签都有这样子的属性)中的class或者是id属性来完成<style>中的描绘的样式的用。 例子&#x…

【计算机网络】NAT及Bridge介绍

OSI七层模型 七层模型介绍及举例 为通过网络将人类可读信息通过网络从一台设备传输到另一台设备&#xff0c;必须在发送设备沿 OSI 模型的七层结构向下传输数据&#xff0c;然后在接收端沿七层结构向上传输数据。 数据在 OSI 模型中如何流动 库珀先生想给帕尔梅女士发一封电…

回归预测 | MATLAB实现SO-CNN-GRU蛇群算法优化卷积门控循环单元多输入单输出回归预测

回归预测 | MATLAB实现SO-CNN-GRU蛇群算法优化卷积门控循环单元多输入单输出回归预测 目录 回归预测 | MATLAB实现SO-CNN-GRU蛇群算法优化卷积门控循环单元多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现SO-CNN-GRU蛇群算法优化卷积门控循…

操作系统启动后网络还需要比较慢的时间才启动(差不多二分钟)

环境 linux 4.14.61 systemd version 247.3 问题 启动时发现网络其实很快就起来了&#xff0c;但是mqtt和docker启动的很慢&#xff0c;导致相关依赖启动很慢。 问题分析 实际通过systemctl list-units发现systemd-networkd-wait-online启动失败 而且从字面上看也有延时…

图解TCP 三次握手和四次挥手的高频面试题(2023最新版)

大家好&#xff0c;最近重新整理了一版 TCP 三次握手和四次挥手的面试题&#xff08;2023最新版&#xff09;。 ----- 任 TCP 虐我千百遍&#xff0c;我仍待 TCP 如初恋。 巨巨巨巨长的提纲&#xff0c;发车&#xff01;发车&#xff01; img TCP 基本认识 TCP 头格式有哪些…

【Selenimu+AutoIT】非input标签上传文件(带参数)

工具下载 非input标签上传文件&#xff0c;就需要借助第三方工具&#xff0c;如AutoIT。 AutoIT下载 安装步骤略 使用 1.打开Auto Window Info 找到这个打开 拖住红框里面的标到需要定位的地方记录下来 2.打开SciTE Script Editor 打开后&#xff0c;修改为UTF-8&am…

统信UOS安装mysql数据库(mariadb)-统信UOS安装JDK-统信UOS安装nginx(附安装包)

统信UOS离线全套安装教程&#xff08;手把手教程&#xff09; 银河麒麟的各种离线全套安装教程&#xff1a; https://blog.csdn.net/ACCPluzhiqi/article/details/131988147 1.统信UOS桌面系统安装mysql&#xff08;mariadb&#xff09; 2.统信UOS桌面系统安装JDK 3.统信UOS桌…

【iOS】App仿写--天气预报

文章目录 前言一、首页二、搜索界面三、添加界面四、浏览界面总结 前言 最近完成了暑假的最后一个任务——天气预报&#xff0c;特此记录博客总结。根据iPhone中天气App的功能大致可以将仿写的App分为四个界面——首页&#xff0c;搜索界面&#xff0c;添加界面&#xff0c;浏…

【NLP概念源和流】 04-过度到RNN(第 4/20 部分)

接上文 【NLP概念源和流】 03-基于计数的嵌入,GloVe(第 3/20 部分) 一、说明 词嵌入使许多NLP任务有了显著的改进。它对单词原理图的理解以及将不同长度的文本表示为固定向量的能力使其在许多复杂的NLP任务中非常受欢迎。大多数机器学习算法可以直接应用于分类和回归任务的…