国内最大的酷站演示中心!
前一阵,从国外网站看到一个用c#来操作串口的类。下载下来试了一下,觉得不错。共享一下。
/*
* author: marcus lorentzon, 2001
* [email protected]
* 
* freeware: please do not remove this header
* 
* file: serialstream.cs
* 
* description: implements a stream for asynchronous
* transfers and comm. stream version.
*
* version: 2.4
* 
*/
#region using
using system;
using system.io;
using system.threading;
using system.runtime.interopservices;
using system.componentmodel;
#endregion using
namespace loman.io {
 public class serialstream : stream {
 
 #region attributes
 private iocompletioncallback m_iocompletioncallback;
 private intptr m_hfile = intptr.zero;
 private string m_sport;
 private bool m_bread;
 private bool m_bwrite;
 #endregion attributes
 #region properties
 public string port {
 get {
 return m_sport;
 }
 set {
 if (m_sport != value) {
 close();
 open(value);
 }
 }
 }
 public override bool canread {
 get {
 return m_bread;
 }
 }
 public override bool canwrite {
 get {
 return m_bwrite;
 }
 }
 public override bool canseek {
 get {
 return false;
 }
 }
 public bool closed {
 get {
 return m_hfile.toint32() 0;
 }
 }
 public bool dsr {
 get {
 uint status;
 if (!getcommmodemstatus(m_hfile, out status)) {
 throw new win32exception();
 }
 return (status & ms_dsr_on) > 0;
 }
 }
 public bool ring {
 get {
 uint status;
 if (!getcommmodemstatus(m_hfile, out status)) {
 throw new win32exception();
 }
 return (status & ms_ring_on) > 0;
 }
 }
 public bool rlsd {
 get {
 uint status;
 if (!getcommmodemstatus(m_hfile, out status)) {
 throw new win32exception();
 }
 return (status & ms_rlsd_on) > 0;
 }
 }
 #endregion properties
 #region constructors
 public serialstream() : this(fileaccess.readwrite) {
 }
 public serialstream(fileaccess access) {
 m_bread = ((int)access & (int)fileaccess.read) != 0;
 m_bwrite = ((int)access & (int)fileaccess.write) != 0;
 unsafe {
 m_iocompletioncallback = new iocompletioncallback(asyncfscallback);
 }
 }
 public serialstream(string port) : this(fileaccess.readwrite) {
 open(port);
 }
 public serialstream(string port, fileaccess access) : this(access) {
 open(port);
 }
 #endregion constructors
 #region methods
 public void open(string port) {
 if (m_hfile != intptr.zero) {
 throw new ioexception("stream already opened.");
 }
 m_sport = port;
 m_hfile = createfile(port, (uint)((m_bread?generic_read:0)|(m_bwrite?generic_write:0)), 0, 0, open_existing, file_flag_overlapped, 0);
 if (m_hfile.toint32() == invalid_handle_value) {
 m_hfile = intptr.zero;
 throw new filenotfoundexception("unable to open " + port);
 }
 threadpool.bindhandle(m_hfile);
 settimeouts(0, 0, 0, 0, 0);
 }
 public override void close() {
 closehandle(m_hfile);
 m_hfile = intptr.zero;
 m_sport = null;
 }
 public iasyncresult beginread(byte[] buffer) {
 return beginread(buffer, 0, buffer.length, null, null);
 }
 public override iasyncresult beginread(byte[] buffer, int offset, int count, asynccallback callback, object state) {
 gchandle gchbuffer = gchandle.alloc(buffer, gchandletype.pinned);
 serialasyncresult sar = new serialasyncresult(this, state, callback, true, gchbuffer);
 overlapped ov = new overlapped(0, 0, sar.asyncwaithandle.handle.toint32(), sar);
 unsafe {
 nativeoverlapped* nov = ov.pack(m_iocompletioncallback);
 byte* data = (byte*)((int)gchbuffer.addrofpinnedobject() + offset);
 uint read = 0;
 if (readfile(m_hfile, data, (uint)count, out read, nov)) {
 sar.m_bcompletedsynchronously = true;
 return sar;
 }
 else if (getlasterror() == error_io_pending) {
 return sar;
 }
 else
 throw new exception("unable to initialize read. errorcode: " + getlasterror().tostring());
 }
 }
 public iasyncresult beginwrite(byte[] buffer) {
 return beginwrite(buffer, 0, buffer.length, null, null);
 }
 public override iasyncresult beginwrite(byte[] buffer, int offset, int count, asynccallback callback, object state) {
 gchandle gchbuffer = gchandle.alloc(buffer, gchandletype.pinned);
 serialasyncresult sar = new serialasyncresult(this, state, callback, false, gchbuffer);
 overlapped ov = new overlapped(0, 0, sar.asyncwaithandle.handle.toint32(), sar);
 unsafe {
 nativeoverlapped* nov = ov.pack(m_iocompletioncallback);
 byte* data = (byte*)((int)gchbuffer.addrofpinnedobject() + offset);
 uint written = 0;
 if (writefile(m_hfile, data, (uint)count, out written, nov)) {
 sar.m_bcompletedsynchronously = true;
 return sar;
 }
 else if (getlasterror() == error_io_pending) {
 return sar;
 }
 else
 throw new exception("unable to initialize write. errorcode: " + getlasterror().tostring());
 }
 }
 private int endoperation(iasyncresult asyncresult, bool isread) {
 serialasyncresult sar = (serialasyncresult)asyncresult;
 if (sar.m_bisread != isread)
 throw new ioexception("invalid parameter: iasyncresult is not from a " + (isread ? "read" : "write"));
 if (sar.endoperationcalled) {
 throw new ioexception("end" + (isread ? "read" : "write") + " called twice for the same operation.");
 }
 else {
 sar.m_bendoperationcalled = true;
 }
 while (!sar.m_bcompleted) {
 sar.asyncwaithandle.waitone();
 }
 sar.dispose();
 if (sar.m_nerrorcode != error_success && sar.m_nerrorcode != error_operation_aborted) {
 throw new ioexception("operation finished with errorcode: " + sar.m_nerrorcode);
 }
 return sar.m_nreadwritten;
 }
 
