本文讲述了c#调用libmodbus 离线调试方法!具有很好的参考价值,希望对大家有所帮助。一起跟随六星小编过来看看吧,具体如下:
准备工具
1. VSPD虚拟串口工具,(7年前用过的工具,现在又用上了,幸好CSDN上传了一份,嘿嘿)
2. Modbus Slave调试工具
3.libModbus封装库
操作步骤:
1.VSPD绑定可以使用的串口号,如COM2与COM3,点击添加端口。
2.Modbus Slave工具点击Connection,选择“serial RTU”模式,COM口选择Port2格式选择如“192000, 8,‘E’,1”,
3.将基于C语言开发的libmodbus类库添加到c#项目工程中,C类库中添加读取ini配置文件的函数,增加需要给C#调用的函数接口
cf_op.h,cf_op.c
#pragma once
#define LineMaxLen 2048
#define KeyMaxLen 128
#define MaxFileLength 1024*10
#ifndef CF_OP_H
#define CF_OP_H
#ifdef __cplusplus
extern "C" {
#endif
int GetCfItem(const char *pFileName /*in*/, char *pKey /*in*/, char * pValue/*in out*/, int * pValueLen /*out*/);
int SetCfItem(const char *pFileName /*in*/, char *pKey /*in*/, char *pValue/*in*/);
#ifdef __cplusplus
}
#endif
#if defined(_MSC_VER)
# if defined(DLLBUILD)
/* define DLLBUILD when building the DLL */
# define MODBUS_API __declspec(dllexport)
# else
# define MODBUS_API __declspec(dllimport)
# endif
#else
# define MODBUS_API
#endif
static char getValueMsg[KeyMaxLen];
static char setValueMsg[KeyMaxLen];
MODBUS_API char * getValue(char *key);
MODBUS_API char * setValue(char *key, char *value);
MODBUS_API int sum(int a, int b);//only for test
#endif
char* getValue(char *key)// chane to key[KeyMaxLen] char *key
{
char *pFileName = "Platform.ini";
int len = 0, rv = 0;
memset(getValueMsg, 0, sizeof(getValueMsg));
rv = GetCfItem(pFileName, key, getValueMsg, &len);
if (rv != 0)
{
char *errMsg;
printf("Get the key value err!");
switch (rv)
{
case -1:
errMsg = "func GetCfItem paramter err!";
break;
case -2:
errMsg = "fopen file err!";
break;
case -3:
errMsg = "The key has no value!";
break;
case -4:
errMsg = "can't find the key";
break;
default:
break;
}
strcpy(getValueMsg, errMsg);
}
return getValueMsg;
}
char* setValue(char *key,char *value)
{
int rv = 0;
char *pFileName = "Platform.ini";
memset(setValueMsg, 0, sizeof(setValueMsg));
memset(value, 0, sizeof(value));*/
rv = SetCfItem(pFileName, key, value);
if (rv != 0)
{
char *errMsg;
printf("Get the key value err!");
switch (rv)
{
case -1:
errMsg = "func WriteCfItem paramter err!";
break;
case -2:
errMsg = "fopen file err";
break;
case -3:
errMsg = "file too long unspport";
break;
case -4:
errMsg = "fopen file err";
break;
default:
break;
}
strcpy(setValueMsg, errMsg);
return setValueMsg;
}
sprintf(setValueMsg, "key %s=%s set OK", key, value);
return setValueMsg;
}
int sum(int a, int b)
{
return a + b;
}
rotControl.h , rotControl.c
/*
* Copyright © <wu_xx2008@hotmail.com>
*
* antoy wu
* 2018-4-16 21:16:30
*/
#ifndef ROTCONTROL_H
#define ROTCONTROL_H
/* Add this for macros that defined unix flavor */
#if (defined(__unix__) || defined(unix)) && !defined(USG)
#include <sys/param.h>
#endif
#ifndef _MSC_VER
#include <stdint.h>
#else
#include "stdint.h"
#endif
#include "modbus-version.h"
#include <stdbool.h>
#include "RotationPlatformDefine.h"
#if defined(_MSC_VER)
# if defined(DLLBUILD)
/* define DLLBUILD when building the DLL */
# define ROT_API __declspec(dllexport)
# else
# define ROT_API __declspec(dllimport)
# endif
#else
# define MODBUS_API
#endif
char* messageStr;
volatile bool b_stop;
bool b_isInitial;
modbus_t*m_ctx;
intm_rc;
intm_nb_fail;
intm_nb_loop;
intm_addr;
intm_nb;
uint8_t*m_tab_rq_bits;
uint8_t*m_tab_rp_bits;
uint16_t*m_tab_rq_registers;
uint16_t*m_tab_rw_rq_registers;
uint16_t*m_tab_rp_registers;
uint16_tm_tab_reg[32] = { 0 };
uint8_t m_rec_reg[32] = { 0 };
uint8_tm_buf_8[32] = { 0 };
uint16_tm_buf_16[32] = { 0 };
int32_tm_cur_pos[3] = { 0 };
int32_tm_cur_vel[3] = { 0 };
int32_tm_cur_acc[3] = { 0 };
boolb_busy;
boolb_alarm;
boolb_emgency;
PlatformSetup m_platform_setup;
ROT_API bool rotInit();
#endif /* ROTCONTROL_H */
void paraInit()
{
b_stop = false;
b_isInitial = false;
m_ctx = NULL;
readIni();
}
bool modbusInit()
{
const char *device = getValue("Serial");
//sprintf(device, "COM%s", device);
if (m_ctx == NULL) {
m_ctx = modbus_new_rtu(device, Baudrate, Parity, Databit, Stopbit);
}
int ret = modbus_set_slave(m_ctx, SLAVE); // set slave adress
if (ret == -1) {
return false;
}
ret = modbus_connect(m_ctx);
if (ret == -1) {
return false;
}
b_isInitial = true;
return b_isInitial;
}
bool rotInit()
{
paraInit();//系统参数初始化以及读取配置文件
if (modbusInit())
{
b_isInitial = true;
}
return b_isInitial;
}
void closeModbus()
{
if(m_ctx!=NULL)
{
modbus_close(m_ctx);
modbus_free(m_ctx);
}
}
C#增加一个类库文件RotPlatformControl_CsDll,用于导入modbus.dll中的各个函数。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace RotPlatformControl_CsDll
{
public class CRotPlatformControl
{
[DllImport("modbus.dll", EntryPoint = "sum", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int sum(int a, int b);
[DllImport("modbus.dll", EntryPoint = "getValue", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr getValue(IntPtr intPtrKey);
[DllImport("modbus.dll", EntryPoint = "setValue", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr setValue(IntPtr intPtrKey, IntPtr intPtrValue);
[DllImport("modbus.dll", EntryPoint = "rotInit", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern bool rotInit();
}
}
UI调试界面增加一些按钮等。
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 System.Threading;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Principal;
using RotPlatformControl_CsDll;
namespace Mirage2B_IMU_Test
{
public partial class IMUDebugTool : Form
{
public IMUDebugTool()
{
InitializeComponent();
}
private void buttonHome_Click(object sender, EventArgs e)
{
log("转台开始回位!");
bool isRotInit=CRotPlatformControl.rotInit();
if(isRotInit)
lblMessage.Text = isRotInit.ToString();
//string res = Getvalue("Baudrate");
//lblMessage.Text = res.ToString();
}
private void buttonStop_Click(object sender, EventArgs e)
{
string strKey = "Hello";
string strValue = "Kitty";
string res=setvalue(strKey,strValue);
lblMessage.Text = res.ToString();
}
private string Getvalue(string strKey)
{
IntPtr key = Marshal.StringToHGlobalAnsi(strKey);
IntPtr temp = CRotPlatformControl.getValue(key);
string res = Marshal.PtrToStringAnsi(temp).ToString();
temp = IntPtr.Zero;
return res;
}
private string setvalue(string strKey,string strValue)
{
IntPtr key = Marshal.StringToHGlobalAnsi(strKey);
IntPtr value = Marshal.StringToHGlobalAnsi(strValue);
IntPtr temp = CRotPlatformControl.setValue(key, value);
string res = Marshal.PtrToStringAnsi(temp).ToString();
temp = IntPtr.Zero;
return res;
}
private void log (string strMsg)
{
ShowMsg(strMsg, Color.Blue);
}
private void error(string strErrMsg)
{
ShowMsg(strErrMsg, Color.Red);
}
private delegate void ShowMsgHandle(string msgString, Color color);
private void ShowMsg(string msgString, Color color)
{
if (!lblMessage.InvokeRequired)
{
lblMessage.Text = msgString;
lblMessage.ForeColor = color;
lblMessage.Refresh();
}
else
{
Invoke(new ShowMsgHandle(ShowMsg), msgString, color);
}
}
}
}
最终结果:
更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。
想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!