本站首页    管理页面    写新日志    退出


«July 2025»
12345
6789101112
13141516171819
20212223242526
2728293031


公告

谦卑,荣誉,牺牲,英勇,怜悯,诚实,精神,公正。


我的分类(专题)

日志更新

最新评论

留言板

链接

 

 


Blog信息
blog名称:
日志总数:183
评论数量:698
留言数量:7
访问次数:3020143
建立时间:2005年12月29日




WINCE串口类
网上资源,  软件技术

newqiang 发表于 2006/9/20 21:40:02

将源代码稍作修改,以便能够在Windows CE环境内运行... 1.特点 我所见过的功能最完善,使用最简单,运行最稳定的串口通信类。 2.构成 Serial.h Serial.cpp SerialEx.h SerialEx.cpp SerialWnd.h SerialWnd.cpp SerialMFC.h 3.MFC CE使用方法 在CWnd窗口派生类中声明CSerialMFC的实例,如m_serial; 然后在Message Map中加入处理串口消息的Handler。 afx_msg LRESULT OnSerial(WPARAM wParam, LPARAM lParam); ON_WM_SERIAL(OnSerialMsg) 4.使用实例 class KSerial : public CWnd { // Construction public: KSerial(); // Attributes public: enum { TIMER_COMM_REQUEST = 1, TIMER_COMM_TIMEOUT, }; CONTROLSET m_controlSet; private: CSerialMFC m_serial; // Operations public: BOOL Connect(LPCTSTR lpszPort); BOOL Disconnect(); void SetTimeout(UINT nTimeout); void LoadSetting(); BOOL SaveSetting(); private: void ProcessResponse(); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(KSerial) //}}AFX_VIRTUAL // Implementation public: virtual ~KSerial(); // Generated message map functions protected: //{{AFX_MSG(KSerial) afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnTimer(UINT nIDEvent); //}}AFX_MSG afx_msg LRESULT OnSerialMsg(WPARAM wParam, LPARAM lParam); DECLARE_MESSAGE_MAP() }; BOOL KSerial::Connect(LPCTSTR lpszPort) { if (m_serial.IsOpen() == FALSE && m_serial.Open(lpszPort, this) != ERROR_SUCCESS) { return FALSE; } m_serial.Setup(CSerial::EBaud9600, CSerial::EData8, CSerial::EParOdd, CSerial::EStop1); m_serial.SetupHandshaking(CSerial::EHandshakeOff); m_serial.SetEventChar((BYTE)0x13); m_serial.SetMask(CSerial::EEventRcvEv); m_serial.Purge(); SetTimer(TIMER_COMM_REQUEST, m_controlSet.nRequestInterval, NULL); SetTimer(TIMER_WAFT_TIMER, 1000, NULL); m_controlSet.bPortOpen = TRUE; m_controlSet.bWaitForResponse = FALSE; m_controlSet.bErrorRetry = FALSE; return TRUE; } BOOL KSerial::Disconnect() { KillTimer(TIMER_COMM_REQUEST); KillTimer(TIMER_COMM_TIMEOUT); m_serial.Close(); return TRUE; } void KSerial::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default switch(nIDEvent) { case TIMER_COMM_REQUEST: if (m_controlSet.bPortOpen == TRUE && m_controlSet.bWaitForResponse == FALSE) { m_serial.Write("STM90FRDCMD002C6SP"); } break; case TIMER_COMM_TIMEOUT: KillTimer(TIMER_COMM_TIMEOUT); m_controlSet.bWaitForResponse = FALSE; break; } // switch (nIDEvent) CWnd::OnTimer(nIDEvent); } LRESULT KSerial::OnSerialMsg(WPARAM wParam, LPARAM lParam) { CSerial::EEvent eEvent = CSerial::EEvent(LOWORD(wParam)); CSerial::EError eError = CSerial::EError(HIWORD(wParam)); if (eEvent & CSerial::EEventRcvEv) { KillTimer(TIMER_COMM_TIMEOUT); // Create a clean buffer DWORD dwRead; char szData[101]; const int nBuflen = sizeof(szData)-1; // Obtain the data from the serial port do { m_serial.Read(szData,nBuflen,&dwRead); szData[dwRead] = '\0'; #ifdef _UNICODE // Convert the ANSI data to Unicode LPTSTR lpszData = LPTSTR(_alloca((dwRead+1)*sizeof(TCHAR))); if (!::MultiByteToWideChar(CP_ACP, 0, szData, -1, lpszData, dwRead+1)) return 0; CString strTemp; strTemp.Format(lpszData); m_controlSet.received += strTemp; #else CString strTemp(szData); m_controlSet.received += strTemp; #endif } while (dwRead == nBuflen); m_controlSet.response = m_controlSet.received; ProcessResponse(); m_controlSet.received.Empty(); m_controlSet.bWaitForResponse = FALSE; } return 0; } 完整的工程实例。。。谁能提供ftp上传并共享?      #ifndef __SERIAL_H #define __SERIAL_H class CSerial { // Class enumerations public: // Communication event typedef enum { EEventUnknown = -1, // Unknown event EEventNone = 0, // Event trigged without cause EEventBreak = EV_BREAK, // A break was detected on input EEventCTS = EV_CTS, // The CTS signal changed state EEventDSR = EV_DSR, // The DSR signal changed state EEventError = EV_ERR, // A line-status error occurred EEventRing = EV_RING, // A ring indicator was detected EEventRLSD = EV_RLSD, // The RLSD signal changed state EEventRecv = EV_RXCHAR, // Data is received on input EEventRcvEv = EV_RXFLAG, // Event character was received on input EEventSend = EV_TXEMPTY, // Last character on output was sent EEventPrinterError = EV_PERR, // Printer error occured EEventRx80Full = EV_RX80FULL, // Receive buffer is 80 percent full EEventProviderEvt1 = EV_EVENT1, // Provider specific event 1 EEventProviderEvt2 = EV_EVENT2, // Provider specific event 2 } EEvent; // Baudrate typedef enum { EBaudUnknown = -1, // Unknown EBaud110 = CBR_110, // 110 bits/sec EBaud300 = CBR_300, // 300 bits/sec EBaud600 = CBR_600, // 600 bits/sec EBaud1200 = CBR_1200, // 1200 bits/sec EBaud2400 = CBR_2400, // 2400 bits/sec EBaud4800 = CBR_4800, // 4800 bits/sec EBaud9600 = CBR_9600, // 9600 bits/sec EBaud14400 = CBR_14400, // 14400 bits/sec EBaud19200 = CBR_19200, // 19200 bits/sec (default) EBaud38400 = CBR_38400, // 38400 bits/sec EBaud56000 = CBR_56000, // 56000 bits/sec EBaud57600 = CBR_57600, // 57600 bits/sec EBaud115200 = CBR_115200, // 115200 bits/sec EBaud128000 = CBR_128000, // 128000 bits/sec EBaud256000 = CBR_256000, // 256000 bits/sec } EBaudrate; // Data bits (5- typedef enum { EDataUnknown = -1, // Unknown EData5 = 5, // 5 bits per byte EData6 = 6, // 6 bits per byte EData7 = 7, // 7 bits per byte EData8 = 8 // 8 bits per byte (default) } EDataBits; // Parity scheme typedef enum { EParUnknown = -1, // Unknown EParNone = NOPARITY, // No parity (default) EParOdd = ODDPARITY, // Odd parity EParEven = EVENPARITY, // Even parity EParMark = MARKPARITY, // Mark parity EParSpace = SPACEPARITY // Space parity } EParity; // Stop bits typedef enum { EStopUnknown = -1, // Unknown EStop1 = ONESTOPBIT, // 1 stopbit (default) EStop1_5 = ONE5STOPBITS,// 1.5 stopbit EStop2 = TWOSTOPBITS // 2 stopbits } EStopBits; // Handshaking typedef enum { EHandshakeUnknown = -1, // Unknown EHandshakeOff = 0, // No handshaking EHandshakeHardware = 1, // Hardware handshaking (RTS/CTS) EHandshakeSoftware = 2 // Software handshaking (XON/XOFF) } EHandshake; // Timeout settings typedef enum { EReadTimeoutUnknown = -1, // Unknown EReadTimeoutNonblocking = 0, // Always return immediately EReadTimeoutBlocking = 1 // Block until everything is retrieved } EReadTimeout; // Communication errors typedef enum { EErrorUnknown = 0, // Unknown EErrorBreak = CE_BREAK, // Break condition detected EErrorFrame = CE_FRAME, // Framing error EErrorIOE = CE_IOE, // I/O device error EErrorMode = CE_MODE, // Unsupported mode EErrorOverrun = CE_OVERRUN, // Character buffer overrun, next byte is lost EErrorRxOver = CE_RXOVER, // Input buffer overflow, byte lost EErrorParity = CE_RXPARITY,// Input parity error EErrorTxFull = CE_TXFULL // Output buffer full } EError; // Port availability typedef enum { EPortUnknownError = -1, // Unknown error occurred EPortAvailable = 0, // Port is available EPortNotAvailable = 1, // Port is not present EPortInUse = 2 // Port is in use } EPort; // Construction public: CSerial(); virtual ~CSerial(); // Operations public: // Check if particular COM-port is available (static method). static EPort CheckPort (LPCTSTR lpszDevice); // Open the serial communications for a particular COM port. You // need to use the full devicename (i.e. "COM1") to open the port. // It's possible to specify the size of the input/output queues. virtual LONG Open (LPCTSTR lpszDevice, DWORD dwInQueue = 0, DWORD dwOutQueue = 0); // Close the serial port. virtual LONG Close (void); // Setup the communication settings such as baudrate, databits, // parity and stopbits. The default settings are applied when the // device has been opened. Call this function if these settings do // not apply for your application. If you prefer to use integers // instead of the enumerated types then just cast the integer to // the required type. So the following two initializations are // equivalent: // // Setup(EBaud9600,EData8,EParNone,EStop1) // // or // // Setup(EBaudrate(9600),EDataBits(,EParity(NOPARITY),EStopBits(ONESTOPBIT)) // // In the latter case, the types are not validated. So make sure // that you specify the appropriate values. virtual LONG Setup (EBaudrate eBaudrate = EBaud9600, EDataBits eDataBits = EData8, EParity eParity = EParNone, EStopBits eStopBits = EStop1); // Set/clear the event character. When this byte is being received // on the serial port then the EEventRcvEv event is signalled, // when the mask has been set appropriately. If the fAdjustMask flag // has been set, then the event mask is automatically adjusted. virtual LONG SetEventChar (BYTE bEventChar, bool fAdjustMask = true); // Set the event mask, which indicates what events should be // monitored. The WaitEvent method can only monitor events that // have been enabled. The default setting only monitors the // error events and data events. An application may choose to // monitor CTS. DSR, RLSD, etc as well. virtual LONG SetMask (DWORD dwMask = EEventBreak|EEventError|EEventRecv); // The WaitEvent method waits for one of the events that are // enabled (see SetMask). virtual LONG WaitEvent (DWORD dwTimeout = INFINITE); // Setup the handshaking protocol. There are three forms of // handshaking: // // 1) No handshaking, so data is always send even if the receiver // cannot handle the data anymore. This can lead to data loss, // when the sender is able to transmit data faster then the // receiver can handle. // 2) Hardware handshaking, where the RTS/CTS lines are used to // indicate if data can be sent. This mode requires that both // ports and the cable support hardware handshaking. Hardware // handshaking is the most reliable and efficient form of // handshaking available, but is hardware dependant. // 3) Software handshaking, where the XON/XOFF characters are used // to throttle the data. A major drawback of this method is that // these characters cannot be used for data anymore. virtual LONG SetupHandshaking (EHandshake eHandshake); // Read operations can be blocking or non-blocking. You can use // this method to setup wether to use blocking or non-blocking // reads. Non-blocking reads is the default, which is required // for most applications. // // 1) Blocking reads, which will cause the 'Read' method to block // until the requested number of bytes have been read. This is // useful if you know how many data you will receive. // 2) Non-blocking reads, which will read as many bytes into your // buffer and returns almost immediately. This is often the // preferred setting. virtual LONG SetupReadTimeouts (EReadTimeout eReadTimeout); // Obtain communication settings virtual EBaudrate GetBaudrate (void); virtual EDataBits GetDataBits (void); virtual EParity GetParity (void); virtual EStopBits GetStopBits (void); virtual EHandshake GetHandshaking (void); virtual DWORD GetEventMask (void); virtual BYTE GetEventChar (void); // Write data to the serial port. Note that we are only able to // send ANSI strings, because it probably doesn't make sense to // transmit Unicode strings to an application. virtual LONG Write (const void* pData, size_t iLen, DWORD* pdwWritten = 0, DWORD dwTimeout = INFINITE); virtual LONG Write (LPCSTR pString, DWORD* pdwWritten = 0, DWORD dwTimeout = INFINITE); // Read data from the serial port. Refer to the description of // the 'SetupReadTimeouts' for an explanation about (non) blocking // reads and how to use this. virtual LONG Read (void* pData, size_t iLen, DWORD* pdwRead = 0, DWORD dwTimeout = INFINITE); // Send a break LONG Break (void); // Determine what caused the event to trigger EEvent GetEventType (void); // Obtain the error EError GetError (void); // Obtain the COMM and event handle HANDLE GetCommHandle (void) { return m_hFile; } // Check if com-port is opened bool IsOpen (void) const { return (m_hFile != 0); } // Obtain last error status LONG GetLastError (void) const { return m_lLastError; } // Obtain CTS/DSR/RING/RLSD settings bool GetCTS (void); bool GetDSR (void); bool GetRing (void); bool GetRLSD (void); // Purge all buffers LONG Purge (void); protected: // Internal helper class which wraps DCB structure class CDCB : public DCB { public: CDCB() { DCBlength = sizeof(DCB); } }; // Attributes protected: LONG m_lLastError; // Last serial error HANDLE m_hFile; // File handle EEvent m_eEvent; // Event type DWORD m_dwEventMask; // Event mask }; #endif // __SERIAL_H       本贴发表时间:2004-10-28 9:23:16      blueroy      等级: 论坛游民贴子:77积分:103微码币:26注册:2004-7-2              第 3 楼    /* #define STRICT #include <crtdbg.h> #include <tchar.h> #include <windows.h> */ #include "StdAfx.h" ////////////////////////////////////////////////////////////////////// // Include module headerfile #include "Serial.h" ////////////////////////////////////////////////////////////////////// // Enable debug memory manager #ifdef _DEBUG #ifdef THIS_FILE #undef THIS_FILE #endif static const char THIS_FILE[] = __FILE__; #define new DEBUG_NEW #endif CSerial::CSerial () : m_lLastError(ERROR_SUCCESS) , m_hFile(0) , m_eEvent(EEventNone) , m_dwEventMask(0) { } CSerial::~CSerial () { // If the device is already closed, // then we don't need to do anything. if (m_hFile) { // Close implicitly Close(); } } CSerial::EPort CSerial::CheckPort (LPCTSTR lpszDevice) { // Try to open the device HANDLE hFile = ::CreateFile(lpszDevice, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); // Check if we could open the device if (hFile == INVALID_HANDLE_value) { // Display error switch (::GetLastError()) { case ERROR_FILE_NOT_FOUND: // The specified COM-port does not exist return EPortNotAvailable; case ERROR_ACCESS_DENIED: // The specified COM-port is in use return EPortInUse; default: // Something else is wrong return EPortUnknownError; } } // Close handle ::CloseHandle(hFile); // Port is available return EPortAvailable; } LONG CSerial::Open (LPCTSTR lpszDevice, DWORD dwInQueue, DWORD dwOutQueue) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the port isn't already opened if (m_hFile) { m_lLastError = ERROR_ALREADY_INITIALIZED; AfxMessageBox(TEXT("COM1 already initialized")); return m_lLastError; } // Open the device m_hFile = ::CreateFile(lpszDevice, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if (m_hFile == INVALID_HANDLE_value) { // Reset file handle m_hFile = 0; // Get error m_lLastError = ::GetLastError(); AfxMessageBox(TEXT("Failed to create file")); return m_lLastError; } // Setup the COM-port if (dwInQueue || dwOutQueue) { // Make sure the queue-sizes are reasonable sized. Win9X systems crash // if the input queue-size is zero. Both queues need to be at least // 16 bytes large. _ASSERTE(dwInQueue >= 16); _ASSERTE(dwOutQueue >= 16); if (!::SetupComm(m_hFile,dwInQueue,dwOutQueue)) { // Get error long lLastError = ::GetLastError(); // Close the port Close(); // Save last error from SetupComm m_lLastError = lLastError; AfxMessageBox(TEXT("Failed to setup com1")); return m_lLastError; } } // Setup the default communication mask SetMask(); // Non-blocking reads is default SetupReadTimeouts(EReadTimeoutNonblocking); // Return successful return m_lLastError; } LONG CSerial::Close (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // If the device is already closed, // then we don't need to do anything. if (m_hFile == 0) { return m_lLastError; } // Close COM port ::CloseHandle(m_hFile); m_hFile = 0; // Return successful return m_lLastError; } LONG CSerial::Setup (EBaudrate eBaudrate, EDataBits eDataBits, EParity eParity, EStopBits eStopBits) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; return m_lLastError; } // Obtain the DCB structure for the device CDCB dcb; if (!::GetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = :: GetLastError(); return m_lLastError; } // Set the new data dcb.BaudRate = DWORD(eBaudrate); dcb.ByteSize = BYTE(eDataBits); dcb.Parity = BYTE(eParity); dcb.StopBits = BYTE(eStopBits); // Determine if parity is used dcb.fParity = (eParity != EParNone); // Set the new DCB structure if (!::SetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); return m_lLastError; } // Return successful return m_lLastError; } LONG CSerial::SetEventChar (BYTE bEventChar, bool fAdjustMask) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; return m_lLastError; } // Obtain the DCB structure for the device CDCB dcb; if (!::GetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); return m_lLastError; } // Set the new event character dcb.EvtChar = char(bEventChar); // Adjust the event mask, to make sure the event will be received if (fAdjustMask) { // Enable 'receive event character' event. Note that this // will generate an EEventNone if there is an asynchronous // WaitCommEvent pending. SetMask(GetEventMask() | EEventRcvEv); } // Set the new DCB structure if (!::SetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); return m_lLastError; } // Return successful return m_lLastError; } LONG CSerial::SetMask (DWORD dwEventMask) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; return m_lLastError; } // Set the new mask. Note that this will generate an EEventNone // if there is an asynchronous WaitCommEvent pending. if (!::SetCommMask(m_hFile,dwEventMask)) { // Obtain the error code m_lLastError = ::GetLastError(); return m_lLastError; } // Save event mask and return successful m_dwEventMask = dwEventMask; return m_lLastError; } LONG CSerial::WaitEvent (DWORD dwTimeout) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; return m_lLastError; } // Wait for the COM event if (!::WaitCommEvent(m_hFile,LPDWORD(&m_eEvent),0)) { // Set the internal error code m_lLastError = ::GetLastError(); return m_lLastError; }        本贴发表时间:2004-10-28 9:24:16      blueroy      等级: 论坛游民贴子:77积分:103微码币:26注册:2004-7-2              第 4 楼    // Return successfully return m_lLastError; } LONG CSerial::SetupHandshaking (EHandshake eHandshake) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; return m_lLastError; } // Obtain the DCB structure for the device CDCB dcb; if (!::GetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); return m_lLastError; } // Set the handshaking flags switch (eHandshake) { case EHandshakeOff: dcb.fOutxCtsFlow = false; // Disable CTS monitoring dcb.fOutxDsrFlow = false; // Disable DSR monitoring dcb.fDtrControl = DTR_CONTROL_DISABLE; // Disable DTR monitoring dcb.fOutX = false; // Disable XON/XOFF for transmission dcb.fInX = false; // Disable XON/XOFF for receiving dcb.fRtsControl = RTS_CONTROL_DISABLE; // Disable RTS (Ready To Send) break; case EHandshakeHardware: dcb.fOutxCtsFlow = true; // Enable CTS monitoring dcb.fOutxDsrFlow = true; // Enable DSR monitoring dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; // Enable DTR handshaking dcb.fOutX = false; // Disable XON/XOFF for transmission dcb.fInX = false; // Disable XON/XOFF for receiving dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; // Enable RTS handshaking break; case EHandshakeSoftware: dcb.fOutxCtsFlow = false; // Disable CTS (Clear To Send) dcb.fOutxDsrFlow = false; // Disable DSR (Data Set Ready) dcb.fDtrControl = DTR_CONTROL_DISABLE; // Disable DTR (Data Terminal Ready) dcb.fOutX = true; // Enable XON/XOFF for transmission dcb.fInX = true; // Enable XON/XOFF for receiving dcb.fRtsControl = RTS_CONTROL_DISABLE; // Disable RTS (Ready To Send) break; default: // This shouldn't be possible _ASSERTE(false); m_lLastError = E_INVALIDARG; return m_lLastError; } // Set the new DCB structure if (!::SetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); return m_lLastError; } // Return successful return m_lLastError; } LONG CSerial::SetupReadTimeouts (EReadTimeout eReadTimeout) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; return m_lLastError; } // Determine the time-outs COMMTIMEOUTS cto; if (!::GetCommTimeouts(m_hFile,&cto)) { // Obtain the error code m_lLastError = ::GetLastError(); return m_lLastError; } // Set the new timeouts switch (eReadTimeout) { case EReadTimeoutBlocking: cto.ReadIntervalTimeout = 0; cto.ReadTotalTimeoutConstant = 0; cto.ReadTotalTimeoutMultiplier = 0; break; case EReadTimeoutNonblocking: cto.ReadIntervalTimeout = MAXDWORD; cto.ReadTotalTimeoutConstant = 0; cto.ReadTotalTimeoutMultiplier = 0; break; default: // This shouldn't be possible _ASSERTE(false); m_lLastError = E_INVALIDARG; return m_lLastError; } // Set the new DCB structure if (!::SetCommTimeouts(m_hFile,&cto)) { // Obtain the error code m_lLastError = ::GetLastError(); return m_lLastError; } // Return successful return m_lLastError; } CSerial::EBaudrate CSerial::GetBaudrate (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; return EBaudUnknown; } // Obtain the DCB structure for the device CDCB dcb; if (!::GetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); return EBaudUnknown; } // Return the appropriate baudrate return EBaudrate(dcb.BaudRate); } CSerial::EDataBits CSerial::GetDataBits (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; return EDataUnknown; } // Obtain the DCB structure for the device CDCB dcb; if (!::GetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); return EDataUnknown; } // Return the appropriate bytesize return EDataBits(dcb.ByteSize); } CSerial::EParity CSerial::GetParity (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; return EParUnknown; } // Obtain the DCB structure for the device CDCB dcb; if (!::GetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); return EParUnknown; } // Check if parity is used if (!dcb.fParity) { // No parity return EParNone; } // Return the appropriate parity setting return EParity(dcb.Parity); } CSerial::EStopBits CSerial::GetStopBits (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; return EStopUnknown; } // Obtain the DCB structure for the device CDCB dcb; if (!::GetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); return EStopUnknown; } // Return the appropriate stopbits return EStopBits(dcb.StopBits); } DWORD CSerial::GetEventMask (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; return 0; } // Return the event mask return m_dwEventMask; } BYTE CSerial::GetEventChar (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; return 0; } // Obtain the DCB structure for the device CDCB dcb; if (!::GetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); return 0; } // Set the new event character return BYTE(dcb.EvtChar); } CSerial::EHandshake CSerial::GetHandshaking (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; return EHandshakeUnknown; } // Obtain the DCB structure for the device CDCB dcb; if (!::GetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); return EHandshakeUnknown; } // Check if hardware handshaking is being used if ((dcb.fDtrControl == DTR_CONTROL_HANDSHAKE) && (dcb.fRtsControl == RTS_CONTROL_HANDSHAKE)) return EHandshakeHardware; // Check if software handshaking is being used if (dcb.fOutX && dcb.fInX) return EHandshakeSoftware; // No handshaking is being used return EHandshakeOff; } LONG CSerial::Write (const void* pData, size_t iLen, DWORD* pdwWritten, DWORD dwTimeout) { // Reset error state m_lLastError = ERROR_SUCCESS; // Use our own variable for read count DWORD dwWritten; if (pdwWritten == 0) { pdwWritten = &dwWritten; } // Reset the number of bytes written *pdwWritten = 0; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; return m_lLastError; } // Write the data if (!::WriteFile(m_hFile,pData,iLen,pdwWritten,0)) { // Set the internal error code m_lLastError = ::GetLastError(); return m_lLastError; } // Return successfully return m_lLastError; } LONG CSerial::Write (LPCSTR pString, DWORD* pdwWritten, DWORD dwTimeout) { // Determine the length of the string return Write(pString,strlen(pString),pdwWritten,dwTimeout); } LONG CSerial::Read (void* pData, size_t iLen, DWORD* pdwRead, DWORD dwTimeout) { // Reset error state m_lLastError = ERROR_SUCCESS; // Use our own variable for read count DWORD dwRead; if (pdwRead == 0) { pdwRead = &dwRead; } // Reset the number of bytes read *pdwRead = 0; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; return m_lLastError; } #ifdef _DEBUG // The debug version fills the entire data structure with // 0xDC bytes, to catch buffer errors as soon as possible. memset(pData,0xDC,iLen); #endif // Read the data if (!::ReadFile(m_hFile,pData,iLen,pdwRead,0)) { // Set the internal error code m_lLastError = ::GetLastError(); return m_lLastError; } // Return successfully return m_lLastError; } LONG CSerial::Purge() { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; return m_lLastError; } if (!::PurgeComm(m_hFile, PURGE_TXCLEAR | PURGE_RXCLEAR)) { // Set the internal error code m_lLastError = ::GetLastError(); } // Return successfully return m_lLastError; } LONG CSerial::Break (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; return m_lLastError; } // Set the RS-232 port in break mode for a little while ::SetCommBreak(m_hFile); ::Sleep(100); ::ClearCommBreak(m_hFile); // Return successfully return m_lLastError; } CSerial::EEvent CSerial::GetEventType (void) { // Obtain the event (mask unwanted events out) EEvent eEvent = EEvent(m_eEvent & m_dwEventMask); // Reset internal event type m_eEvent = EEventNone; // Return the current cause return eEvent; } CSerial::EError CSerial::GetError (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; return EErrorUnknown; } // Obtain COM status DWORD dwErrors = 0; if (!::ClearCommError(m_hFile,&dwErrors,0)) { // Set the internal error code m_lLastError = ::GetLastError(); return EErrorUnknown; } // Return the error return EError(dwErrors); } bool CSerial::GetCTS (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Obtain the modem status DWORD dwModemStat = 0; if (!::GetCommModemStatus(m_hFile,&dwModemStat)) { // Obtain the error code m_lLastError = ::GetLastError(); return false; } // Determine if CTS is on return (dwModemStat & MS_CTS_ON) != 0; } bool CSerial::GetDSR (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Obtain the modem status DWORD dwModemStat = 0; if (!::GetCommModemStatus(m_hFile,&dwModemStat)) { // Obtain the error code m_lLastError = ::GetLastError(); return false; } // Determine if DSR is on return (dwModemStat & MS_DSR_ON) != 0; } bool CSerial::GetRing (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Obtain the modem status DWORD dwModemStat = 0; if (!::GetCommModemStatus(m_hFile,&dwModemStat)) { // Obtain the error code m_lLastError = ::GetLastError(); return false; } // Determine if Ring is on return (dwModemStat & MS_RING_ON) != 0; } bool CSerial::GetRLSD (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Obtain the modem status DWORD dwModemStat = 0; if (!::GetCommModemStatus(m_hFile,&dwModemStat)) { // Obtain the error code m_lLastError = ::GetLastError(); return false; } // Determine if RLSD is on return (dwModemStat & MS_RLSD_ON) != 0; }       本贴发表时间:2004-10-28 9:24:49      blueroy      等级: 论坛游民贴子:77积分:103微码币:26注册:2004-7-2              第 5 楼    #ifndef __SERIAL_EX_H #define __SERIAL_EX_H ////////////////////////////////////////////////////////////////////// // Include CSerial base class #include "Serial.h" class CSerialEx : public CSerial { public: CSerialEx(); virtual ~CSerialEx(); // Operations public: // Open the serial communications for a particular COM port. You // need to use the full devicename (i.e. "COM1") to open the port. virtual LONG Open (LPCTSTR lpszDevice, DWORD dwInQueue = 0, DWORD dwOutQueue = 0, bool fStartListener = false); // Close the serial port. virtual LONG Close (void); // Start the listener thread virtual LONG StartListener (void); // Stop the listener thread. Because the other thread might be // busy processing data it might take a while, so you can specify // a time-out. virtual LONG StopListener (DWORD dwTimeout = INFINITE); protected: // Each opened COM-port uses its own specific thread, which will // wait for one of the events to happen. When an event happens, // then the client window is send a message informing about the // event. static DWORD WINAPI ThreadProc (LPVOID lpArg); DWORD ThreadProc (void); // Event handler virtual void OnEvent (EEvent eEvent, EError eError) = 0; protected: // The WaitEvent method is being used by this class internally // and shouldn't be used by client applications. Client // application should monior the messages. using CSerial::WaitEvent; // The event-type is send in the WPARAM of the message and // the GetEventType method returns the wrong data, so we'll // hide this method for client applications to avoid problems. using CSerial::GetEventType; using CSerial::GetError; protected: // Internal attributes bool m_fStopping; HANDLE m_hThread; }; #endif // __SERIAL_EX_H       本贴发表时间:2004-10-28 9:25:16      blueroy      等级: 论坛游民贴子:77积分:103微码币:26注册:2004-7-2              第 6 楼    /* #define STRICT #include <crtdbg.h> #include <tchar.h> #include <windows.h> */ #include "StdAfx.h" ////////////////////////////////////////////////////////////////////// // Include module headerfile #include "SerialEx.h" ////////////////////////////////////////////////////////////////////// // Enable debug memory manager #ifdef _DEBUG #ifdef THIS_FILE #undef THIS_FILE #endif static const char THIS_FILE[] = __FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CSerialEx::CSerialEx() : m_fStopping(false) , m_hThread(0) { } CSerialEx::~CSerialEx() { // Check if the thread handle is still there. If so, then we // didn't close the serial port. We cannot depend on the // CSerial destructor, because if it calls Close then it // won't call our overridden Close. if (m_hThread) { // Close implicitly Close(); } } LONG CSerialEx::Open (LPCTSTR lpszDevice, DWORD dwInQueue, DWORD dwOutQueue, bool fStartListener) { // Call the base class first long lLastError = CSerial::Open(lpszDevice,dwInQueue,dwOutQueue); if (lLastError != ERROR_SUCCESS) return lLastError; // Start the listener thread (only on request) if (fStartListener) { lLastError = StartListener(); if (lLastError != ERROR_SUCCESS) return lLastError; } // Return the error return m_lLastError; } LONG CSerialEx::Close (void) { // Stop listener thread (wait until it ends) StopListener(INFINITE); // Call the base class return CSerial::Close(); } LONG CSerialEx::StartListener (void) { // Check if the watcher thread was already running if (m_hThread == 0) { // Make sure the thread has stopped _ASSERTE(!m_fStopping); // Start the watcher thread DWORD dwThreadId = 0; m_hThread = ::CreateThread(0,0,ThreadProc,LPVOID(this),0,&dwThreadId); if (m_hThread == 0) { // Set the error code and exit m_lLastError = ::GetLastError(); return m_lLastError; } } // Return the error m_lLastError = ERROR_SUCCESS; return m_lLastError; } LONG CSerialEx::StopListener (DWORD dwTimeout) { // Check if the thread is running if (m_hThread) { // Set the flag that the thread must be stopped m_fStopping = true; // Cancel the pending WaitEvent, but we won't do this using // CancelIo. This would break Win95 compatibility and some // USB serial dongles cannot handle CancelIo correctly. By // setting the event mask again, the call will also be // completed before the thread exits. SetMask(GetEventMask()); // Wait until the watcher thread has stopped ::WaitForSingleObject(m_hThread,dwTimeout); // The thread has stopped m_fStopping = false; // Close handle to the thread ::CloseHandle(m_hThread); m_hThread = 0; } // Return the error m_lLastError = ERROR_SUCCESS; return m_lLastError; } DWORD WINAPI CSerialEx::ThreadProc (LPVOID lpArg) { // Route the method to the actual object CSerialEx* pThis = reinterpret_cast<CSerialEx*>(lpArg); return pThis->ThreadProc(); } DWORD CSerialEx::ThreadProc (void) { // Use overlapped structure LPOVERLAPPED lpOverlapped = 0; // Keep looping do { // Start the WaitEvent (don't need to specify an overlapped structure) if (WaitEvent() != ERROR_SUCCESS) return m_lLastError; // Wait until one of the events happens if (!m_fStopping) { // Determine the event EEvent eEvent = GetEventType(); // Obtain the error status during this event DWORD dwErrors = 0; if (!::ClearCommError(m_hFile,&dwErrors,0)) { // Set the internal error code m_lLastError = ::GetLastError(); } // Convert the error EError eError = EError(dwErrors); // There was a COMM event, which needs handling. We'll call the // event handler. We can receive a "zero" event, when the // mask or event character has been set. We won't pass this // down to the window. if (eEvent) OnEvent(eEvent,eError); } } while (!m_fStopping); // Bye bye return 0; }       本贴发表时间:2004-10-28 9:25:46      blueroy      等级: 论坛游民贴子:77积分:103微码币:26注册:2004-7-2              第 7 楼    #ifndef __SERIAL_WND_H #define __SERIAL_WND_H ////////////////////////////////////////////////////////////////////// // Include CSerialEx base class #include "SerialEx.h" class CSerialWnd : public CSerialEx { // Construction public: CSerialWnd(); virtual ~CSerialWnd(); // Operations public: // Open the serial communications for a particular COM port. You // need to use the full devicename (i.e. "COM1") to open the port. virtual LONG Open (LPCTSTR lpszDevice, HWND hwndDest, UINT nComMsg=WM_NULL, LPARAM lParam=0, DWORD dwInQueue = 0, DWORD dwOutQueue = 0); // Close the serial port. virtual LONG Close (void); protected: // Event handler that is called when virtual void OnEvent (EEvent eEvent, EError eError); public: // Default Serial notification message static const UINT mg_nDefaultComMsg; protected: // Internal attributes HWND m_hwndDest; UINT m_nComMsg; LONG m_lParam; }; #endif // __SERIAL_WND_H       本贴发表时间:2004-10-28 9:26:24      blueroy      等级: 论坛游民贴子:77积分:103微码币:26注册:2004-7-2              第 8 楼    ////////////////////////////////////////////////////////////////////// // Include the standard header files /* #define STRICT #include <crtdbg.h> #include <tchar.h> #include <windows.h> */ #include "StdAfx.h" ////////////////////////////////////////////////////////////////////// // Include module headerfile #include "SerialWnd.h" ////////////////////////////////////////////////////////////////////// // Enable debug memory manager #ifdef _DEBUG #ifdef THIS_FILE #undef THIS_FILE #endif static const char THIS_FILE[] = __FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Code // Register the standard CSerialWnd COM message const UINT CSerialWnd::mg_nDefaultComMsg = ::RegisterWindowMessage(_T("CSerialWnd_DefaultComMsg")); CSerialWnd::CSerialWnd() : m_hwndDest(0) , m_nComMsg(WM_NULL) , m_lParam(0) { } CSerialWnd::~CSerialWnd() { // Check if the thread handle is still there. If so, then we // didn't close the serial port. We cannot depend on the // CSerial destructor, because if it calls Close then it // won't call our overridden Close. if (m_hThread) { // Close implicitly Close(); } } LONG CSerialWnd::Open (LPCTSTR lpszDevice, HWND hwndDest, UINT nComMsg, LPARAM lParam, DWORD dwInQueue, DWORD dwOutQueue) { // Call the base class first long lLastError = CSerialEx::Open(lpszDevice,dwInQueue,dwOutQueue); if (lLastError != ERROR_SUCCESS) return lLastError; // Save the window handle, notification message and user message m_hwndDest = hwndDest; m_nComMsg = nComMsg?nComMsg:mg_nDefaultComMsg; m_lParam = lParam; // Start the listener thread lLastError = StartListener(); if (lLastError != ERROR_SUCCESS) { // Close the serial port Close(); // Return the error-code m_lLastError = lLastError; return m_lLastError; } // Return the error m_lLastError = ERROR_SUCCESS; return m_lLastError; } LONG CSerialWnd::Close (void) { // Reset all members m_hwndDest = 0; m_nComMsg = WM_NULL; // Call the base class return CSerialEx::Close(); } void CSerialWnd::OnEvent (EEvent eEvent, EError eError) { // Post message to the client window ::PostMessage(m_hwndDest,m_nComMsg,MAKEWPARAM(eEvent,eError),LPARAM(m_lParam)); }       本贴发表时间:2004-10-28 9:26:55      blueroy      等级: 论坛游民贴子:77积分:103微码币:26注册:2004-7-2              第 9 楼    // SerialMFC.h - Definition of the CSerialMFC class // // Copyright (C) 1999-2003 Ramon de Klein (Ramon.de.Klein@ict.nl) // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #ifndef __SERIAL_MFC_H #define __SERIAL_MFC_H ////////////////////////////////////////////////////////////////////// // Include CSerialWnd base class #include "SerialWnd.h" ////////////////////////////////////////////////////////////////////// // Make sure that MFC is already loaded // // We don't include it here, because MFC based applications typically // use a precompiled header file. #ifndef __AFXWIN_H__ #error "CWnd class isn't included (include AFXWIN.H)" #endif ////////////////////////////////////////////////////////////////////// // // CSerialMFC - MFC wrapper for serial communication handling // // CSerialMFC is a very thing wrapper around the CSerialWnd class, // which makes it more suitable for use in MFC-based applications. // Unfortenately, the MFC framework isn't very flexible when it comes // to adding custom message handlers. We cannot add our own types to // the message handlers, but we're stuck to use 32-bit integers. // // Add the following entry to the window's message map to make sure // that MFC calls your handler, when a serial message comes in. // // DECLARE_MESSAGE_MAP(CMyClass,CWnd) // ... // ON_WM_SERIAL(OnSerialMsg) // ... // END_MESSAGE_MAP() // // A typical handler could look like this: // // afx_msg LRESULT CMyClass::OnSerialMsg (WPARAM wParam, LPARAM lParam) // { // CSerial::EEvent eEvent = CSerial::EEvent(LOWORD(wParam)); // CSerial::EError eError = CSerial::EError(HIWORD(wParam)); // // // lParam: User-defined 32-bit integer (type LPARAM) // switch (eEvent) // { // case CSerialMFC::EEventRecv: // // TODO: Read data from the port // break; // ... // } // // // Return successful // return 0; // } // // // Pros: // ----- // - Easy to use // - Fully ANSI and Unicode aware // - Integrates seamless in MFC applications // // Cons: // ----- // - No more then CSerialWnd, except that you need MFC // // Copyright (C) 1999-2003 Ramon de Klein // (Ramon.de.Klein@ict.nl) class CSerialMFC : public CSerialWnd { // Operations public: // Open the serial communications for a particular COM port. You // need to use the full devicename (i.e. "COM1") to open the port. virtual LONG Open (LPCTSTR lpszDevice, CWnd* pwndDest, UINT nComMsg = WM_NULL, LPARAM lParam = 0, DWORD dwInQueue = 0, DWORD dwOutQueue = 0) { return CSerialWnd::Open(lpszDevice,pwndDest->GetSafeHwnd(),nComMsg,lParam,dwInQueue,dwOutQueue); } }; ////////////////////////////////////////////////////////////////////// // Message map macro for the default COM message #define ON_WM_SERIAL(memberFxn) \ ON_REGISTERED_MESSAGE(CSerialMFC::mg_nDefaultComMsg,memberFxn) ////////////////////////////////////////////////////////////////////// // Don't link to the default runtime libraries, because this will // give a warning during link-time. #ifdef _DEBUG #pragma comment(linker,"/nodefaultlib:LIBCD") #else #pr


阅读全文(13160) | 回复(4) | 编辑 | 精华
 


回复:WINCE串口类
网上资源,  软件技术

老毛(游客)发表评论于2007/3/27 17:01:52

博主你好~ 我现在也正在将这个类移植到WinCE下..但有很多问题,你能将你的移植的类提供给我么? 谢谢你. 如果可以请发送到我的邮箱: ncsoft@263.net 再次感谢


个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除
 


回复:WINCE串口类
网上资源,  软件技术

max(游客)发表评论于2006/12/17 19:49:53

非常好,如果加些诸如报头、报尾处理的数据包会更完美些

个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除
 


回复:WINCE串口类
网上资源,  软件技术

wittman(游客)发表评论于2006/11/3 16:55:33

CONTROLSET 没有声明,怎么回事?

个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除
 


回复:WINCE串口类
网上资源,  软件技术

雯菲(游客)发表评论于2006/9/21 16:57:45

好复杂啊,看不懂!

个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除
 


» 1 »

发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.307 second(s), page refreshed 144775622 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号