USB NetPower 8800 SDK 從 C++ 轉成 C# - Part 2
今天繼續USB NetPower 8800 SDK 從 C++ 轉成 C# - Part 1未完成的工作,先用 Google尋找一下有關PL2303的資料,結果找到了這一家萬平科技網,這家公司主要是提供 USB to(轉) Serial(UART/TTL/RS232/RS485)的應用開發工具,這家的網路上有提供PL2303 HXD原廠的4 * GPIO sample code及使用手冊,下載 sample code 並執行 PL2303 4 GPIO Test.exe,畫面如下:
很順利開啟連接埠,接著試用 GP0 及 GP1 等功能,發現 Net Power 只有用到 GP1,當 GP1 的值設成是 1 時插座供電,設成0時插座斷電:
測到這我已經大概了解 C++ 對這 NetPower 所作的動作,現在就要來把 C++ 改成 C#
,這裡我是用 CreateFile 的 方式,由於 C# 已經不像 C++ 有提供 CreateFile 所以要用 Dllimport
:
[DllImport("kernel32.dll")]
private static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess,
int dwShareMode,
IntPtr lpSecurityAttributes,
int dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile
);
使用如下:
pl2303 = CreateFile("COM8",
GENERIC_READ | GENERIC_WRITE,
0,
IntPtr.Zero,
OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
IntPtr.Zero);
由於 C# 也沒有 define 要把原有 C++中的 define 改成:
public const uint GENERIC_READ = 0x80000000;
public const uint GENERIC_WRITE = 0x40000000;
public const int OPEN_EXISTING = 3;
在來是要改 DeviceIoControl:
[DllImport("kernel32.dll", EntryPoint = "DeviceIoControl", SetLastError = true)]
internal static extern bool DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
ref byte lpInBuffer,
uint nInBufferSize,
ref byte lpOutBuffer,
int nOutBufferSize,
ref uint lpBytesReturned,
IntPtr lpOverlapped);
原有在 C++ 中定義的 CTL_CODE也要改成 function 的型態:
static uint CTL_CODE(uint DeviceType, uint Function, uint Method, uint Access)
{
return ((DeviceType << 16) | (Access << 14) | (Function << 2) | Method);
}
同樣的也要宣告:
private const uint FILE_FLAG_OVERLAPPED = 0x40000000;
private const uint FILE_DEVICE_UNKNOWN = 0x00000022;
private const uint FILE_ATTRIBUTE_SYSTEM = 0x00000004;
private const uint USB2SER_IOCTL_INDEX = 0x0800;
private const uint METHOD_BUFFERED = 0;
private const uint FILE_ANY_ACCESS = 0;
DeviceIoControl 在 C# 中的用法如下:
uint GP1_SET_VALUE = CTL_CODE(FILE_DEVICE_UNKNOWN, USB2SER_IOCTL_INDEX + 23, METHOD_BUFFERED, FILE_ANY_ACCESS);
bool bSuccess = DeviceIoControl(hDrv, GP1_SET_VALUE, ref val, sizeof(byte), ref dummybyte,
0,
ref nBytes,
IntPtr.Zero);
因為時間有限,所以我只改了設定GP1:
GP1_SetValue
GP1_GetValue
GP1_Enable
我改好的 C# 程式執行畫面如下:
完整的程式如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public const int FILE_ATTRIBUTE_NORMAL = 0x00000080;
public const uint GENERIC_READ = 0x80000000;
public const uint GENERIC_WRITE = 0x40000000;
public const int OPEN_EXISTING = 3;
// public const UInt32 INVALID_HANDLE_VALUE = 0xffffffff;
private const uint FILE_FLAG_OVERLAPPED = 0x40000000;
private const uint FILE_DEVICE_UNKNOWN = 0x00000022;
private const uint FILE_ATTRIBUTE_SYSTEM = 0x00000004;
private const uint USB2SER_IOCTL_INDEX = 0x0800;
private const uint METHOD_BUFFERED = 0;
private const uint FILE_ANY_ACCESS = 0;
public Form1()
{
InitializeComponent();
}
IntPtr pl2303 = (IntPtr)(-1);
static uint CTL_CODE(uint DeviceType, uint Function, uint Method, uint Access)
{
return ((DeviceType << 16) | (Access << 14) | (Function << 2) | Method);
}
private void button1_Click(object sender, EventArgs e)
{
if (pl2303 == (IntPtr)(-1))
{
pl2303 = CreateFile("COM8",
GENERIC_READ | GENERIC_WRITE,
0,
IntPtr.Zero,
OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
IntPtr.Zero);
button1.Text = "關閉通訊埠";
}
else
{
CloseHandle(pl2303);
button1.Text = "開啟通訊埠";
pl2303 = (IntPtr)(-1);
}
}
private void button2_Click(object sender, EventArgs e)
{
if (pl2303 != (IntPtr)(-1))
{ // pl2303 open success
byte val = 0;
if (PL2303_GP1_GetValue(pl2303, ref val))
{
// button2.Text = val.ToString();
if (val == 0)
{
if (PL2303_GP1_Enable(pl2303))
{
if (PL2303_GP1_SetValue(pl2303, 1))
{
button2.Text = "插座断電";
}
}
else
{
MessageBox.Show("enable fail");
}
}
else
{
if (PL2303_GP1_Enable(pl2303))
{
if (PL2303_GP1_SetValue(pl2303, 0))
{
button2.Text = "插座通電";
}
}
else
{
MessageBox.Show("enable fail");
}
}
}
}
else
{
MessageBox.Show("通訊埠尚未開啟");
}
}
private bool PL2303_GP1_SetValue(IntPtr hDrv, byte val)
{
uint nBytes = 0;
byte dummybyte = 0;
uint GP1_SET_VALUE = CTL_CODE(FILE_DEVICE_UNKNOWN, USB2SER_IOCTL_INDEX + 23, METHOD_BUFFERED, FILE_ANY_ACCESS);
bool bSuccess = DeviceIoControl(hDrv, GP1_SET_VALUE, ref val, sizeof(byte), ref dummybyte,
0,
ref nBytes,
IntPtr.Zero);
return bSuccess;
}
private bool PL2303_GP1_GetValue(IntPtr hDrv, ref byte val)
{
uint nBytes = 0;
byte dummybyte = 0;
uint GP1_GET_VALUE = CTL_CODE(FILE_DEVICE_UNKNOWN, USB2SER_IOCTL_INDEX + 25, METHOD_BUFFERED, FILE_ANY_ACCESS);
bool bSuccess = DeviceIoControl(hDrv, GP1_GET_VALUE, ref dummybyte, 0, ref val,
sizeof(byte),
ref nBytes,
IntPtr.Zero);
return bSuccess;
}
private bool PL2303_GP1_Enable(IntPtr hDrv)
{
uint nBytes = 0;
byte enable = 1;
byte dummybyte = 0;
uint GP1_OUTPUT_ENABLE = CTL_CODE(FILE_DEVICE_UNKNOWN, USB2SER_IOCTL_INDEX + 21, METHOD_BUFFERED, FILE_ANY_ACCESS);
bool bSuccess = DeviceIoControl(hDrv, GP1_OUTPUT_ENABLE, ref enable, sizeof(byte), ref dummybyte,
0,
ref nBytes,
IntPtr.Zero);
return bSuccess;
}
[DllImport("kernel32.dll")]
private static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess,
int dwShareMode,
IntPtr lpSecurityAttributes,
int dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile
);
[DllImport("kernel32.dll", EntryPoint = "DeviceIoControl", SetLastError = true)]
internal static extern bool DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
ref byte lpInBuffer,
uint nInBufferSize,
ref byte lpOutBuffer,
int nOutBufferSize,
ref uint lpBytesReturned,
IntPtr lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);
}
}
PL-2303 4 GPIO Test |
測試 GP0 及 GP1 |
,這裡我是用 CreateFile 的 方式,由於 C# 已經不像 C++ 有提供 CreateFile 所以要用 Dllimport
:
[DllImport("kernel32.dll")]
private static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess,
int dwShareMode,
IntPtr lpSecurityAttributes,
int dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile
);
使用如下:
pl2303 = CreateFile("COM8",
GENERIC_READ | GENERIC_WRITE,
0,
IntPtr.Zero,
OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
IntPtr.Zero);
由於 C# 也沒有 define 要把原有 C++中的 define 改成:
public const uint GENERIC_READ = 0x80000000;
public const uint GENERIC_WRITE = 0x40000000;
public const int OPEN_EXISTING = 3;
在來是要改 DeviceIoControl:
[DllImport("kernel32.dll", EntryPoint = "DeviceIoControl", SetLastError = true)]
internal static extern bool DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
ref byte lpInBuffer,
uint nInBufferSize,
ref byte lpOutBuffer,
int nOutBufferSize,
ref uint lpBytesReturned,
IntPtr lpOverlapped);
原有在 C++ 中定義的 CTL_CODE也要改成 function 的型態:
static uint CTL_CODE(uint DeviceType, uint Function, uint Method, uint Access)
{
return ((DeviceType << 16) | (Access << 14) | (Function << 2) | Method);
}
同樣的也要宣告:
private const uint FILE_FLAG_OVERLAPPED = 0x40000000;
private const uint FILE_DEVICE_UNKNOWN = 0x00000022;
private const uint FILE_ATTRIBUTE_SYSTEM = 0x00000004;
private const uint USB2SER_IOCTL_INDEX = 0x0800;
private const uint METHOD_BUFFERED = 0;
private const uint FILE_ANY_ACCESS = 0;
DeviceIoControl 在 C# 中的用法如下:
uint GP1_SET_VALUE = CTL_CODE(FILE_DEVICE_UNKNOWN, USB2SER_IOCTL_INDEX + 23, METHOD_BUFFERED, FILE_ANY_ACCESS);
bool bSuccess = DeviceIoControl(hDrv, GP1_SET_VALUE, ref val, sizeof(byte), ref dummybyte,
0,
ref nBytes,
IntPtr.Zero);
因為時間有限,所以我只改了設定GP1:
GP1_SetValue
GP1_GetValue
GP1_Enable
我改好的 C# 程式執行畫面如下:
C# for USB Netpower |
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public const int FILE_ATTRIBUTE_NORMAL = 0x00000080;
public const uint GENERIC_READ = 0x80000000;
public const uint GENERIC_WRITE = 0x40000000;
public const int OPEN_EXISTING = 3;
// public const UInt32 INVALID_HANDLE_VALUE = 0xffffffff;
private const uint FILE_FLAG_OVERLAPPED = 0x40000000;
private const uint FILE_DEVICE_UNKNOWN = 0x00000022;
private const uint FILE_ATTRIBUTE_SYSTEM = 0x00000004;
private const uint USB2SER_IOCTL_INDEX = 0x0800;
private const uint METHOD_BUFFERED = 0;
private const uint FILE_ANY_ACCESS = 0;
public Form1()
{
InitializeComponent();
}
IntPtr pl2303 = (IntPtr)(-1);
static uint CTL_CODE(uint DeviceType, uint Function, uint Method, uint Access)
{
return ((DeviceType << 16) | (Access << 14) | (Function << 2) | Method);
}
private void button1_Click(object sender, EventArgs e)
{
if (pl2303 == (IntPtr)(-1))
{
pl2303 = CreateFile("COM8",
GENERIC_READ | GENERIC_WRITE,
0,
IntPtr.Zero,
OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
IntPtr.Zero);
button1.Text = "關閉通訊埠";
}
else
{
CloseHandle(pl2303);
button1.Text = "開啟通訊埠";
pl2303 = (IntPtr)(-1);
}
}
private void button2_Click(object sender, EventArgs e)
{
if (pl2303 != (IntPtr)(-1))
{ // pl2303 open success
byte val = 0;
if (PL2303_GP1_GetValue(pl2303, ref val))
{
// button2.Text = val.ToString();
if (val == 0)
{
if (PL2303_GP1_Enable(pl2303))
{
if (PL2303_GP1_SetValue(pl2303, 1))
{
button2.Text = "插座断電";
}
}
else
{
MessageBox.Show("enable fail");
}
}
else
{
if (PL2303_GP1_Enable(pl2303))
{
if (PL2303_GP1_SetValue(pl2303, 0))
{
button2.Text = "插座通電";
}
}
else
{
MessageBox.Show("enable fail");
}
}
}
}
else
{
MessageBox.Show("通訊埠尚未開啟");
}
}
private bool PL2303_GP1_SetValue(IntPtr hDrv, byte val)
{
uint nBytes = 0;
byte dummybyte = 0;
uint GP1_SET_VALUE = CTL_CODE(FILE_DEVICE_UNKNOWN, USB2SER_IOCTL_INDEX + 23, METHOD_BUFFERED, FILE_ANY_ACCESS);
bool bSuccess = DeviceIoControl(hDrv, GP1_SET_VALUE, ref val, sizeof(byte), ref dummybyte,
0,
ref nBytes,
IntPtr.Zero);
return bSuccess;
}
private bool PL2303_GP1_GetValue(IntPtr hDrv, ref byte val)
{
uint nBytes = 0;
byte dummybyte = 0;
uint GP1_GET_VALUE = CTL_CODE(FILE_DEVICE_UNKNOWN, USB2SER_IOCTL_INDEX + 25, METHOD_BUFFERED, FILE_ANY_ACCESS);
bool bSuccess = DeviceIoControl(hDrv, GP1_GET_VALUE, ref dummybyte, 0, ref val,
sizeof(byte),
ref nBytes,
IntPtr.Zero);
return bSuccess;
}
private bool PL2303_GP1_Enable(IntPtr hDrv)
{
uint nBytes = 0;
byte enable = 1;
byte dummybyte = 0;
uint GP1_OUTPUT_ENABLE = CTL_CODE(FILE_DEVICE_UNKNOWN, USB2SER_IOCTL_INDEX + 21, METHOD_BUFFERED, FILE_ANY_ACCESS);
bool bSuccess = DeviceIoControl(hDrv, GP1_OUTPUT_ENABLE, ref enable, sizeof(byte), ref dummybyte,
0,
ref nBytes,
IntPtr.Zero);
return bSuccess;
}
[DllImport("kernel32.dll")]
private static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess,
int dwShareMode,
IntPtr lpSecurityAttributes,
int dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile
);
[DllImport("kernel32.dll", EntryPoint = "DeviceIoControl", SetLastError = true)]
internal static extern bool DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
ref byte lpInBuffer,
uint nInBufferSize,
ref byte lpOutBuffer,
int nOutBufferSize,
ref uint lpBytesReturned,
IntPtr lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);
}
}
留言
張貼留言
請多指教