 public override int endread(iasyncresult asyncresult) {
 return endoperation(asyncresult, true);
 }
 
 public override void endwrite(iasyncresult asyncresult) {
 endoperation(asyncresult, false);
 }
 public int endwriteex(iasyncresult asyncresult) {
 return endoperation(asyncresult, false);
 }
 public override int read(byte[] buffer, int offset, int count) {
 return endread(beginread(buffer, offset, count, null, null));
 }
 public override void write(byte[] buffer, int offset, int count) {
 endwrite(beginwrite(buffer, offset, count, null, null));
 }
 public int writeex(byte[] buffer, int offset, int count) {
 return endwriteex(beginwrite(buffer, offset, count, null, null));
 }
 public int read(byte[] buffer) {
 return endread(beginread(buffer, 0, buffer.length, null, null));
 }
 public int write(byte[] buffer) {
 return endoperation(beginwrite(buffer, 0, buffer.length, null, null), false);
 }
 public override void flush() {
 flushfilebuffers(m_hfile);
 }
 public bool purgeread() {
 return purgecomm(m_hfile, purge_rxclear);
 }
 public bool purgewrite() {
 return purgecomm(m_hfile, purge_txclear);
 }
 public bool purge() {
 return purgeread() && purgewrite();
 }
 public bool cancelread() {
 return purgecomm(m_hfile, purge_rxabort);
 }
 public bool cancelwrite() {
 return purgecomm(m_hfile, purge_txabort);
 }
 public bool cancelall() {
 return cancelread() && cancelwrite();
 }
 public override void setlength(long nlength) {
 throw new notsupportedexception("setlength isn't supported on serial ports.");
 }
 public override long seek(long offset, seekorigin origin) {
 throw new notsupportedexception("seek isn't supported on serial ports.");
 }
 public void settimeouts(int readintervaltimeout,
 int readtotaltimeoutmultiplier,
 int readtotaltimeoutconstant, 
 int writetotaltimeoutmultiplier,
 int writetotaltimeoutconstant) {
 serialtimeouts timeouts = new serialtimeouts(readintervaltimeout,
 readtotaltimeoutmultiplier,
 readtotaltimeoutconstant, 
 writetotaltimeoutmultiplier,
 writetotaltimeoutconstant);
 unsafe { setcommtimeouts(m_hfile, ref timeouts); }
 }
 public bool setportsettings(uint baudrate) {
 return setportsettings(baudrate, flowcontrol.hardware);
 }
 public bool setportsettings(uint baudrate, flowcontrol flowcontrol) {
 return setportsettings(baudrate, flowcontrol, parity.none);
 }
 public bool setportsettings(uint baudrate, flowcontrol flowcontrol, parity parity) {
 return setportsettings(baudrate, flowcontrol, parity, 8, stopbits.one);
 }
 public bool setportsettings(uint baudrate, flowcontrol flowcontrol, parity parity, byte databits, stopbits stopbits) {
 unsafe {
 dcb dcb = new dcb();
 dcb.dcblength = sizeof(dcb);
 dcb.baudrate = baudrate;
 dcb.bytesize = databits;
 dcb.stopbits = (byte)stopbits;
 dcb.parity = (byte)parity;
 dcb.fparity = (parity > 0)? 1u : 0u;
 dcb.fbinary = dcb.fdtrcontrol = dcb.ftxcontinueonxoff = 1;
 dcb.foutxctsflow = dcb.fabortonerror = (flowcontrol == flowcontrol.hardware)? 1u : 0u;
 dcb.foutx = dcb.finx = (flowcontrol == flowcontrol.xonxoff)? 1u : 0u;
 dcb.frtscontrol = (flowcontrol == flowcontrol.hardware)? 2u : 1u;
 dcb.xonlim = 2048;
 dcb.xofflim = 512;
 dcb.xonchar = 0x11; // ctrl-q
 dcb.xoffchar = 0x13; // ctrl-s
 return setcommstate(m_hfile, ref dcb);
 }
 }
 public bool setportsettings(dcb dcb) {
 return setcommstate(m_hfile, ref dcb);
 }
 public bool getportsettings(out dcb dcb) {
 unsafe {
 dcb dcb2 = new dcb();
 dcb2.dcblength = sizeof(dcb);
 bool ret = getcommstate(m_hfile, ref dcb2);
 dcb = dcb2;
 return ret;
 }
 }
 public bool setxon() {
 return escapecommfunction(m_hfile, setxon);
 }
 public bool setxoff() {
 return escapecommfunction(m_hfile, setxoff);
 }
 private unsafe void asyncfscallback(uint errorcode, uint numbytes, nativeoverlapped* poverlapped) {
 serialasyncresult sar = (serialasyncresult)overlapped.unpack(poverlapped).asyncresult;
 sar.m_nerrorcode = errorcode;
 sar.m_nreadwritten = (int)numbytes;
 sar.m_bcompleted = true;
 if (sar.callback != null)
 sar.callback.invoke(sar);
 overlapped.free(poverlapped);
 }
 #endregion methods
 #region constants
 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.
 private const uint setxoff = 1; // simulate xoff received
 private const uint setxon = 2; // simulate xon received
 private const uint setrts = 3; // set rts high
 private const uint clrrts = 4; // set rts low
 private const uint setdtr = 5; // set dtr high
 private const uint clrdtr = 6; // set dtr low
 private const uint setbreak = 8; // set the device break line.
 private const uint clrbreak = 9; // clear the device break line.
 private const uint ms_cts_on = 0x0010;
 private const uint ms_dsr_on = 0x0020;
 private const uint ms_ring_on = 0x0040;
 private const uint ms_rlsd_on = 0x0080;
 private const uint file_flag_overlapped = 0x40000000;
 private const uint open_existing = 3;
 private const int invalid_handle_value = -1;
 private const uint generic_read = 0x80000000;
 private const uint generic_write = 0x40000000;
 private const uint error_success = 0;
 private const uint error_operation_aborted = 995;
 private const uint error_io_pending = 997;
 #endregion constants
 #region enums
 public enum parity {none, odd, even, mark, space};
 public enum stopbits {one, oneandhalf, two};
 public enum flowcontrol {none, xonxoff, hardware};
 #endregion enums
 #region classes
 [structlayout(layoutkind.sequential)]
 public struct dcb {
 #region attributes
 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;
 #endregion attributes
 #region properties
 public uint fbinary { get { return flags&0x0001; } 
 set { flags = flags & ~1u | value; } }
 public uint fparity { get { return (flags>>1)&1; }
 set { flags = flags & ~(1u >2)&1; }
 set { flags = flags & ~(1u >3)&1; }
 set { flags = flags & ~(1u >4)&3; }
 set { flags = flags & ~(3u >6)&1; }
 set { flags = flags & ~(1u >7)&1; }
 set { flags = flags & ~(1u >8)&1; }
 set { flags = flags & ~(1u >9)&1; }
 set { flags = flags & ~(1u >10)&1; }
 set { flags = flags & ~(1u >11)&1; }
 set { flags = flags & ~(1u >12)&3; }
 set { flags = flags & ~(3u >14)&1; }
 set { flags = flags & ~(1u << 14) | (value << 14); } }
 #endregion properties
 #region methods
 public override string tostring() {
 return "dcblength: " + dcblength + "/r/n" +
 "baudrate: " + baudrate + "/r/n" +
 "fbinary: " + fbinary + "/r/n" +
 "fparity: " + fparity + "/r/n" +
 "foutxctsflow: " + foutxctsflow + "/r/n" +
 "foutxdsrflow: " + foutxdsrflow + "/r/n" +
 "fdtrcontrol: " + fdtrcontrol + "/r/n" +
 "fdsrsensitivity: " + fdsrsensitivity + "/r/n" +
 "ftxcontinueonxoff: " + ftxcontinueonxoff + "/r/n" +
 "foutx: " + foutx + "/r/n" +
 "finx: " + finx + "/r/n" +
 "ferrorchar: " + ferrorchar + "/r/n" +
 "fnull: " + fnull + "/r/n" +
 "frtscontrol: " + frtscontrol + "/r/n" +
 "fabortonerror: " + fabortonerror + "/r/n" +
 "xonlim: " + xonlim + "/r/n" +
 "xofflim: " + xofflim + "/r/n" +
 "bytesize: " + bytesize + "/r/n" +
 "parity: " + parity + "/r/n" +
 "stopbits: " + stopbits + "/r/n" +
 "xonchar: " + xonchar + "/r/n" +
  "xoffchar: " + xoffchar + "/r/n" +
 "eofchar: " + eofchar + "/r/n" +
 "evtchar: " + evtchar + "/r/n";
 }
 #endregion methods
 }
 private class serialasyncresult : iasyncresult, idisposable {
 #region attributes
 internal bool m_bendoperationcalled = false;
 internal bool m_bisread;
 internal int m_nreadwritten = 0;
 internal bool m_bcompleted = false;
 internal bool m_bcompletedsynchronously = false;
 internal uint m_nerrorcode = error_success;
 private object m_asyncobject;
 private object m_stateobject;
 private manualresetevent m_waithandle = new manualresetevent(false);
 private asynccallback m_callback;
 private gchandle m_gchbuffer;
 #endregion attributes
 #region properties
 internal bool endoperationcalled { get { return m_bendoperationcalled; } }
 public bool iscompleted { get { return m_bcompleted; } }
 public bool completedsynchronously { get { return m_bcompletedsynchronously; } }
 public object asyncobject { get { return m_asyncobject; } }
 public object asyncstate { get { return m_stateobject; } }
 public waithandle asyncwaithandle { get { return m_waithandle; } }
 internal manualresetevent waithandle { get { return m_waithandle; } }
 public asynccallback callback { get { return m_callback; } }
 #endregion properties
 #region constructors
 public serialasyncresult(object asyncobject,
 object stateobject, 
 asynccallback callback, 
 bool bisread, 
 gchandle gchbuffer) {
 m_asyncobject = asyncobject;
 m_stateobject = stateobject;
 m_callback = callback;
 m_bisread = bisread;
 m_gchbuffer = gchbuffer;
 }
 #endregion constructors
 #region methods
 public void dispose() {
 m_waithandle.close();
 m_gchbuffer.free();
 }
 #endregion methods
 }
 #endregion classes
 #region imports
 [dllimport("kernel32.dll", entrypoint="createfilew", setlasterror=true,
 charset=charset.unicode, exactspelling=true)]
 static extern intptr createfile(string filename, uint access, uint sharemode, uint security_attributes, uint creation, uint flags, uint template);
 [dllimport("kernel32.dll", setlasterror=true)]
 static extern bool closehandle(intptr handle);
 [dllimport("kernel32.dll", setlasterror=true)]
 static extern unsafe bool readfile(intptr hfile, byte* lpbuffer, uint nnumberofbytestoread, out uint lpnumberofbytesread, nativeoverlapped* lpoverlapped);
 [dllimport("kernel32.dll", setlasterror=true)]
 static extern unsafe bool writefile(intptr hfile, byte* lpbuffer, uint nnumberofbytestowrite, out uint lpnumberofbyteswritten, nativeoverlapped* lpoverlapped);
 [dllimport("kernel32.dll", setlasterror=true)]
 static extern bool setcommtimeouts(intptr hfile, ref serialtimeouts lpcommtimeouts);
 [dllimport("kernel32.dll", setlasterror=true)]
 static extern bool setcommstate(intptr hfile, ref dcb lpdcb);
 [dllimport("kernel32.dll", setlasterror=true)]
 static extern bool getcommstate(intptr hfile, ref dcb lpdcb);
 [dllimport("kernel32.dll", setlasterror=true)]
 static extern bool buildcommdcb(string def, ref dcb lpdcb);
 [dllimport("kernel32.dll", setlasterror=true)]
  static extern int getlasterror();
 [dllimport("kernel32.dll", setlasterror=true)]
 static extern bool flushfilebuffers(intptr hfile);
 [dllimport("kernel32.dll", setlasterror=true)]
 static extern bool purgecomm(intptr hfile, uint dwflags);
 [dllimport("kernel32.dll", setlasterror=true)]
 static extern bool escapecommfunction(intptr hfile, uint dwfunc);
 [dllimport("kernel32.dll", setlasterror=true)]
 static extern bool getcommmodemstatus(intptr hfile, out uint modemstat);
 #endregion imports
 }
 [structlayout(layoutkind.sequential)]
 public struct serialtimeouts {
 #region attributes
 public int readintervaltimeout;
 public int readtotaltimeoutmultiplier;
 public int readtotaltimeoutconstant;
 public int writetotaltimeoutmultiplier;
 public int writetotaltimeoutconstant;
 #endregion attributes
 #region constructors
 public serialtimeouts(int r1, int r2, int r3, int w1, int w2) {
 readintervaltimeout = r1;
 readtotaltimeoutmultiplier = r2;
 readtotaltimeoutconstant = r3;
 writetotaltimeoutmultiplier = w1;
 writetotaltimeoutconstant = w2;
 }
 #endregion constructors
 #region methods
 public override string tostring() {
 return "readintervaltimeout: " + readintervaltimeout + "/r/n" +
 "readtotaltimeoutmultiplier: " + readtotaltimeoutmultiplier + "/r/n" +
 "readtotaltimeoutconstant: " + readtotaltimeoutconstant + "/r/n" +
 "writetotaltimeoutmultiplier: " + writetotaltimeoutmultiplier + "/r/n" +
 "writetotaltimeoutconstant: " + writetotaltimeoutconstant + "/r/n";
 }
 #endregion methods
 }
}
using system;
using system.io;
using system.threading;
using loman.io;
namespace serialstreamreader {
 class app {
 // the main serial stream
 static serialstream ss;
 [stathread]
 static void main(string[] args) {
 // create a serial port
 ss = new serialstream();
 try {
 ss.open("com4"); //我对猫进行了调用
 }
 catch (exception e) {
 console.writeline("error: " + e.message);
 return;
 }
 // set port settings
 ss.setportsettings(9600);
 // set timeout so read ends after 20ms of silence after a response
 ss.settimeouts(20, 0, 0, 0, 0);
 // create the streamwriter used to send commands
 streamwriter sw = new streamwriter(ss, system.text.encoding.ascii);
 // create the thread used to read responses
 thread responsereaderthread = new thread(new threadstart(readresponsethread));
 responsereaderthread.start();
 // read all returned lines
 for (;;) {
 // read command from console
 string command = console.readline();
 // check for exit command
 if (command.trim().tolower() == "exit") {
 responsereaderthread.abort();
 break;
 }
 // write command to modem
 sw.writeline(command);
 sw.flush();
 }
 }
 // main loop for reading responses
 static void readresponsethread() {
 streamreader sr = new streamreader(ss, system.text.encoding.ascii);
 try {
 for (;;) {
 // read response from modem
 string response = sr.readline();
 console.writeline("response: " + response);
 }
 }
 catch (threadabortexception) {
 }
 }
 }
}
程序运行后,你可以对设备进行指令操作。(具体设备接受的指令)