You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
632 lines
22 KiB
632 lines
22 KiB
|
|
using System;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
|
|
namespace TestSerialDLL
|
|
{
|
|
public class SerialWrapper : IDisposable
|
|
{
|
|
#region Enum
|
|
public enum StopBits
|
|
{
|
|
None,
|
|
One,
|
|
Two,
|
|
OnePointFive,
|
|
}
|
|
|
|
public enum Parity
|
|
{
|
|
None,
|
|
Odd,
|
|
Even,
|
|
Mark,
|
|
Space,
|
|
}
|
|
#endregion
|
|
#region Fields
|
|
/// <summary>
|
|
/// The baud rate at which the communications device operates.
|
|
/// </summary>
|
|
private readonly int iBaudRate;
|
|
|
|
/// <summary>
|
|
/// The number of bits in the bytes to be transmitted and received.
|
|
/// </summary>
|
|
private readonly byte byteSize;
|
|
|
|
/// <summary>
|
|
/// The system handle to the serial port connection ('file' handle).
|
|
/// </summary>
|
|
private IntPtr pHandle = IntPtr.Zero;
|
|
|
|
/// <summary>
|
|
/// The parity scheme to be used.
|
|
/// </summary>
|
|
private readonly Parity parity;
|
|
|
|
/// <summary>
|
|
/// The name of the serial port to connect to.
|
|
/// </summary>
|
|
private readonly string sPortName;
|
|
|
|
/// <summary>
|
|
/// The number of bits in the bytes to be transmitted and received.
|
|
/// </summary>
|
|
private readonly StopBits stopBits;
|
|
#endregion
|
|
|
|
#region Constructor
|
|
/// <summary>
|
|
/// Creates a new instance of SerialCom.
|
|
/// </summary>
|
|
/// <param>The name of the serial port to connect to</param>
|
|
/// <param>The baud rate at which the communications device operates</param>
|
|
/// <param>The number of stop bits to be used</param>
|
|
/// <param>The parity scheme to be used</param>
|
|
/// <param>The number of bits in the bytes to be transmitted and received</param>
|
|
public SerialWrapper(string portName, int baudRate, StopBits stopBits, Parity parity, byte byteSize)
|
|
{
|
|
if (stopBits == StopBits.None)
|
|
throw new ArgumentException("stopBits cannot be StopBits.None", "stopBits");
|
|
if (byteSize < 5 || byteSize > 8)
|
|
throw new ArgumentOutOfRangeException("The number of data bits must be 5 to 8 bits.", "byteSize");
|
|
if (baudRate < 110 || baudRate > 256000)
|
|
throw new ArgumentOutOfRangeException("Invalid baud rate specified.", "baudRate");
|
|
if ((byteSize == 5 && stopBits == StopBits.Two) || (stopBits == StopBits.OnePointFive && byteSize > 5))
|
|
throw new ArgumentException("The use of 5 data bits with 2 stop bits is an invalid combination, " +
|
|
"as is 6, 7, or 8 data bits with 1.5 stop bits.");
|
|
|
|
this.sPortName = portName;
|
|
this.iBaudRate = baudRate;
|
|
this.byteSize = byteSize;
|
|
this.stopBits = stopBits;
|
|
this.parity = parity;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new instance of SerialCom.
|
|
/// </summary>
|
|
/// <param>The name of the serial port to connect to</param>
|
|
/// <param>The baud rate at which the communications device operates</param>
|
|
/// <param>The number of stop bits to be used</param>
|
|
/// <param>The parity scheme to be used</param>
|
|
public SerialWrapper(string portName, int baudRate, StopBits stopBits, Parity parity)
|
|
: this(portName, baudRate, stopBits, parity, 8)
|
|
{
|
|
|
|
}
|
|
#endregion
|
|
|
|
#region Open
|
|
/// <summary>
|
|
/// Opens and initializes the serial connection.
|
|
/// </summary>
|
|
/// <returns>Whether or not the operation succeeded</returns>
|
|
public bool Open()
|
|
{
|
|
pHandle = CreateFile(this.sPortName, FileAccess.ReadWrite, FileShare.None,
|
|
IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
|
|
if (pHandle == IntPtr.Zero) return false;
|
|
|
|
if (ConfigureSerialPort()) return true;
|
|
else
|
|
{
|
|
Dispose();
|
|
return false;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Write
|
|
/// <summary>
|
|
/// Transmits the specified array of bytes.
|
|
/// </summary>
|
|
/// <param>The bytes to write</param>
|
|
/// <returns>The number of bytes written (-1 if error)</returns>
|
|
public int Write(byte[] data)
|
|
{
|
|
FailIfNotConnected();
|
|
if (data == null) return 0;
|
|
|
|
int bytesWritten;
|
|
if (WriteFile(pHandle, data, data.Length, out bytesWritten, 0))
|
|
return bytesWritten;
|
|
return -1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Transmits the specified string.
|
|
/// </summary>
|
|
/// <param>The string to write</param>
|
|
/// <returns>The number of bytes written (-1 if error)</returns>
|
|
public int Write(string data)
|
|
{
|
|
FailIfNotConnected();
|
|
|
|
// convert the string to bytes
|
|
byte[] bytes;
|
|
if (data == null)
|
|
{
|
|
bytes = null;
|
|
}
|
|
else
|
|
{
|
|
bytes = Encoding.UTF8.GetBytes(data);
|
|
}
|
|
|
|
return Write(bytes);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Transmits the specified string and appends the carriage return to the end
|
|
/// if it does not exist.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Note that the string must end in '\r\n' before any serial device will interpret the data
|
|
/// sent. For ease of programmability, this method should be used instead of Write() when you
|
|
/// want to automatically execute the specified command string.
|
|
/// </remarks>
|
|
/// <param>The string to write</param>
|
|
/// <returns>The number of bytes written (-1 if error)</returns>
|
|
public int WriteLine(string data)
|
|
{
|
|
if (data != null && !data.EndsWith("\r\n"))
|
|
data += "\r\n";
|
|
return Write(data);
|
|
}
|
|
#endregion
|
|
|
|
#region Read
|
|
/// <summary>
|
|
/// Reads any bytes that have been received and writes them to the specified array.
|
|
/// </summary>
|
|
/// <param>The array to write the read data to</param>
|
|
/// <returns>The number of bytes read (-1 if error)</returns>
|
|
public int Read(byte[] data)
|
|
{
|
|
FailIfNotConnected();
|
|
if (data == null) return 0;
|
|
|
|
int bytesRead;
|
|
if (ReadFile(pHandle, data, data.Length, out bytesRead, 0))
|
|
return bytesRead;
|
|
return -1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads any data that has been received as a string.
|
|
/// </summary>
|
|
/// <param>The maximum number of bytes to read</param>
|
|
/// <returns>The data received (null if no data)</returns>
|
|
public string ReadString(int maxBytesToRead)
|
|
{
|
|
if (maxBytesToRead < 1) throw new ArgumentOutOfRangeException("maxBytesToRead");
|
|
|
|
byte[] bytes = new byte[maxBytesToRead];
|
|
int numBytes = Read(bytes);
|
|
//string data = ASCIIEncoding.ASCII.GetString(bytes, 0, numBytes);
|
|
string data = Encoding.UTF8.GetString(bytes, 0, numBytes);
|
|
return data;
|
|
}
|
|
#endregion
|
|
|
|
#region Dispose Utils
|
|
/// <summary>
|
|
/// Disconnects and disposes of the SerialCom instance.
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
if (pHandle != IntPtr.Zero)
|
|
{
|
|
CloseHandle(pHandle);
|
|
pHandle = IntPtr.Zero;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Flushes the serial I/O buffers.
|
|
/// </summary>
|
|
/// <returns>Whether or not the operation succeeded</returns>
|
|
public bool Flush()
|
|
{
|
|
FailIfNotConnected();
|
|
|
|
const int PURGE_RXCLEAR = 0x0008; // input buffer
|
|
const int PURGE_TXCLEAR = 0x0004; // output buffer
|
|
return PurgeComm(pHandle, PURGE_RXCLEAR | PURGE_TXCLEAR);
|
|
}
|
|
#endregion
|
|
|
|
#region Private Helpers
|
|
/// <summary>
|
|
/// Configures the serial device based on the connection parameters pased in by the user.
|
|
/// </summary>
|
|
/// <returns>Whether or not the operation succeeded</returns>
|
|
private bool ConfigureSerialPort()
|
|
{
|
|
DCB serialConfig = new DCB();
|
|
if (GetCommState(pHandle, ref serialConfig))
|
|
{
|
|
// setup the DCB struct with the serial settings we need
|
|
serialConfig.BaudRate = (uint)this.iBaudRate;
|
|
serialConfig.ByteSize = this.byteSize;
|
|
serialConfig.fBinary = 1; // must be true
|
|
serialConfig.fDtrControl = 1; // DTR_CONTROL_ENABLE "Enables the DTR line when the device is opened and leaves it on."
|
|
serialConfig.fAbortOnError = 0; // false
|
|
serialConfig.fTXContinueOnXoff = 0; // false
|
|
|
|
serialConfig.fParity = 1; // true so that the Parity member is looked at
|
|
switch (this.parity)
|
|
{
|
|
case Parity.Even:
|
|
serialConfig.Parity = 2;
|
|
break;
|
|
case Parity.Mark:
|
|
serialConfig.Parity = 3;
|
|
break;
|
|
case Parity.Odd:
|
|
serialConfig.Parity = 1;
|
|
break;
|
|
case Parity.Space:
|
|
serialConfig.Parity = 4;
|
|
break;
|
|
case Parity.None:
|
|
default:
|
|
serialConfig.Parity = 0;
|
|
break;
|
|
}
|
|
switch (this.stopBits)
|
|
{
|
|
case StopBits.One:
|
|
serialConfig.StopBits = 0;
|
|
break;
|
|
case StopBits.OnePointFive:
|
|
serialConfig.StopBits = 1;
|
|
break;
|
|
case StopBits.Two:
|
|
serialConfig.StopBits = 2;
|
|
break;
|
|
case StopBits.None:
|
|
default:
|
|
throw new ArgumentException("stopBits cannot be StopBits.None");
|
|
}
|
|
|
|
if (SetCommState(pHandle, ref serialConfig))
|
|
{
|
|
// set the serial connection timeouts
|
|
COMMTIMEOUTS timeouts = new COMMTIMEOUTS();
|
|
timeouts.ReadIntervalTimeout = 1;
|
|
timeouts.ReadTotalTimeoutMultiplier = 0;
|
|
timeouts.ReadTotalTimeoutConstant = 0;
|
|
timeouts.WriteTotalTimeoutMultiplier = 0;
|
|
timeouts.WriteTotalTimeoutConstant = 0;
|
|
if (SetCommTimeouts(pHandle, ref timeouts))
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Helper that throws a InvalidOperationException if we don't have a serial connection.
|
|
/// </summary>
|
|
private void FailIfNotConnected()
|
|
{
|
|
if (pHandle == IntPtr.Zero)
|
|
throw new InvalidOperationException("You must be connected to the serial port before performing this operation.");
|
|
}
|
|
#endregion
|
|
|
|
#region Native Helpers
|
|
#region Native structures
|
|
/// <summary>
|
|
/// Contains the time-out parameters for a communications device.
|
|
/// </summary>
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
struct COMMTIMEOUTS
|
|
{
|
|
public uint ReadIntervalTimeout;
|
|
public uint ReadTotalTimeoutMultiplier;
|
|
public uint ReadTotalTimeoutConstant;
|
|
public uint WriteTotalTimeoutMultiplier;
|
|
public uint WriteTotalTimeoutConstant;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Defines the control setting for a serial communications device.
|
|
/// </summary>
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
struct DCB
|
|
{
|
|
public int DCBlength;
|
|
public uint BaudRate;
|
|
public uint Flags;
|
|
public ushort wReserved;
|
|
public ushort XonLim;
|
|
public ushort XoffLim;
|
|
public byte ByteSize;
|
|
public byte Parity;
|
|
public byte StopBits;
|
|
public sbyte XonChar;
|
|
public sbyte XoffChar;
|
|
public sbyte ErrorChar;
|
|
public sbyte EofChar;
|
|
public sbyte EvtChar;
|
|
public ushort wReserved1;
|
|
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;
|
|
}
|
|
#endregion
|
|
|
|
#region Native Methods
|
|
// Used to get a handle to the serial port so that we can read/write to it.
|
|
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
|
static extern IntPtr CreateFile(string fileName,
|
|
[MarshalAs(UnmanagedType.U4)] FileAccess fileAccess,
|
|
[MarshalAs(UnmanagedType.U4)] FileShare fileShare,
|
|
IntPtr securityAttributes,
|
|
[MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
|
|
int flags,
|
|
IntPtr template);
|
|
|
|
// Used to close the handle to the serial port.
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern bool CloseHandle(IntPtr hObject);
|
|
|
|
// Used to get the state of the serial port so that we can configure it.
|
|
[DllImport("kernel32.dll")]
|
|
static extern bool GetCommState(IntPtr hFile, ref DCB lpDCB);
|
|
|
|
// Used to configure the serial port.
|
|
[DllImport("kernel32.dll")]
|
|
static extern bool SetCommState(IntPtr hFile, [In] ref DCB lpDCB);
|
|
|
|
// Used to set the connection timeouts on our serial connection.
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern bool SetCommTimeouts(IntPtr hFile, ref COMMTIMEOUTS lpCommTimeouts);
|
|
|
|
// Used to read bytes from the serial connection.
|
|
[DllImport("kernel32.dll")]
|
|
static extern bool ReadFile(IntPtr hFile, byte[] lpBuffer,
|
|
int nNumberOfBytesToRead, out int lpNumberOfBytesRead, int lpOverlapped);
|
|
|
|
// Used to write bytes to the serial connection.
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern bool WriteFile(IntPtr hFile, byte[] lpBuffer,
|
|
int nNumberOfBytesToWrite, out int lpNumberOfBytesWritten, int lpOverlapped);
|
|
|
|
// Used to flush the I/O buffers.
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern bool PurgeComm(IntPtr hFile, int dwFlags);
|
|
#endregion
|
|
#endregion
|
|
}
|
|
}
|
|
// using System;
|
|
// using System.Collections.Generic;
|
|
// using System.Linq;
|
|
// using System.Runtime.InteropServices;
|
|
// using System.Text;
|
|
// using System;
|
|
// using System.IO.Ports;
|
|
// using System.Threading;
|
|
//
|
|
// namespace Scale
|
|
// {
|
|
// // Use this code inside a project created with the Visual C# > Windows Desktop > Console Application template.
|
|
// // Replace the code in Program.cs with this code.
|
|
//
|
|
//
|
|
// public class PortChat
|
|
// {
|
|
// static bool _continue;
|
|
// static SerialPort _serialPort;
|
|
//
|
|
// public static void Main()
|
|
// {
|
|
// string name;
|
|
// string message;
|
|
// StringComparer stringComparer = StringComparer.OrdinalIgnoreCase;
|
|
// Thread readThread = new Thread(Read);
|
|
//
|
|
// // Create a new SerialPort object with default settings.
|
|
// _serialPort = new SerialPort();
|
|
//
|
|
// // Allow the user to set the appropriate properties.
|
|
// _serialPort.PortName = SetPortName(_serialPort.PortName);
|
|
// _serialPort.BaudRate = SetPortBaudRate(_serialPort.BaudRate);
|
|
// _serialPort.Parity = SetPortParity(_serialPort.Parity);
|
|
// _serialPort.DataBits = SetPortDataBits(_serialPort.DataBits);
|
|
// _serialPort.StopBits = SetPortStopBits(_serialPort.StopBits);
|
|
// _serialPort.Handshake = SetPortHandshake(_serialPort.Handshake);
|
|
//
|
|
// // Set the read/write timeouts
|
|
// _serialPort.ReadTimeout = 500;
|
|
// _serialPort.WriteTimeout = 500;
|
|
//
|
|
// _serialPort.Open();
|
|
// _continue = true;
|
|
// readThread.Start();
|
|
//
|
|
// Console.Write("Name: ");
|
|
// name = Console.ReadLine();
|
|
//
|
|
// Console.WriteLine("Type QUIT to exit");
|
|
//
|
|
// while (_continue)
|
|
// {
|
|
// message = Console.ReadLine();
|
|
//
|
|
// if (stringComparer.Equals("quit", message))
|
|
// {
|
|
// _continue = false;
|
|
// }
|
|
// else
|
|
// {
|
|
// _serialPort.WriteLine(
|
|
// String.Format("<{0}>: {1}", name, message));
|
|
// }
|
|
// }
|
|
//
|
|
// readThread.Join();
|
|
// _serialPort.Close();
|
|
// }
|
|
//
|
|
// public static void Read()
|
|
// {
|
|
// while (_continue)
|
|
// {
|
|
// try
|
|
// {
|
|
// string message = _serialPort.ReadLine();
|
|
// Console.WriteLine(message);
|
|
// }
|
|
// catch (TimeoutException) { }
|
|
// }
|
|
// }
|
|
//
|
|
// // Display Port values and prompt user to enter a port.
|
|
// public static string SetPortName(string defaultPortName)
|
|
// {
|
|
// string portName;
|
|
//
|
|
// Console.WriteLine("Available Ports:");
|
|
// foreach (string s in SerialPort.GetPortNames())
|
|
// {
|
|
// Console.WriteLine(" {0}", s);
|
|
// }
|
|
//
|
|
// Console.Write("Enter COM port value (Default: {0}): ", defaultPortName);
|
|
// portName = Console.ReadLine();
|
|
//
|
|
// if (portName == "" || !(portName.ToLower()).StartsWith("com"))
|
|
// {
|
|
// portName = defaultPortName;
|
|
// }
|
|
// return portName;
|
|
// }
|
|
// // Display BaudRate values and prompt user to enter a value.
|
|
// public static int SetPortBaudRate(int defaultPortBaudRate)
|
|
// {
|
|
// string baudRate;
|
|
//
|
|
// Console.Write("Baud Rate(default:{0}): ", defaultPortBaudRate);
|
|
// baudRate = Console.ReadLine();
|
|
//
|
|
// if (baudRate == "")
|
|
// {
|
|
// baudRate = defaultPortBaudRate.ToString();
|
|
// }
|
|
//
|
|
// return int.Parse(baudRate);
|
|
// }
|
|
//
|
|
// // Display PortParity values and prompt user to enter a value.
|
|
// public static Parity SetPortParity(Parity defaultPortParity)
|
|
// {
|
|
// string parity;
|
|
//
|
|
// Console.WriteLine("Available Parity options:");
|
|
// foreach (string s in Enum.GetNames(typeof(Parity)))
|
|
// {
|
|
// Console.WriteLine(" {0}", s);
|
|
// }
|
|
//
|
|
// Console.Write("Enter Parity value (Default: {0}):", defaultPortParity.ToString(), true);
|
|
// parity = Console.ReadLine();
|
|
//
|
|
// if (parity == "")
|
|
// {
|
|
// parity = defaultPortParity.ToString();
|
|
// }
|
|
//
|
|
// return (Parity)Enum.Parse(typeof(Parity), parity, true);
|
|
// }
|
|
// // Display DataBits values and prompt user to enter a value.
|
|
// public static int SetPortDataBits(int defaultPortDataBits)
|
|
// {
|
|
// string dataBits;
|
|
//
|
|
// Console.Write("Enter DataBits value (Default: {0}): ", defaultPortDataBits);
|
|
// dataBits = Console.ReadLine();
|
|
//
|
|
// if (dataBits == "")
|
|
// {
|
|
// dataBits = defaultPortDataBits.ToString();
|
|
// }
|
|
//
|
|
// return int.Parse(dataBits.ToUpperInvariant());
|
|
// }
|
|
//
|
|
// // Display StopBits values and prompt user to enter a value.
|
|
// public static StopBits SetPortStopBits(StopBits defaultPortStopBits)
|
|
// {
|
|
// string stopBits;
|
|
//
|
|
// Console.WriteLine("Available StopBits options:");
|
|
// foreach (string s in Enum.GetNames(typeof(StopBits)))
|
|
// {
|
|
// Console.WriteLine(" {0}", s);
|
|
// }
|
|
//
|
|
// Console.Write("Enter StopBits value (None is not supported and \n" +
|
|
// "raises an ArgumentOutOfRangeException. \n (Default: {0}):", defaultPortStopBits.ToString());
|
|
// stopBits = Console.ReadLine();
|
|
//
|
|
// if (stopBits == "")
|
|
// {
|
|
// stopBits = defaultPortStopBits.ToString();
|
|
// }
|
|
//
|
|
// return (StopBits)Enum.Parse(typeof(StopBits), stopBits, true);
|
|
// }
|
|
// public static Handshake SetPortHandshake(Handshake defaultPortHandshake)
|
|
// {
|
|
// string handshake;
|
|
//
|
|
// Console.WriteLine("Available Handshake options:");
|
|
// foreach (string s in Enum.GetNames(typeof(Handshake)))
|
|
// {
|
|
// Console.WriteLine(" {0}", s);
|
|
// }
|
|
//
|
|
// Console.Write("Enter Handshake value (Default: {0}):", defaultPortHandshake.ToString());
|
|
// handshake = Console.ReadLine();
|
|
//
|
|
// if (handshake == "")
|
|
// {
|
|
// handshake = defaultPortHandshake.ToString();
|
|
// }
|
|
//
|
|
// return (Handshake)Enum.Parse(typeof(Handshake), handshake, true);
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
|