using System;
using System.Runtime.InteropServices;
using System.Text;
namespace serier
{
class SerialPortAPI
{
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool WriteFile(
IntPtr hFile,
byte[] lpBuffer,
uint nNumberOfBytesToWrite,
out uint lpNumberOfBytesWritten,
IntPtr lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool ReadFile(
IntPtr hFile,
byte[] lpBuffer,
uint nNumberOfBytesToRead,
out uint lpNumberOfBytesRead,
IntPtr lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hObject);
// ... 其他需要的API声明
[StructLayout(LayoutKind.Sequential)]
private struct DCB
{
public uint DCBlength;
public uint BaudRate;
public uint fBinary;
public uint fParity;
public uint fOutxCtsFlow;
public uint fOutxDsrFlow;
public uint fDtrControl;
public uint fDsrSensitivity;
public uint fTXContinueOnXoff;
public uint fOutX;
public uint fInX;
public uint fErrorChar;
public uint fNull;
public uint fRtsControl;
public uint fAbortOnError;
public uint fDummy2;
public byte wReserved;
public ushort XonLim;
public ushort XoffLim;
public byte ByteSize;
public byte Parity;
public byte StopBits;
public char XonChar;
public char XoffChar;
public char ErrorChar;
public char EofChar;
public char EvtChar;
public ushort wReserved1;
}
// ... 其他API函数声明 ...
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool GetCommState(IntPtr hFile, ref DCB lpDCB);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetCommState(IntPtr hFile, ref DCB lpDCB);
// ...
private void ConfigureSerialPort(IntPtr hSerial, uint baudRate, byte dataBits, Parity parity, StopBits stopBits)
{
DCB dcb = new DCB
{
DCBlength = (uint)Marshal.SizeOf(typeof(DCB)),
BaudRate = baudRate,
ByteSize = dataBits,
StopBits = (byte)stopBits,
Parity = (byte)parity
};
dcb.fBinary = 1; // Binary mode; no EOF check
dcb.fParity = (byte)(parity /*!= Parity.None*/);
if (!GetCommState(hSerial, ref dcb))
{
throw new InvalidOperationException("Failed to get serial port state");
}
// 这里没有修改其他不需要改变的位,直接设置新的值
if (!SetCommState(hSerial, ref dcb))
{
throw new InvalidOperationException("Failed to set serial port state");
}
}
// 枚举类型,用于简化Parity和StopBits的指定
private enum Parity
{
None = 0,
Odd = 1,
Even = 2,
Mark = 3,
Space = 4
}
private enum StopBits
{
One = 0,
OnePointFive = 1, // 注意:Windows API通常不支持1.5停止位
Two = 2
}
// ... 其他方法 ...
IntPtr _IntPtr;
public void Open(string portName, uint baudRate)
{
_IntPtr = OpenSerialPort(portName, baudRate);
Task.Run(() => { test(); });
}
public IntPtr OpenSerialPort(string portName, uint baudRate)
{
string port = $"\\\\.\\{portName}";
uint dwFlagsAndAttributes = 0x80000000; // FILE_FLAG_OVERLAPPED
IntPtr hSerial = CreateFile(port,
0xC0000000, // GENERIC_READ | GENERIC_WRITE
0,
IntPtr.Zero,
3, // OPEN_EXISTING
dwFlagsAndAttributes,
IntPtr.Zero);
if (hSerial == IntPtr.Zero)
{
throw new InvalidOperationException("Failed to open serial port");
}
ConfigureSerialPort(hSerial, baudRate,8,0,0);
// 设置串口参数(这里简单示例,实际可能需要调用其他API设置)
// 例如:DCB结构体设置,需要P/Invoke SetCommState
return hSerial;
}
public delegate void readd(string x);
public readd DoOnRead;
public void test()
{
while (true)
{
string x= ReadFromSerialPort(_IntPtr, 1024);
if (x.Length>0)
{
DoOnRead?.Invoke(x);
}
Thread.Sleep(2);
}
}
public void WriteToSerialPort(IntPtr hSerial, string text)
{
byte[] buffer = Encoding.ASCII.GetBytes(text);
uint bytesWritten;
if (!WriteFile(hSerial, buffer, (uint)buffer.Length, out bytesWritten, IntPtr.Zero))
{
throw new InvalidOperationException("Failed to write to serial port");
}
}
public string ReadFromSerialPort(IntPtr hSerial, uint bufferSize)
{
byte[] buffer = new byte[bufferSize];
uint bytesRead;
if (!ReadFile(hSerial, buffer, bufferSize, out bytesRead, IntPtr.Zero))
{
throw new InvalidOperationException("Failed to read from serial port");
}
return Encoding.ASCII.GetString(buffer, 0, (int)bytesRead);
}
private void CloseSerialPort(IntPtr hSerial)
{
if (hSerial != IntPtr.Zero)
{
CloseHandle(hSerial);
}
}
}
}