[WinCE]Windows CE下的串口通訊執行個體
來源:互聯網
上載者:User
Windows CE下的串口通訊執行個體 串列通訊是目前電腦、通訊和控制領域最基本的通訊方式。在CSDN的“嵌入式開發/WINCE”社區中,經常有人提問該到哪找串口通訊例子,其實這個問題我自己也問過。:)而一般的回答是給你提供一個Pocket PC 2002的SDK例子程式。但到底SDK的程式和MFC的結構有很大的不同,對於想用MFC編寫通訊程式的人來說也不是很便利。另一方面,由於Windows CE是一個基於Unicode的作業系統,並且Windows CE不支援Windows下常用的串列通訊重疊I/O方式(OVERLAPPED),因此編寫Windows CE下的串口通訊類有一些與案頭Windows不同的地方。以下是我從SDK程式改寫而來的MFC例子程式,希望能和致力於WINCE開發的朋友多多交流,由於本人才疏學淺,程式中有許多不完善的地方,請大家指正。我的程式是基於“主動發送請求,被動接收響應”的假設,因此我只設定了一個接收資料的線程。感謝“嵌入式開發/WINCE”社區為我提供SDK例子的朋友,感謝CSDN上所有熱心的朋友,祝願中國的軟硬體水平能早日擠身世界一流。 標頭檔Serial.h// Serial.h: interface for the CSerial class.//////////////////////////////////////////////////////////////////////// #if !defined(AFX_SERIAL_H__59575586_AAA9_4FEF_B2A7_E089553698EF__INCLUDED_)#define AFX_SERIAL_H__59575586_AAA9_4FEF_B2A7_E089553698EF__INCLUDED_ #if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000 DWORD WINAPI ReadPortThread(LPVOID lpvoid); //讀資料線程 class CSerial {public: BOOL InitCommTimeouts(); //設定逾時參數 BOOL InitDCB(); //配置串口 BOOL m_bConnected; BOOL ClosePort(HANDLE hCommPort); //關閉串口 DWORD WritePort(TCHAR *buf,DWORD dwBytesToWrite); //寫資料 BOOL OpenPort(LPTSTR lpszPortName); //開啟串口 CSerial(); HANDLE hReadThread; virtual ~CSerial(); }; #endif // !defined(AFX_SERIAL_H__59575586_AAA9_4FEF_B2A7_E089553698EF__INCLUDED_) 源檔案:Serial.cpp// Serial.cpp: implementation of the CSerial class.//////////////////////////////////////////////////////////////////////// #include "stdafx.h"#include "Serial.h" #ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;#define new DEBUG_NEW#endif HANDLE hPort;CString strInChar; //////////////////////////////////////////////////////////////////////// Construction/Destruction////////////////////////////////////////////////////////////////////// CSerial::CSerial(){ } CSerial::~CSerial(){ if(hPort != INVALID_HANDLE_VALUE) ClosePort(hPort);} BOOL CSerial::OpenPort(LPTSTR lpszPortName){ DWORD dwError, dwThreadID; if(hPort) { return FALSE; } //開啟串口 hPort = CreateFile (lpszPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,0, NULL); //如果開啟連接埠出錯, 返回FALSE if ( hPort == INVALID_HANDLE_VALUE ) { //不能開啟連接埠 CString strError; strError.Format(_T("Unable to open %s, Error No.=%d"), lpszPortName, GetLastError()); MessageBox (NULL, strError, TEXT("Error"), MB_OK); return FALSE; } //指定連接埠監測的事件集 SetCommMask (hPort, EV_RXCHAR); //分配裝置緩衝區 SetupComm(hPort,512,512); //初始化緩衝區中的資訊 PurgeComm(hPort,PURGE_TXCLEAR|PURGE_RXCLEAR); //配置序列埠 if(!InitDCB()) return FALSE; //設定連接埠逾時值 if(!InitCommTimeouts()) return FALSE; //設定連接埠上指定訊號的狀態 // SETDTR: 發送DTR (data-terminal-ready)訊號 // SETRTS: 發送RTS (request-to-send)訊號 EscapeCommFunction (hPort, SETDTR); EscapeCommFunction (hPort, SETRTS); //建立一個從串口讀取資料的線程 if (hReadThread = CreateThread (NULL, 0, ReadPortThread, 0, 0, &dwThreadID)) { } else { //不能建立線程 MessageBox (NULL, TEXT("Unable to create the read thread"), TEXT("Error"), MB_OK); dwError = GetLastError (); return FALSE; } m_bConnected=TRUE; return TRUE;} DWORD CSerial::WritePort(TCHAR *buf,DWORD dwCharToWrite){ BOOL fWriteState; DWORD dwBytesWritten; //寫入資料 fWriteState=WriteFile(hPort,buf,dwCharToWrite*sizeof(TCHAR),&dwBytesWritten,NULL); if(!fWriteState) { //不能寫資料 MessageBox(NULL,TEXT("Can't Write String to Comm"),TEXT("Error"),MB_OK); dwBytesWritten=0; } return dwBytesWritten;} DWORD WINAPI ReadPortThread(LPVOID lpvoid){ BOOL fReadState; DWORD dwCommModemStatus; DWORD dwLength; COMSTAT ComStat; DWORD dwErrorFlags; while (hPort != INVALID_HANDLE_VALUE) { //等待串口的事件發生 WaitCommEvent (hPort, &dwCommModemStatus, 0); if (dwCommModemStatus & EV_RXCHAR) { ClearCommError(hPort,&dwErrorFlags,&ComStat); //cbInQue返回在串列驅動程式輸入隊列中的字元數 dwLength=ComStat.cbInQue; if(dwLength>0) { //從串口讀取資料 TCHAR* buf=new TCHAR[256]; fReadState=ReadFile(hPort,buf,dwLength,&dwLength,NULL); if(!fReadState) { //不能從串口讀取資料 MessageBox(NULL,TEXT("Error in read from serial port"),TEXT("Read Error"),MB_OK); } else { //把資料賦值給全域變數 strInChar=buf; } delete[] buf; } } GetCommModemStatus (hPort, &dwCommModemStatus); } return 0;} BOOL CSerial::ClosePort(HANDLE hCommPort){ if (hCommPort != INVALID_HANDLE_VALUE) { //設定串連屬性為FALSE m_bConnected=FALSE; //結束線程中WaitCommEvent的等待 SetCommMask(hPort,0); //阻塞至線程停止 if(hReadThread) { TerminateThread(hReadThread,0); CloseHandle(hReadThread); } //清除連接埠上指定訊號的狀態 EscapeCommFunction(hPort,CLRDTR); EscapeCommFunction(hPort,CLRRTS); //清除驅動程式內部的發送和接收隊列 PurgeComm(hPort,PURGE_TXCLEAR|PURGE_RXCLEAR); //關閉串口 CloseHandle (hCommPort); hCommPort = INVALID_HANDLE_VALUE; return TRUE; } else { return TRUE; }} BOOL CSerial::InitDCB(){ DCB PortDCB; DWORD dwError; PortDCB.DCBlength = sizeof (DCB); //得到連接埠的預設設定資訊 GetCommState (hPort, &PortDCB); //改變DCB結構設定 PortDCB.BaudRate = 19200; //傳輸速率 PortDCB.fBinary = TRUE; //Win32不支援非二進位串列傳輸模式,必須為TRUE PortDCB.fParity = TRUE; //啟用同位 PortDCB.fOutxCtsFlow = TRUE; //序列埠的輸出由CTS線控制 PortDCB.fOutxDsrFlow = FALSE; //關閉序列埠的DSR流量控制 PortDCB.fDtrControl = DTR_CONTROL_ENABLE; //啟用DTR線 PortDCB.fDsrSensitivity = FALSE; //如果設為TRUE將忽略任何輸入的位元組,除非DSR線被啟用 //PortDCB.fTXContinueOnXoff = TRUE; //當為TRUE時,如果接收緩衝區已滿且驅動程式已傳送XOFF字元,將使驅動程式停止傳輸字元 PortDCB.fTXContinueOnXoff = FALSE; PortDCB.fOutX = FALSE; //設為TRUE指定XON/XOFF控制被用於控制串列輸出 PortDCB.fInX = FALSE; //設為TRUE指定XON/XOFF控制被用於控制串列輸入 PortDCB.fErrorChar = FALSE; //WINCE串列驅動程式的預設執行將忽略這個欄位 PortDCB.fNull = FALSE; //設為TRUE將使串列驅動程式忽略收到的空位元組 PortDCB.fRtsControl = RTS_CONTROL_ENABLE; //啟用RTS線 PortDCB.fAbortOnError = FALSE; //WINCE串列驅動程式的預設執行將忽略這個欄位 PortDCB.ByteSize = 8; //每位元組的位元 PortDCB.Parity = NOPARITY; //無同位 PortDCB.StopBits = ONESTOPBIT; //每位元組一位停止位 //根據DCB結構配置連接埠 if (!SetCommState (hPort, &PortDCB)) { //不能配置序列埠 MessageBox (NULL, TEXT("Unable to configure the serial port"), TEXT("Error"), MB_OK); dwError = GetLastError (); return FALSE; } return TRUE;} BOOL CSerial::InitCommTimeouts(){ COMMTIMEOUTS CommTimeouts; DWORD dwError; //得到逾時參數 GetCommTimeouts (hPort, &CommTimeouts); //改變COMMTIMEOUTS結構設定 CommTimeouts.ReadIntervalTimeout = MAXDWORD; CommTimeouts.ReadTotalTimeoutMultiplier = 0; CommTimeouts.ReadTotalTimeoutConstant = 0; CommTimeouts.WriteTotalTimeoutMultiplier = 10; CommTimeouts.WriteTotalTimeoutConstant = 1000; //設定連接埠逾時值 if (!SetCommTimeouts (hPort, &CommTimeouts)) { //不能設定逾時值 MessageBox (NULL, TEXT("Unable to set the time-out parameters"), TEXT("Error"), MB_OK); dwError = GetLastError (); return FALSE; } return TRUE;} 以上類代碼在eMbedded Visual C++4.0和基於ARM9的三星S3C2410開發板(運行Windows CE.NET 4.1)上測試通過。Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=17885