国内最大的酷站演示中心!
前一阵,从国外网站看到一个用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) {
}
}
}
}
程序运行后,你可以对设备进行指令操作。(具体设备接受的指令)