Windows CE串口通訊類的實現

來源:互聯網
上載者:User

串列通訊是目前電腦、通訊和控制領域最基本的通訊方式。但採用那種串口通訊類呢?一般的情況下是給你提供一個Pocket PC 2002的SDK例子程式。但到底SDK的程式和MFC的結構有很大的不同,對於想用MFC編寫通訊程式的人來說也不是很便利。

  另一方面,由於Windows CE是一個基於Unicode的作業系統,並且Windows CE不支援Windows下常用的串列通訊重疊I/O方式(OVERLAPPED),因此編寫Windows CE下的串口通訊類有一些與案頭Windows不同的地方。

  以下是我從SDK程式改寫而來的MFC類,希望能和致力於WINCE開發的朋友多多交流,由於本人才疏學淺,程式中有許多不完善的地方,請大家指正。我的程式是基於“主動發送請求,被動接收響應”的假設,因此我只設定了一個接收資料的線程。如果有朋友能提供有獨立發送資料和接收資料線程的類,我將十分感激。

  標頭檔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_FILE
static 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)上測試通過。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.