zoukankan      html  css  js  c++  java
  • 通用串口通信类

      以前串口通信一直用AxInterop.MSCommLib第三方串口通信类,但是发现那个东西用着很麻烦,因为需要设置ActiveX控件的持久状态OcxState,这个东西又蛋疼的一般在Winform的Designer里面,随意调整一下界面的布局,那个OcxState的设定就不见了。。。还有个蛋疼的地方就是打开和关闭串口需要比较久的时间。

      于是我就想要自己写一个串口通信类,就叫做SerialCommunication。

      首先需要一些DllImport

    [DllImport("kernel32.dll")]
    private static extern 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 
        );
    [DllImport("kernel32.dll")]
    private static extern bool GetCommState(
        int hFile, // handle to communications device 
        ref Dcb lpDcb // device-control block 
        );
    //[DllImport("kernel32.dll")]
    //private static extern bool BuildCommDCB(
    //    string lpDef, // device-control string 
    //    ref DCB lpDcb // device-control block 
    //    );
    [DllImport("kernel32.dll")]
    private static extern bool SetCommState(
        int hFile, // handle to communications device 
        ref Dcb lpDcb // device-control block 
        );
    //[DllImport("kernel32.dll")]
    //private static extern bool GetCommTimeouts(
    //    int hFile, // handle to comm device 
    //    ref CommTimeouts lpCommTimeouts // time-out values 
    //    );
    [DllImport("kernel32.dll")]
    private static extern bool SetCommTimeouts(
        int hFile, // handle to comm device 
        ref CommTimeouts lpCommTimeouts // time-out values 
        );
    [DllImport("kernel32.dll")]
    private static extern 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 
        );
    [DllImport("kernel32.dll")]
    private static extern 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 
        );
    [DllImport("kernel32.dll")]
    private static extern bool CloseHandle(
        int hObject // handle to object 
        );
    //[DllImport("kernel32.dll")]
    //private static extern uint GetLastError();

      然后需要一些struct

    [StructLayout(LayoutKind.Sequential)]
    public struct CommTimeouts
    {
        public UInt32 ReadIntervalTimeout;
        public UInt32 ReadTotalTimeoutMultiplier;
        public UInt32 ReadTotalTimeoutConstant;
        public UInt32 WriteTotalTimeoutMultiplier;
        public UInt32 WriteTotalTimeoutConstant;
    }
    [StructLayout(LayoutKind.Sequential)]
    public struct Dcb
    {
        public Int32 DCBlength;
        public Int32 BaudRate;
        public Int32 PackedValues;
        public Int16 wReserved;
        public Int16 XonLim;
        public Int16 XoffLim;
        public Byte ByteSize;
        public Byte Parity;
        public Byte StopBits;
        public Byte XonChar;
        public Byte XoffChar;
        public Byte ErrorChar;
        public Byte EofChar;
        public Byte EvtChar;
        public Int16 wReserved1;
    }
    [StructLayout(LayoutKind.Sequential)]
    public struct Overlapped
    {
        public UIntPtr Internal;
        public UIntPtr InternalHigh;
        public UInt32 Offset;
        public UInt32 OffsetHigh;
        public IntPtr hEvent;
    }
    

      最后实现开关读写串口即可。开串口只需打开串口,设置串口两步操作,打开串口可能会失败,原因一般是该串口没有设备连接或者正在被其他设备使用中,设置串口也有可能会失败,原因一般是设置的参数不正确或者不够。关串口只需要执行CloseHandle即可

    public void Open()
    {
        // OPEN THE COMM PORT. 
        _hComm = CreateFile("COM" + PortNum, GenericRead | GenericWrite, 0, 0, OpenExisting, 0, 0);
        // IF THE PORT CANNOT BE OPENED, BAIL OUT. 
        if (_hComm == InvalidHandleValue)
        {
    		throw (new Exception("Port Open Failure"));
        }
        CommTimeouts ctoCommPort = new CommTimeouts { ReadTotalTimeoutConstant = ReadTimeout };
        if (!SetCommTimeouts(_hComm, ref ctoCommPort))
        {
    		throw (new Exception("Bad Timeout Settings"));
        }
        Dcb dcb = new Dcb();
        GetCommState(_hComm, ref dcb);
        dcb.BaudRate = BaudRate;
        dcb.Parity = Parity;
        dcb.ByteSize = ByteSize;
        dcb.StopBits = StopBits;
        if (!SetCommState(_hComm, ref dcb))
        {
    		throw (new Exception("Bad Com Settings"));
        }
    }
    public void Close()
    {
        if (_hComm != InvalidHandleValue)
        {
    		CloseHandle(_hComm);
        }
    }
    

      读串口执行ReadFile即可,可以在调用的地方开一个线程不断的读串口,不过需要考虑效率问题。写串口执行WriteFile即可,每次读、写串口不需要先关闭再打开串口,那样的话也会浪费效率,但是若串口号或者串口配置修改了,则需要关闭并重新打开串口。

      串口通信类源码

      

  • 相关阅读:
    spring security 单一账户多地方登陆提醒, ajax 拦截器 Interceptor
    Maven 项目打包发布
    jQuery使用on()绑定动态生成元素的事件无效
    ie下li标签中span加float:right不换行问题解决方案
    IE使用多彩文档上传数据库报错
    对象数组中删除指定元素
    jquery 文本框内容清空
    SQL删除重复数据方法
    静态数据的初始化
    java变量初始化顺序
  • 原文地址:https://www.cnblogs.com/hambert/p/3392779.html
Copyright © 2011-2022 走看看