c#调api串口通讯
生活随笔
收集整理的這篇文章主要介紹了
c#调api串口通讯
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
c#調(diào)api串口通訊 原文:c#調(diào)api串口通訊
在調(diào)試ICU通信設備的時候,由于串口通信老出現(xiàn)故障,所以就懷疑CF實現(xiàn)的SerialPort類是否有問題,所以最后決定用純API函數(shù)實現(xiàn)串口讀寫。 先從網(wǎng)上搜索相關代碼(關鍵字:C# API 串口),發(fā)現(xiàn)網(wǎng)上相關的資料大約來源于一個版本,那就是所謂的msdn提供的樣例代碼(msdn的具體出處,我沒有考證),其它的代碼大都是它的變種。 其實這個示例代碼是有問題的,也就是說DCB結構體聲明的有問題,雖然該代碼可以正常通信,不過如果你設置了奇偶校驗的話,你會發(fā)現(xiàn)奇偶校驗無效。 VC中的DCB結構聲明如下: typedef struct _DCB { DWORD DCBlength;????? /* sizeof(DCB)???????????????????? */ DWORD BaudRate;?????? /* Baudrate at which running?????? */ DWORD fBinary: 1;???? /* Binary Mode (skip EOF check)??? */ DWORD fParity: 1;???? /* Enable parity checking????????? */ DWORD fOutxCtsFlow:1; /* CTS handshaking on output?????? */ DWORD fOutxDsrFlow:1; /* DSR handshaking on output?????? */ DWORD fDtrControl:2;?/* DTR Flow control??????????????? */ DWORD fDsrSensitivity:1; /* DSR Sensitivity????????????? */ DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ DWORD fOutX: 1;?????? /* Enable output X-ON/X-OFF??????? */ DWORD fInX: 1;??????? /* Enable input X-ON/X-OFF???????? */ DWORD fErrorChar: 1;?/* Enable Err Replacement????????? */ DWORD fNull: 1;?????? /* Enable Null stripping?????????? */ DWORD fRtsControl:2;?/* Rts Flow control??????????????? */ DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ DWORD fDummy2:17;??? ?/* Reserved??????????????????????? */ WORD wReserved;?????? /* Not currently used????????????? */ WORD XonLim;????????? /* Transmit X-ON threshold???????? */ WORD XoffLim;???????? /* Transmit X-OFF threshold??????? */ BYTE ByteSize;?????? ?/* Number of bits/byte, 4-8??????? */ BYTE Parity;????????? /* 0-4=None,Odd,Even,Mark,Space??? */ BYTE StopBits;??????? /* 0,1,2 = 1, 1.5, 2?????????????? */ char XonChar;???????? /* Tx and Rx X-ON character??????? */ char XoffChar;?????? ?/* Tx and Rx X-OFF character?????? */ char ErrorChar;?????? /* Error replacement char????????? */ char EofChar;???????? /* End of Input character????????? */ char EvtChar;???????? /* Received Event character??????? */ WORD wReserved1;???? ?/* Fill for now.?????????????????? */ } DCB, *LPDCB; 有問題的代碼DCB結構聲明如下: [StructLayout(LayoutKind.Sequential)] ??????? public struct DCB ??????? { ??????????? public int DCBlength; ??????????? public int BaudRate; ??????????? public int fBinary; ?????????? ?public int fParity; ??????????? public int fOutxCtsFlow; ??????????? public int fOutxDsrFlow; ??????????? public int fDtrControl; ??????????? public int fDsrSensitivity; ??????????? public int fTXContinueOnXoff; ??????????? public int fOutX; ??????????? public int fInX; ??????????? public int fErrorChar; ??????????? public int fNull; ??????????? public int fRtsControl; ??????????? public int fAbortOnError; ??????????? public int fDummy2; ??????????? public uint flags; ??????????? public ushort wReserved; ??????????? public ushort XonLim; ??????????? public ushort 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 ushort wReserved1; ??????? } 對C++比較熟悉網(wǎng)友應該知道,結構體中這種格式的聲明,如DWORD fBinary: 1;是以位為單位進行變量設置的,DCB中相關位一共占4個字節(jié),也就是相當于C#中的一個int變量所占的空間。很明顯上面的DCB結構會有問題,實際上后面你設置的串口參數(shù),如奇偶校驗由于偏移有問題,雖然你設置了,其實都沒有設置成功。 其實也不是我說人家的DCB聲明錯了就錯了,在SerialPort類中你就可以找到微軟官方自己的DCB聲明(需要反編譯SerialPort類),聲明如下: [StructLayout(LayoutKind.Sequential)] ??????? public struct DCB ??????? { ??????????? public int DCBlength; ??????????? public int BaudRate; ??????????? public uint Flags; ??????????? public ushort wReserved; ??????????? public ushort XonLim; ??????????? public ushort 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 ushort wReserved1; ??????? } 并且專門有一個設置位標志的函數(shù),如下: internal void SetDcbFlag(int whichFlag, int setting) ??????? { ??????????? uint num; ??????????? setting = setting << whichFlag; ??????????? if ((whichFlag == 4) || (whichFlag == 12)) ??????????? { ??????????????? num = 3; ??????????? } ??????????? else if (whichFlag == 15) ??????????? { ??????????????? num = 0x1ffff; ??????????? } ??????????? else ??????????? { ??????????????? num = 1; ??????????? } ??????????? dcb.flags &= ~(num << whichFlag); ??????????? dcb.flags |= (uint)setting; ??????? } 經(jīng)過修改能正確運行的API代碼如下(注意,由于我是在WinCE平臺上運行,所以DLL的路徑為"//windows//coredll.dll",你修改為"kernel32"后即可在PC機使用): ///<summary> ??? /// API串口類?葉帆修改 http://blog.csdn.net/yefanqiu ??? ///</summary> ??? public class CommPort ??? { ??????? ///<summary> ??????? ///端口名稱(COM1,COM2...COM4...) ??????? ///</summary> ??????? public string Port = "COM1:"; ??????? ///<summary> ??????? ///波特率9600 ??????? ///</summary> ??????? public int BaudRate = 9600; ??????? ///<summary> ??????? ///數(shù)據(jù)位4-8 ??????? ///</summary> ??????? public byte ByteSize = 8; //4-8 ??????? ///<summary> ??????? ///奇偶校驗0-4=no,odd,even,mark,space ??????? ///</summary> ??????? public byte Parity = 0;?? //0-4=no,odd,even,mark,space ??????? ///<summary> ??????? ///停止位 ??????? ///</summary> ??????? public byte StopBits = 0;?? //0,1,2 = 1, 1.5, 2 ??????? ///<summary> ??????? ///超時長 ??????? ///</summary> ??????? public int ReadTimeout = 200; ??????? ///<summary> ??????? ///串口是否已經(jīng)打開 ??????? ///</summary> ??????? public bool Opened = false; ??????? ///<summary> ??????? /// COM口句柄 ??????? ///</summary> ??????? private int hComm = -1; ??????? #region "API相關定義" ??????? private const string DLLPATH = "//windows//coredll.dll"; // "kernel32"; ??????? ///<summary> ??????? /// WINAPI常量,寫標志 ??????? ///</summary> ??????? private const uint GENERIC_READ = 0x80000000; ??????? ///<summary> ??????? /// WINAPI常量,讀標志 ??????? ///</summary> ??????? private const uint GENERIC_WRITE = 0x40000000; ??????? ///<summary> ??????? /// WINAPI常量,打開已存在 ??????? ///</summary> ??????? private const int OPEN_EXISTING = 3; ??????? ///<summary> ??????? /// WINAPI常量,無效句柄 ??????? ///</summary> ??????? private const int INVALID_HANDLE_VALUE = -1; ??????? private const int PURGE_RXABORT = 0x2; ??????? private const int PURGE_RXCLEAR = 0x8; ??????? private const int PURGE_TXABORT = 0x1; ??????? private const int PURGE_TXCLEAR = 0x4; ??????? ///<summary> ??????? ///設備控制塊結構體類型 ??????? ///</summary> ??????? [StructLayout(LayoutKind.Sequential)] ??????? public struct DCB ??????? { ???????????///<summary> ??????????? /// DCB長度 ??????????? ///</summary> ??????????? public int DCBlength; ??????????? ///<summary> ??????????? ///指定當前波特率 ??????????? ///</summary> ??????????? public int BaudRate; ??????????? ///<summary> ??????????? ///標志位 ??????????? ///</summary> ??????????? public uint flags; ??????????? ///<summary> ??????????? ///未使用,必須為0 ??????????? ///</summary> ??????????? public ushort wReserved; ??????????? ///<summary> ??????????? ///指定在XON字符發(fā)送這前接收緩沖區(qū)中可允許的最小字節(jié)數(shù) ????? ??????///</summary> ??????????? public ushort XonLim; ??????????? ///<summary> ??????????? ///指定在XOFF字符發(fā)送這前接收緩沖區(qū)中可允許的最小字節(jié)數(shù) ??????????? ///</summary> ??????????? public ushort XoffLim; ??????????? ///<summary> ??????????? ///指定端口當前使用的數(shù)據(jù)位 ??????????? ///</summary> ??????????? public byte ByteSize; ??????????? ///<summary> ??????????? ///指定端口當前使用的奇偶校驗方法,可能為:EVENPARITY,MARKPARITY,NOPARITY,ODDPARITY 0-4=no,odd,even,mark,space ??????????? ///</summary> ??????????? public byte Parity; ??????????? ///<summary> ??????????? ///指定端口當前使用的停止位數(shù),可能為:ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS 0,1,2 = 1, 1.5, 2 ??????????? ///</summary> ??????????? public byte StopBits; ??????????? ///<summary> ??????????? ///指定用于發(fā)送和接收字符XON的值 Tx and Rx XON character ??????????? ///</summary> ??????????? public byte XonChar; ??????????? ///<summary> ??????????? ///指定用于發(fā)送和接收字符XOFF值 Tx and Rx XOFF character ??????????? ///</summary> ??????????? public byte XoffChar; ??????????? ///<summary> ??????????? ///本字符用來代替接收到的奇偶校驗發(fā)生錯誤時的值 ??????????? ///</summary> ??????????? public byte ErrorChar; ??????????? ///<summary> ??????????? ///當沒有使用二進制模式時,本字符可用來指示數(shù)據(jù)的結束 ??????????? ///</summary> ??????????? public byte EofChar; ??????????? ///<summary> ??????????? ///當接收到此字符時,會產(chǎn)生一個事件 ????? ??????///</summary> ??????????? public byte EvtChar; ??????????? ///<summary> ??????????? ///未使用 ??????????? ///</summary> ??????????? public ushort wReserved1; ??????? } ??????? ///<summary> ??????? ///串口超時時間結構體類型 ??????? ///</summary> ??????? [StructLayout(LayoutKind.Sequential)] ??????? private struct COMMTIMEOUTS ??????? { ??????????? public int ReadIntervalTimeout; ??????????? public int ReadTotalTimeoutMultiplier; ??????????? public int ReadTotalTimeoutConstant; ??????????? public int WriteTotalTimeoutMultiplier; ??????????? public int WriteTotalTimeoutConstant; ??????? } ??????? ///<summary> ??????? ///溢出緩沖區(qū)結構體類型 ??????? ///</summary> ??????? [StructLayout(LayoutKind.Sequential)] ??????? private struct OVERLAPPED ??????? { ??????????? public int Internal; ??????????? public int InternalHigh; ??????????? public int Offset; ??????????? public int OffsetHigh; ??????????? public int hEvent; ??????? } ??????? ///<summary> ??????? ///打開串口 ??????? ///</summary> ??????? ///<param name="lpFileName">要打開的串口名稱</param> ??????? ///<param name="dwDesiredAccess">指定串口的訪問方式,一般設置為可讀可寫方式</param> ??????? ///<param name="dwShareMode">指定串口的共享模式,串口不能共享,所以設置為0</param> ??????? ///<param name="lpSecurityAttributes">設置串口的安全屬性,WIN9X下不支持,應設為NULL</param> ??????? ///<param name="dwCreationDisposition">對于串口通信,創(chuàng)建方式只能為OPEN_EXISTING</param> ??????? ///<param name="dwFlagsAndAttributes">指定串口屬性與標志,設置為FILE_FLAG_OVERLAPPED(重疊I/O操作),指定串口以異步方式通信</param> ??????? ///<param name="hTemplateFile">對于串口通信必須設置為NULL</param> ??????? [DllImport(DLLPATH)] ??????? private static extern int CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode, ??????? int lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile); ??????? ///<summary> ??????? ///得到串口狀態(tài) ??????? ///</summary> ??????? ///<param name="hFile">通信設備句柄</param> ??????? ///<param name="lpDCB">設備控制塊DCB</param> ??????? [DllImport(DLLPATH)] ??????? private static extern bool GetCommState(int hFile, ref DCB lpDCB); ??????? ///<summary> ??????? ///建立串口設備控制塊(嵌入版沒有) ??????? ///</summary> ??????? ///<param name="lpDef">設備控制字符串</param> ??????? ///<param name="lpDCB">設備控制塊</param> ??????? //[DllImport(DLLPATH)] ??????? //private static extern bool BuildCommDCB(string lpDef, ref DCB lpDCB); ??????? ///<summary> ??????? ///設置串口狀態(tài) ??????? ///</summary> ??????? ///<param name="hFile">通信設備句柄</param> ??????? ///<param name="lpDCB">設備控制塊</param> ??????? [DllImport(DLLPATH)] ??????? private static extern bool SetCommState(int hFile, ref DCB lpDCB); ??????? ///<summary> ??????? ///讀取串口超時時間 ??????? ///</summary> ??????? ///<param name="hFile">通信設備句柄</param> ??????? ///<param name="lpCommTimeouts">超時時間</param> ??????? [DllImport(DLLPATH)] ??????? private static extern bool GetCommTimeouts(int hFile, ref COMMTIMEOUTS lpCommTimeouts); ??????? ///<summary> ??????? ///設置串口超時時間 ??????? ///</summary> ??????? ///<param name="hFile">通信設備句柄</param> ??????? ///<param name="lpCommTimeouts">超時時間</param> ??????? [DllImport(DLLPATH)] ??????? private static extern bool SetCommTimeouts(int hFile, ref COMMTIMEOUTS lpCommTimeouts); ??????? ///<summary> ??? ????///讀取串口數(shù)據(jù) ??????? ///</summary> ??????? ///<param name="hFile">通信設備句柄</param> ??????? ///<param name="lpBuffer">數(shù)據(jù)緩沖區(qū)</param> ??????? ///<param name="nNumberOfBytesToRead">多少字節(jié)等待讀取</param> ??????? ///<param name="lpNumberOfBytesRead">讀取多少字節(jié)</param> ??????? ///<param name="lpOverlapped">溢出緩沖區(qū)</param> ??????? [DllImport(DLLPATH)] ??????? private static extern bool ReadFile(int hFile, byte[] lpBuffer, int nNumberOfBytesToRead, ??????? ref int lpNumberOfBytesRead, ref OVERLAPPED lpOverlapped); ???? ???///<summary> ??????? ///寫串口數(shù)據(jù) ??????? ///</summary> ??????? ///<param name="hFile">通信設備句柄</param> ??????? ///<param name="lpBuffer">數(shù)據(jù)緩沖區(qū)</param> ??????? ///<param name="nNumberOfBytesToWrite">多少字節(jié)等待寫入</param> ??????? ///<param name="lpNumberOfBytesWritten">已經(jīng)寫入多少字節(jié)</param> ??????? ///<param name="lpOverlapped">溢出緩沖區(qū)</param> ??????? [DllImport(DLLPATH)] ??????? private static extern bool WriteFile(int hFile, byte[] lpBuffer, int nNumberOfBytesToWrite, ??????? ref int lpNumberOfBytesWritten, ref OVERLAPPED lpOverlapped); ??????? [DllImport(DLLPATH, SetLastError = true)] ??????? private static extern bool FlushFileBuffers(int hFile); ??????? [DllImport(DLLPATH, SetLastError = true)] ??????? private static extern bool PurgeComm(int hFile, uint dwFlags); ??????? ///<summary> ??????? ///關閉串口 ??????? ///</summary> ??????? ///<param name="hObject">通信設備句柄</param> ??????? [DllImport(DLLPATH)] ??????? private static extern bool CloseHandle(int hObject); ??????? ///<summary> ??????? ///得到串口最后一次返回的錯誤 ??????? ///</summary> ??????? [DllImport(DLLPATH)] ??????? private static extern uint GetLastError(); ??????? #endregion ??????? ///<summary> ??????? ///設置DCB標志位 ??????? ///</summary> ??????? ///<param name="whichFlag"></param> ??????? ///<param name="setting"></param> ??????? ///<param name="dcb"></param> ??????? internal void SetDcbFlag(int whichFlag, int setting, DCB dcb) ??????? { ??????????? uint num; ??????????? setting = setting << whichFlag; ??????????? if ((whichFlag == 4) || (whichFlag == 12)) ??????????? { ??????????????? num = 3; ??????????? } ??????????? else if (whichFlag == 15) ??????????? { ??????????????? num = 0x1ffff; ??????????? } ??????????? else ??????????? { ??????????????? num = 1; ??????????? } ??????????? dcb.flags &= ~(num << whichFlag); ??????????? dcb.flags |= (uint)setting; ??????? } ??????? ///<summary> ??????? ///建立與串口的連接 ??????? ///</summary> ??????? public int Open() ??????? { ??????????? DCB dcb = new DCB(); ??????????? COMMTIMEOUTS ctoCommPort = new COMMTIMEOUTS(); ??????????? // 打開串口 ??????????? hComm = CreateFile(Port, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); ??????????? if (hComm == INVALID_HANDLE_VALUE) ??????????? { ??????????????? return -1; ??????????? } ??????????? // 設置通信超時時間 ??????? ????GetCommTimeouts(hComm, ref ctoCommPort); ??????????? ctoCommPort.ReadTotalTimeoutConstant = ReadTimeout; ??????????? ctoCommPort.ReadTotalTimeoutMultiplier = 0; ??????????? ctoCommPort.WriteTotalTimeoutMultiplier = 0; ??????????? ctoCommPort.WriteTotalTimeoutConstant = 0; ??????????? SetCommTimeouts(hComm, ref ctoCommPort); ??????????? //設置串口參數(shù) ??????????? GetCommState(hComm, ref dcb); ??????????? dcb.DCBlength = Marshal.SizeOf(dcb); ??????????? dcb.BaudRate = BaudRate; ??????????? dcb.flags = 0; ???? ???????dcb.ByteSize = (byte)ByteSize; ??????????? dcb.StopBits = StopBits; ??????????? dcb.Parity = (byte)Parity; ??????????? //------------------------------ ??????????? SetDcbFlag(0, 1, dcb);??????????? //二進制方式 ??????????? SetDcbFlag(1, (Parity == 0) ? 0 : 1, dcb); ??????????? SetDcbFlag(2, 0, dcb);??????????? //不用CTS檢測發(fā)送流控制 ??????????? SetDcbFlag(3, 0, dcb);??????????? //不用DSR檢測發(fā)送流控制 ??????????? SetDcbFlag(4, 0, dcb);??????????? //禁止DTR流量控制 ??????????? SetDcbFlag(6, 0, dcb);??????????? //對DTR信號線不敏感 ?? ?????????SetDcbFlag(9, 1, dcb);??????????? //檢測接收緩沖區(qū) ??????????? SetDcbFlag(8, 0, dcb);??????????? //不做發(fā)送字符控制 ??????????? SetDcbFlag(10, 0, dcb);?????????? //是否用指定字符替換校驗錯的字符 ??????????? SetDcbFlag(11, 0, dcb);?????????? //保留NULL字符 ??????????? SetDcbFlag(12, 0, dcb);?????????? //允許RTS流量控制 ??????????? SetDcbFlag(14, 0, dcb);?????????? //發(fā)送錯誤后,繼續(xù)進行下面的讀寫操作 ??????????? //-------------------------------- ??????????? dcb.wReserved = 0;?????????????????????? //沒有使用,必須為0?????? ??????????? dcb.XonLim = 0;??????????????? ??????????//指定在XOFF字符發(fā)送之前接收到緩沖區(qū)中可允許的最小字節(jié)數(shù) ??????????? dcb.XoffLim = 0;???????????????????????? //指定在XOFF字符發(fā)送之前緩沖區(qū)中可允許的最小可用字節(jié)數(shù) ??????????? dcb.XonChar = 0;???????????????????????? //發(fā)送和接收的XON字符 ??????????? dcb.XoffChar = 0;??????????????????????? //發(fā)送和接收的XOFF字符 ??????????? dcb.ErrorChar = 0;?????????????????????? //代替接收到奇偶校驗錯誤的字符 ??????????? dcb.EofChar = 0;???????????????????????? //用來表示數(shù)據(jù)的結束????? ??????????? dcb.EvtChar = 0;???????????????????????? //事件字符,接收到此字符時,會產(chǎn)生一個事件??????? ??????????? dcb.wReserved1 = 0;?? ???????????????????//沒有使用 ??????????? if (!SetCommState(hComm, ref dcb)) ??????????? { ??????????????? return -2; ??????????? } ??????????? Opened = true; ??????????? return 0; ??????? } ??????? ///<summary> ??????? ///關閉串口,結束通訊 ??????? ///</summary> ??????? public void Close() ??????? { ??????????? if (hComm != INVALID_HANDLE_VALUE) ??????????? { ??????????????? CloseHandle(hComm); ??????????? } ??????? } ??????? ///<summary> ??????? ///讀取串口返回的數(shù)據(jù) ??????? ///</summary> ??????? ///<param name="NumBytes">數(shù)據(jù)長度</param> ??????? public int Read(ref byte[] bytData, int NumBytes) ??????? { ??????????? if (hComm != INVALID_HANDLE_VALUE) ??????????? { ??????????????? OVERLAPPED ovlCommPort = new OVERLAPPED(); ??????????????? int BytesRead = 0; ?????????????? ?ReadFile(hComm, bytData, NumBytes, ref BytesRead, ref ovlCommPort); ??????????????? return BytesRead; ??????????? } ??????????? else ??????????? { ??????????????? return -1; ??????????? } ??????? } ??????? ///<summary> ??????? ///向串口寫數(shù)據(jù) ??????? ///</summary> ??????? ///<param name="WriteBytes">數(shù)據(jù)數(shù)組</param> ??????? public int Write(byte[] WriteBytes, int intSize) ??????? { ??????????? if (hComm != INVALID_HANDLE_VALUE) ??????????? { ??????????????? OVERLAPPED ovlCommPort = new OVERLAPPED(); ?????????? ?????int BytesWritten = 0; ??????????????? WriteFile(hComm, WriteBytes, intSize, ref BytesWritten, ref ovlCommPort); ??????????????? return BytesWritten; ??????????? } ??????????? else ??????????? { ??????????????? return -1; ??????????? } ??????? } ???? ???///<summary> ??????? ///清除接收緩沖區(qū) ??????? ///</summary> ??????? ///<returns></returns> ??????? public void ClearReceiveBuf() ??????? { ??????????? if (hComm != INVALID_HANDLE_VALUE) ??????????? { ??????????????? PurgeComm(hComm, PURGE_RXABORT | PURGE_RXCLEAR); ??????????? } ??????? } ??????? ///<summary> ??????? ///清除發(fā)送緩沖區(qū) ??????? ///</summary> ??????? public void ClearSendBuf() ??????? { ??????????? if (hComm != INVALID_HANDLE_VALUE) ??????????? { ??????????????? PurgeComm(hComm, PURGE_TXABORT | PURGE_TXCLEAR); ??????????? } ??????? } ?} 后記:我的串口程序修改為API方式后,實際發(fā)現(xiàn)與SerialPort類遇到同樣的問題,所以SerialPort類還是值得信任的。該API方式的代碼在WinCE平臺和PC平臺都調(diào)試通過。 ? posted on 2018-09-30 08:58 NET未來之路 閱讀(...) 評論(...) 編輯 收藏
轉載于:https://www.cnblogs.com/lonelyxmas/p/9727888.html
總結
以上是生活随笔為你收集整理的c#调api串口通讯的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Luogu 1351] NOIP201
- 下一篇: Xcode9 LaunchScreen.