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
    }

silverlight5 OOB 直接p/invoke实现串口通信的更多相关文章

  1. C#串口通信

    通过COM1发送数据,COM2接收数据.当COM2接收完本次发送的数据后,向COM1发送信息通知COM1本次数据已发完,COM1接到通知后,再发下一段数据.这样可以确保每次发送的数据都可以被正确接收. ...

  2. 利用 SerialPort 控件实现 PC 串口通信

    整理参考自<Visual C#.NET 串口通信及测控应用典型实例>1.3 节 以及 一篇博文:C# 串口操作系列(1) -- 入门篇,一个标准的,简陋的串口例子. 硬件部分 如果是两个串 ...

  3. 在C#中实现串口通信的方法

    通常,在C#中实现串口通信,我们有四种方法: 第一:通过MSCOMM控件这是最简单的,最方便的方法.可功能上很难做到控制自如,同时这个控件并不是系统本身所带,所以还得注册,不在本文讨论范围.可以访问h ...

  4. C#串口介绍以及简单串口通信程序设计实现

    C#串口介绍以及简单串口通信程序设计实现 周末,没事干,写个简单的串口通信工具,也算是本周末曾来过,废话不多,直接到主题 串口介绍 串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口) ...

  5. C# 编程实现串口通信

    http://blog.sina.com.cn/s/blog_6c67dab30101p3vn.html ----------------------------------------------- ...

  6. C#中缓存的使用 ajax请求基于restFul的WebApi(post、get、delete、put) 让 .NET 更方便的导入导出 Excel .net core api +swagger(一个简单的入门demo 使用codefirst+mysql) C# 位运算详解 c# 交错数组 c# 数组协变 C# 添加Excel表单控件(Form Controls) C#串口通信程序

    C#中缓存的使用   缓存的概念及优缺点在这里就不多做介绍,主要介绍一下使用的方法. 1.在ASP.NET中页面缓存的使用方法简单,只需要在aspx页的顶部加上一句声明即可:  <%@ Outp ...

  7. C#串口通信及数据表格存储

    1.开发环境 系统:win10 开发工具:Visual Studio 2017 2.界面设计 串口通信的界面大致如此,在此基础上添加项目所需的调试指令与数据存储功能,界面排布方面可参考其他教程. 3. ...

  8. C#串口通信程序实现无感知签到与答题

    最近公司项目上线,之前利用串口通讯实现校牌的无感知签到程序, 项目上线以后刚刚好有时间把之前的出现的问题做下记录,废话不多,直接到主题 串口介绍: 串行接口简称串口,也称串行通信接口或串行通讯接口(通 ...

  9. C#实现简单的串口通信

    前言 本着学习研究的态度,用c#语言实现简单的串口通信工具. 一.串口通信原理 串口通信 串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节.尽管比 ...

随机推荐

  1. Codeforces 1091E New Year and the Acquaintance Estimation Erdős–Gallai定理

    题目链接:E - New Year and the Acquaintance Estimation 题解参考: Havel–Hakimi algorithm 和 Erdős–Gallai theore ...

  2. $Django 模板层(变量、过滤器 、标签)、自定义(模板过滤器,标签)

    1 模版语法之变量:详见源码  -{{ 变量 }}:******重要******{#相当于print了该变量#} {#只写函数名 相当于()执行了#}<p>函数:{{ test }}< ...

  3. javascript for循环 日期 select

    2016年12月28日 20:01:54 星期三 html: <a href="aaaa">AAAA</a> <a href="bbbb&q ...

  4. [WebRTC/JsSIP] AUDIO RTP REPORTS ERROR: [Remote Address Error!]

    问题描述: 在使用FreeSWITCH WebRTC 测试时,FS回复  502 Bad Gateway.查看FS日志 [DEBUG] switch_core_media.c:5147 AUDIO R ...

  5. .NET基础之构造函数

    1.构造函数: 分为实例构造函数.静态构造函数.私有构造函数. 使用new表达式创建某个类的对象时, 1.1实例构造函数: (1)构造函数的名字与类名相同: (2)使用new表达式创建类的对象或者结构 ...

  6. 【原创】大数据基础之Logstash(2)应用之mysql-kafka

    应用一:mysql数据增量同步到kafka 1 准备mysql测试表 mysql> create table test_sync(id int not null auto_increment, ...

  7. 36)django-jsonp跨域

    一:什么是JSONP JSONP(JSON with Padding)是JSON的一种"使用模式",可用于解决主流浏览器的跨域数据访问的问题.由于同源策略,一般来说位于 serve ...

  8. 使用WebBrowser控件播放Flash网页相关问题解决方法(转)

    就是写一个类继承WebBrower控件,重写 protected   override   void   WndProc(ref   System.Windows.Forms.Message   m) ...

  9. 姿势摆好,一招学会android的布局优化!

    作为android应用来讲,无论应用本身多么美观,功能多么强大,内容多么丰富.但如果App本身打开界面缓慢超过手机16ms刷新一次页面的时间,就会产生卡顿.用户体验都会变得极差,导致用户量减少.所以我 ...

  10. Confluence 6 用户宏示例 - Formatted Panel

    下面的用演示了如果还写一个用户宏,并在这个宏中创建一个格式化的面板,并且指定颜色.将会创建下面的面板: (Title)   注意:这个面板的标题为空,如果你没有给这个面板标题参数的话. Macro n ...