« | July 2025 | » | 日 | 一 | 二 | 三 | 四 | 五 | 六 | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | | | |
| 公告 |
谦卑,荣誉,牺牲,英勇,怜悯,诚实,精神,公正。 |
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 |
|
回复: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 |
|
回复:WINCE串口类 网上资源, 软件技术
雯菲(游客)发表评论于2006/9/21 16:57:45 |
|
» 1 »
|