首页  ·  知识 ·  云计算
NET平台下通用的串口操作类
佚名  http://aspxboy.com/private/5530/default.aspx  综合  编辑:dezai  图片来源:网络
Author: swnuwangyun From: swnuwangyun1. 动机应用程序开发语言为C# 应用程序要求既能在PDA上运行,又能在PC上运行,具备良好

Author: swnuwangyun
From: swnuwangyun
1.   动机
应用程序开发语言为C#
应用程序要求既能在PDA上运行,又能在PC上运行,具备良好的兼容性
应用程序要求尽可能多的兼容不同PDA上的红外线设备
.net自带的SerialPort在HP某型号PDA上操作红外线设备时,只能接受,不能发射
2.   目标
具备良好的兼容性,既能够在PC上运行也能够在PDA上运行。
挡在PDA上运行时,尽可能多的兼容红外设备。
3.   局限性
单线程
仅提供send/receive模式的接口,无事件驱动机制
4.   关键技术问题及典型测试案例
最关键的是对EscapeCommFunction的调用,当串口为红外设备时,必须调用此函数才能确保串口工作正常。当串口为一般的COM口时,出于兼容性的考虑,切勿调用此函数。

在HP某PDA上测试时,不管串口是否为红外设备,均调用此函数启用红外功能,均能够工作正常。
在SIEMENS某PDA上测试时,如果串口为一般COM接口,并且调用了此函数,那么串口不能正常工作,屏蔽此函数后,一切正常。
5.   源码

using System;
using System.Runtime.InteropServices;

namespace NativeDll
{
    public class SerialPort
    {
        serial port api#region serial port api
        //for ir control
        private const int SETIR = 10;
        private const int CLRIR = 11;
        //win32 api constants
        private const uint GENERIC_READ = 0x80000000;
        private const uint GENERIC_WRITE = 0x40000000;
        private const int OPEN_EXISTING = 3;
        private const int INVALID_HANDLE_VALUE = -1;
        private const int MAXBLOCK = 4096;

        private const uint PURGE_TXABORT = 0x0001;
        // Kill the pending/current writes to the comm port.
        private const uint PURGE_RXABORT = 0x0002;
        // Kill the pending/current reads to the comm port.
        private const uint PURGE_TXCLEAR = 0x0004;
        // Kill the transmit queue if there.
        private const uint PURGE_RXCLEAR = 0x0008;
        // Kill the typeahead buffer if there.

