using System;
using System.Windows.Forms;
using Microsoft.Win32; // for the registry table
using System.Runtime.InteropServices; // for the P/Invoke
namespace WindowsApplication1
{
public partial class Form1 : Form
{
private IntPtr _hDmtDll; // handle of a loaded DLL
private delegate void DelegateClose(int connNum); // function pointer for disconnection
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr LoadLibrary(string dllPath);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool FreeLibrary(IntPtr hDll);
// 数据相关
[DllImport("DMT.dll", CharSet = CharSet.Auto)]
private static extern int RequestData(int commType, int connNum, int slaveAddr, int funcCode, byte[] sendbuf, int sendlen);
[DllImport("DMT.dll", CharSet = CharSet.Auto)]
private static extern int ResponseData(int commType, int connNum, ref int slaveAddr, ref int funcCode, byte[] recvbuf);
// 串口通信
[DllImport("DMT.dll", CharSet = CharSet.Auto)]
private static extern int OpenModbusSerial(int connNum, int baudRate, int dataLen, char parity, int stopBits, int modbusMode);
[DllImport("DMT.dll", CharSet = CharSet.Auto)]
private static extern void CloseSerial(int connNum);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string path = Environment.CurrentDirectory;
path = path.Remove(path.Length - 9);
path = path.Replace("\\", "\\\\");
path = path.Insert(path.Length, "DMT.dll"); // obtain the relative path where the DMT.dll resides
_hDmtDll = LoadLibrary(path); // explicitly link to DMT.dll
var myRegKey = Registry.LocalMachine.OpenSubKey("HARDWARE\\DEVICEMAP\\SERIALCOMM");
if (myRegKey == null) return;
foreach (var valueName in myRegKey.GetValueNames())
{
ComPort.Items.Add(myRegKey.GetValue(valueName)
.ToString());
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
FreeLibrary(_hDmtDll);
}
private void button1_Click_1(object sender, EventArgs e)
{
string strReq = "";
string strRes = "";
ActStatus.Text = "";
int baud_rate = 9600;
int data_len = 7;
char parity = 'E';
int stop_bits = 1;
int modbus_mode = 1; // ASCII
int comm_type = 0; // RS-232
var connNum = Convert.ToInt32(ComPort.Text.Replace("COM", ""));
DelegateClose closeModbus = CloseSerial;
var status = OpenModbusSerial(connNum, baud_rate, data_len, parity, stop_bits, modbus_mode);
if (status == -1)
{
ActStatus.Text = @"串口打开失败";
}
byte[] sendbuf = new byte[1024];
byte[] recvbuf = new byte[1024];
int modbusAddr = 0;
int modbusFunc = 0;
int modbusAddrRet = 0;
int modbusFuncRet = 0;
int sendlen = 0;
int i;
strReq = ReqData.Text;
const string strValid = "0123456789ABCDEF";
if (strReq.Length < 4)
{
ActStatus.Text = @"长度不够";
closeModbus(connNum);
return;
}
if (strReq.Length % 2 != 0)
{
ActStatus.Text = @"发送数据必须为偶数位";
closeModbus(connNum);
return;
}
for (i = 0; i < strReq.Length; i++)
{
if (strValid.IndexOf(strReq.ToUpper()[i]) == -1)
{
ActStatus.Text = @"包含无效数据";
closeModbus(connNum);
return;
}
}
for (i = 0; i <= strReq.Length - 2; i += 2) // 将发送数据放入缓冲区
{
string strConvert = strReq[i] + strReq[i + 1].ToString();
if (i == 0)
modbusAddr = Convert.ToByte(strConvert, 16);
else if (i == 2)
modbusFunc = Convert.ToByte(strConvert, 16);
else
{
sendbuf[sendlen] = Convert.ToByte(strConvert, 16);
sendlen++;
}
}
// 发送数据
int req = RequestData(comm_type, connNum, modbusAddr, modbusFunc, sendbuf, sendlen); // modbus request
if (req == -1)
{
ActStatus.Text = @"数据发送失败";
closeModbus(connNum);
return;
}
// 接收数据
int res = ResponseData(comm_type, connNum, ref modbusAddrRet, ref modbusFuncRet, recvbuf); // modbus response
if (res > 0)
{
strRes += modbusAddrRet.ToString("X2");
strRes += modbusFuncRet.ToString("X2");
switch (modbusFuncRet)
{
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x11:
case 0x17:
strRes += res.ToString("X2");
break;
}
for (i = 0; i < res; i++) // recover a string from recvbuf
{
strRes += recvbuf[i].ToString("X2");
}
ActStatus.Text = @"数据接收完成";
ResData.Text = strRes;
}
else
{
ActStatus.Text = @"未接受到数据";
ResData.Text = "";
}
closeModbus(connNum);
}
}
}