        [StructLayout(LayoutKind.Sequential)]
        private struct DCB
        {
            //taken from c struct in platform sdk
            public int DCBlength; // sizeof(DCB)
            public int BaudRate; // current baud rate
            public int fBinary; // binary mode, no EOF check
            public int fParity; // enable parity checking
            public int fOutxCtsFlow; // CTS output flow control
            public int fOutxDsrFlow; // DSR output flow control
            public int fDtrControl; // DTR flow control type
            public int fDsrSensitivity; // DSR sensitivity
            public int fTXContinueOnXoff; // XOFF continues Tx
            public int fOutX; // XON/XOFF out flow control
            public int fInX; // XON/XOFF in flow control
            public int fErrorChar; // enable error replacement
            public int fNull; // enable null stripping
            public int fRtsControl; // RTS flow control
            public int fAbortonError; // abort on error
            public int fDummy2; // reserved
            public ushort wReserved; // not currently used
            public ushort XonLim; // transmit XON threshold
            public ushort XoffLim; // transmit XOFF threshold
            public byte ByteSize; // number of bits/byte, 4-8
            public byte Parity; // 0-4=no,odd,even,mark,space
            public byte StopBits; // 0,1,2 = 1, 1.5, 2
            public char XonChar; // Tx and Rx XON character
            public char XoffChar; // Tx and Rx XOFF character
            public char ErrorChar; // error replacement character
            public char EofChar; // end of input character
            public char EvtChar; // received event character
            public ushort wReserved1; // reserved; do not use
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct COMMTIMEOUTS
        {
            public int ReadIntervalTimeout;
            public int ReadTotalTimeoutMultiplier;
            public int ReadTotalTimeoutConstant;
            public int WriteTotalTimeoutMultiplier;
            public int WriteTotalTimeoutConstant;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct OVERLAPPED
        {
            public int Internal;
            public int InternalHigh;
            public int Offset;
            public int OffsetHigh;
            public int hEvent;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct COMSTAT
        {
            /**//*public int fCtsHold;
            public int fDsrHold;
            public int fRlsdHold;
            public int fXoffHold;
            public int fXoffSent;
            public int fEof;
            public int fTxim;
            public int fReserved;
            public int cbInQue;
            public int cbOutQue;*/
            // Should have a reverse, i don't know why!!!!!
            public int cbOutQue;
            public int cbInQue;
            public int fReserved;
            public int fTxim;
            public int fEof;
            public int fXoffSent;
            public int fXoffHold;
            public int fRlsdHold;
            public int fDsrHold;
            public int fCtsHold;
        }

        #endregion

        private int hComm = INVALID_HANDLE_VALUE;
        private bool bOpened = false;
        private API api = null;

        public SerialPort()
        {
            if (System.Environment.OSVersion.Platform != PlatformID.WinCE)
                api = new PCAPI();
            else
                api = new PDAAPI();
        }

        public bool Opened
        {
            get
            {
                return bOpened;
            }
        }

        /**////
        /// open port
        ///
        ///
        ///
        ///
        ///
        ///
        ///
        public bool OpenPort(string lpFileName, int baudRate, byte parity, byte
            byteSize, byte stopBits)
        {
            // OPEN THE COMM PORT.
            hComm = api.CreateFile(lpFileName, GENERIC_READ | GENERIC_WRITE, 0,
                0, OPEN_EXISTING, 0, 0);
            // IF THE PORT CANNOT BE OPENED, BAIL OUT.
            if (hComm == INVALID_HANDLE_VALUE)
            {
                return false;
            }

            api.SetupComm(hComm, MAXBLOCK, MAXBLOCK);


            // SET THE COMM TIMEOUTS.
            COMMTIMEOUTS ctoCommPort = new COMMTIMEOUTS();
            api.GetCommTimeouts(hComm, ref ctoCommPort);
            ctoCommPort.ReadIntervalTimeout = Int32.MaxValue;
            ctoCommPort.ReadTotalTimeoutConstant = 1000;
            ctoCommPort.ReadTotalTimeoutMultiplier = 0;
            ctoCommPort.WriteTotalTimeoutMultiplier = 0;
            ctoCommPort.WriteTotalTimeoutConstant = 1000;
            api.SetCommTimeouts(hComm, ref ctoCommPort);

            // SET BAUD RATE, PARITY, word SIZE, AND STOP BITS.
            // THERE ARE OTHER WAYS OF DOING SETTING THESE BUT THIS IS THE EASIEST.
            // IF YOU WANT TO LATER ADD CODE FOR OTHER BAUD RATES, REMEMBER
            // THAT THE ARGUMENT FOR BuildCommDCB MUST BE A POINTER TO A STRING.
            // ALSO NOTE THAT BuildCommDCB() DEFAULTS TO NO HANDSHAKING.
            DCB dcbCommPort = new DCB();
            dcbCommPort.DCBlength = Marshal.SizeOf(dcbCommPort);
            api.GetCommState(hComm, ref dcbCommPort);
            dcbCommPort.BaudRate = baudRate;
            dcbCommPort.Parity = parity;
            dcbCommPort.ByteSize = byteSize;
            dcbCommPort.StopBits = stopBits;
            api.SetCommState(hComm, ref dcbCommPort);

            api.PurgeComm(hComm, PURGE_RXCLEAR | PURGE_RXABORT);
            api.PurgeComm(hComm, PURGE_TXCLEAR | PURGE_TXABORT);

            bOpened = true;
            return true;
        }
        /**////
        /// when set this property ,be sure the port is opened.
        ///
        public bool IREnable
        {
            set
            {
                if (bOpened)
                {
                    if (System.Environment.OSVersion.Platform == PlatformID.WinCE)
                    {
                        if (value)
                        {
                            api.EscapeCommFunction(hComm, SETIR);//enable ir
                        }
                        else
                        {
                            api.EscapeCommFunction(hComm, CLRIR);//disable ir
                        }
                    }
                }
            }
        }
        /**////
        /// get/set baudrate
        ///
        public int BaudRate
        {
            get
            {
                DCB dcbCommPort = new DCB();
                dcbCommPort.DCBlength = Marshal.SizeOf(dcbCommPort);
                api.GetCommState(hComm, ref dcbCommPort);
                return dcbCommPort.BaudRate;
            }
            set
            {
                DCB dcbCommPort = new DCB();
                dcbCommPort.DCBlength = Marshal.SizeOf(dcbCommPort);
                api.GetCommState(hComm, ref dcbCommPort);
                dcbCommPort.BaudRate = value;
                api.SetCommState(hComm, ref dcbCommPort);

                //12/21/2006 wang
                //api.PurgeComm(hComm, PURGE_RXCLEAR | PURGE_RXABORT);
                //api.PurgeComm(hComm, PURGE_TXCLEAR | PURGE_TXABORT);
            }
        }
        /**////
        /// close port
        ///
        ///
        public bool ClosePort()
        {
            if (hComm == INVALID_HANDLE_VALUE)
            {
                return false;
            }

            if (api.CloseHandle(hComm))
            {
                hComm = INVALID_HANDLE_VALUE;
                bOpened = false;
                return true;
            }
            else
            {
                return false;
            }
        }

        /**////
        /// write to port
        ///
        ///
        ///
        public bool WritePort(byte[] WriteBytes)
        {
            bool flag = false;
            COMSTAT ComStat = new COMSTAT();
            int dwErrorFlags = 0;
            int BytesWritten = 0;
            OVERLAPPED ovlCommPort = new OVERLAPPED();
            api.ClearCommError(hComm, ref dwErrorFlags, ref ComStat);
            api.PurgeComm(hComm, PURGE_RXCLEAR | PURGE_RXABORT);
            //api.PurgeComm(hComm, PURGE_TXCLEAR | PURGE_TXABORT);//19/10 2006 wang this is because of the hitachi mode writing bytes continuesly
            flag = api.WriteFile(hComm, WriteBytes, WriteBytes.Length, ref BytesWritten, ref ovlCommPort);
            return flag;
        }

        /**////
        /// read from port
        ///
        ///
        ///
        ///
        public bool ReadPort(int NumBytes, ref byte[] commRead)
        {
            bool flag = false;
            COMSTAT ComStat = new COMSTAT();
            int dwErrorFlags = 0;
            int BytesRead = 0;
            OVERLAPPED ovlCommPort = new OVERLAPPED();
            api.ClearCommError(hComm, ref dwErrorFlags, ref ComStat);
            flag = api.ReadFile(hComm, commRead, NumBytes, ref BytesRead, ref ovlCommPort);
            return flag;
        }
        interface API
        {
            int CreateFile(string lpFileName,  // file name
            uint dwDesiredAccess,  // access mode
            int dwShareMode,  // share mode
            int lpSecurityAttributes,  // SD
            int dwCreationDisposition,  // how to create
            int dwFlagsAndAttributes,  // file attributes
            int hTemplateFile  // handle to template file
            );


            bool GetCommState(int hFile,  // handle to communications device
            ref DCB lpDCB  // device-control block
            );


            bool BuildCommDCB(string lpDef,  // device-control string
            ref DCB lpDCB  // device-control block
            );


            bool SetCommState(int hFile,  // handle to communications device
            ref DCB lpDCB  // device-control block
            );


            bool GetCommTimeouts(int hFile,  // handle to comm device
            ref COMMTIMEOUTS lpCommTimeouts  // time-out values
            );


            bool SetCommTimeouts(int hFile,  // handle to comm device
            ref COMMTIMEOUTS lpCommTimeouts  // time-out values
            );


            bool ReadFile(int hFile,  // handle to file
            byte[] lpBuffer,  // data buffer
            int nNumberOfBytesToRead,  // number of bytes to read
            ref int lpNumberOfBytesRead,  // number of bytes read
            ref OVERLAPPED lpOverlapped  // overlapped buffer
            );


            bool WriteFile(int hFile,  // handle to file
            byte[] lpBuffer,  // data buffer
            int nNumberOfBytesToWrite,  // number of bytes to write
            ref int lpNumberOfBytesWritten,  // number of bytes written
            ref OVERLAPPED lpOverlapped  // overlapped buffer
            );


            bool CloseHandle(int hObject  // handle to object
            );


            bool ClearCommError(int hFile,  // handle to file
            ref int lpErrors, ref COMSTAT lpStat);


            bool PurgeComm(int hFile,  // handle to file
            uint dwFlags);


            bool SetupComm(int hFile, int dwInQueue, int dwOutQueue);

            int EscapeCommFunction(int hFile, UInt32 dwFunc);
        }
        class PCAPI : API
        {
            public int CreateFile(string lpFileName,  // file name
            uint dwDesiredAccess,  // access mode
            int dwShareMode,  // share mode
            int lpSecurityAttributes,  // SD
            int dwCreationDisposition,  // how to create
            int dwFlagsAndAttributes,  // file attributes
            int hTemplateFile  // handle to template file
            )
            {
                return WinCreateFile(lpFileName,  // file name
                dwDesiredAccess,  // access mode
                dwShareMode,  // share mode
                lpSecurityAttributes,  // SD
                dwCreationDisposition,  // how to create
                dwFlagsAndAttributes,  // file attributes
                hTemplateFile  // handle to template file
                );
            }


            public bool GetCommState(int hFile,
                // handle to communications device
            ref DCB lpDCB  // device-control block
            )
            {
                return WinGetCommState(hFile,
                    // handle to communications device
                ref lpDCB  // device-control block
                );
            }


            public bool BuildCommDCB(string lpDef,  // device-control string
            ref DCB lpDCB  // device-control block
            )
            {
                return WinBuildCommDCB(lpDef,  // device-control string
                ref lpDCB  // device-control block
                );
            }


            public bool SetCommState(int hFile,
                // handle to communications device
            ref DCB lpDCB  // device-control block
            )
            {
                return WinSetCommState(hFile,
                    // handle to communications device
                ref lpDCB  // device-control block
                );
            }


            public bool GetCommTimeouts(int hFile,  // handle to comm device
            ref COMMTIMEOUTS lpCommTimeouts  // time-out values
            )
            {
                return WinGetCommTimeouts(hFile,  // handle to comm device
                ref lpCommTimeouts  // time-out values
                );
            }


            public bool SetCommTimeouts(int hFile,  // handle to comm device
            ref COMMTIMEOUTS lpCommTimeouts  // time-out values
            )
            {
                return WinSetCommTimeouts(hFile,  // handle to comm device
                ref lpCommTimeouts  // time-out values
                );
            }


            public bool ReadFile(int hFile,  // handle to file
            byte[] lpBuffer,  // data buffer
            int nNumberOfBytesToRead,  // number of bytes to read
            ref int lpNumberOfBytesRead,  // number of bytes read
            ref OVERLAPPED lpOverlapped  // overlapped buffer
            )
            {
                return WinReadFile(hFile,  // handle to file
                lpBuffer,  // data buffer
                nNumberOfBytesToRead,  // number of bytes to read
                ref lpNumberOfBytesRead,  // number of bytes read
                ref lpOverlapped  // overlapped buffer
                );
            }


            public bool WriteFile(int hFile,  // handle to file
            byte[] lpBuffer,  // data buffer
            int nNumberOfBytesToWrite,  // number of bytes to write
            ref int lpNumberOfBytesWritten,  // number of bytes written
            ref OVERLAPPED lpOverlapped  // overlapped buffer
            )
            {
                return WinWriteFile(hFile,  // handle to file
                lpBuffer,  // data buffer
                nNumberOfBytesToWrite,  // number of bytes to write
                ref lpNumberOfBytesWritten,  // number of bytes written
                ref lpOverlapped  // overlapped buffer
                );
            }


            public bool CloseHandle(int hObject  // handle to object
            )
            {
                return WinCloseHandle(hObject  // handle to object
                );
            }


            public bool ClearCommError(int hFile,  // handle to file
            ref int lpErrors, ref COMSTAT lpStat)
            {
                return WinClearCommError(hFile,  // handle to file
                ref lpErrors, ref lpStat);
            }


            public bool PurgeComm(int hFile,  // handle to file
            uint dwFlags)
            {
                return WinPurgeComm(hFile,  // handle to file
                dwFlags);
            }


            public bool SetupComm(int hFile, int dwInQueue, int dwOutQueue)
            {
                return WinSetupComm(hFile, dwInQueue, dwOutQueue);
            }

            public int EscapeCommFunction(int hFile, UInt32 dwFunc)
            {
                return WinEscapeCommFunction(hFile, dwFunc);
            }
            P/Invoke#region P/Invoke
            [DllImport("kernel32", EntryPoint = "CreateFile")]
            private static extern int WinCreateFile(string lpFileName,
                // file name
            uint dwDesiredAccess,  // access mode
            int dwShareMode,  // share mode
            int lpSecurityAttributes,  // SD
            int dwCreationDisposition,  // how to create
            int dwFlagsAndAttributes,  // file attributes
            int hTemplateFile  // handle to template file
            );

            [DllImport("kernel32", EntryPoint = "GetCommState")]
            private static extern bool WinGetCommState(int hFile,
                // handle to communications device
            ref DCB lpDCB  // device-control block
            );

            [DllImport("kernel32", EntryPoint = "BuildCommDCB")]
            private static extern bool WinBuildCommDCB(string lpDef,
                // device-control string
            ref DCB lpDCB  // device-control block
            );

            [DllImport("kernel32", EntryPoint = "SetCommState")]
            private static extern bool WinSetCommState(int hFile,
                // handle to communications device
            ref DCB lpDCB  // device-control block
            );

            [DllImport("kernel32", EntryPoint = "GetCommTimeouts")]
            private static extern bool WinGetCommTimeouts(int hFile,
                // handle to comm device
            ref COMMTIMEOUTS lpCommTimeouts  // time-out values
            );

            [DllImport("kernel32", EntryPoint = "SetCommTimeouts")]
            private static extern bool WinSetCommTimeouts(int hFile,
                // handle to comm device
            ref COMMTIMEOUTS lpCommTimeouts  // time-out values
            );

            [DllImport("kernel32", EntryPoint = "ReadFile")]
            private static extern bool WinReadFile(int hFile,  // handle to file
            byte[] lpBuffer,  // data buffer
            int nNumberOfBytesToRead,  // number of bytes to read
            ref int lpNumberOfBytesRead,  // number of bytes read
            ref OVERLAPPED lpOverlapped  // overlapped buffer
            );

 

本文作者:佚名 来源:http://aspxboy.com/private/5530/default.aspx
CIO之家 www.ciozj.com 微信公众号:imciow
   
免责声明:本站转载此文章旨在分享信息,不代表对其内容的完全认同。文章来源已尽可能注明,若涉及版权问题,请及时与我们联系,我们将积极配合处理。同时,我们无法对文章内容的真实性、准确性及完整性进行完全保证,对于因文章内容而产生的任何后果,本账号不承担法律责任。转载仅出于传播目的,读者应自行对内容进行核实与判断。请谨慎参考文章信息,一切责任由读者自行承担。
延伸阅读