1. gzyueqian
      18078865874

      Windows CE下的串口通訊實(shí)例

      更新時(shí)間: 2007-07-02 14:39:20來(lái)源: 粵嵌教育瀏覽量:852

        串行通訊是目前計(jì)算機(jī)、通信和控制領(lǐng)域基本的通信方式。在CSDN的“嵌入式開(kāi)發(fā)/WINCE”社區(qū)中,經(jīng)常有人提問(wèn)該到哪找串口通訊例子,其實(shí)這個(gè)問(wèn)題我自己也問(wèn)過(guò)。:)而一般的回答是給你提供一個(gè)Pocket PC 2002的SDK例子程序。但到底SDK的程序和MFC的結(jié)構(gòu)有很大的不同,對(duì)于想用MFC編寫(xiě)通信程序的人來(lái)說(shuō)也不是很便利。

        另一方面,由于Windows CE是一個(gè)基于Unicode的操作系統(tǒng),并且Windows CE不支持Windows下常用的串行通信重疊I/O方式(OVERLAPPED),因此編寫(xiě)Windows CE下的串口通訊類(lèi)有一些與桌面Windows不同的地方。

        以下是我從SDK程序改寫(xiě)而來(lái)的MFC例子程序,希望能和致力于WINCE開(kāi)發(fā)的朋友多多交流,由于本人才疏學(xué)淺,程序中有許多不完善的地方,請(qǐng)大家指正。我的程序是基于“主動(dòng)發(fā)送請(qǐng)求,被動(dòng)接收響應(yīng)”的假設(shè),因此我只設(shè)置了一個(gè)接收數(shù)據(jù)的線(xiàn)程。

      感謝“嵌入式開(kāi)發(fā)/WINCE”社區(qū)為我提供SDK例子的朋友,感謝CSDN上所有熱心的朋友,祝愿中國(guó)的軟硬件水平能早日擠身世界。

      頭文件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); //讀數(shù)據(jù)線(xiàn)程



      class CSerial

      {

      public:

      BOOL InitCommTimeouts(); //設(shè)置超時(shí)參數(shù)

      BOOL InitDCB(); //配置串口

      BOOL m_bConnected;

      BOOL ClosePort(HANDLE hCommPort); //關(guān)閉串口

      DWORD WritePort(TCHAR *buf,DWORD dwBytesToWrite); //寫(xiě)數(shù)據(jù)

      BOOL OpenPort(LPTSTR lpszPortName); //打開(kāi)串口

      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;

      }



      //打開(kāi)串口

      hPort = CreateFile (lpszPortName, GENERIC_READ | GENERIC_WRITE,

      0, NULL, OPEN_EXISTING,0, NULL);

      //如果打開(kāi)端口出錯(cuò), 返回FALSE

      if ( hPort == INVALID_HANDLE_VALUE )

      {

      //不能打開(kāi)端口

      CString strError;

      strError.Format(_T("Unable to open %s, Error No.=%d"),

      lpszPortName, GetLastError());



      MessageBox (NULL, strError, TEXT("Error"), MB_OK);



      return FALSE;

      }



      //指定端口監(jiān)測(cè)的事件集

      SetCommMask (hPort, EV_RXCHAR);

      //分配設(shè)備緩沖區(qū)

      SetupComm(hPort,512,512);

      //初始化緩沖區(qū)中的信息

      PurgeComm(hPort,PURGE_TXCLEAR|PURGE_RXCLEAR);



      //配置串行端口

      if(!InitDCB())

      return FALSE;



      //設(shè)置端口超時(shí)值

      if(!InitCommTimeouts())

      return FALSE;



      //設(shè)置端口上指定信號(hào)的狀態(tài)

      // SETDTR: 發(fā)送DTR (data-terminal-ready)信號(hào)

      // SETRTS: 發(fā)送RTS (request-to-send)信號(hào)

      EscapeCommFunction (hPort, SETDTR);

      EscapeCommFunction (hPort, SETRTS);



      //創(chuàng)建一個(gè)從串口讀取數(shù)據(jù)的線(xiàn)程

      if (hReadThread = CreateThread (NULL, 0, ReadPortThread, 0, 0,

      &dwThreadID))

      {

      }

      else

      {

      //不能創(chuàng)建線(xiàn)程

      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;



      //寫(xiě)入數(shù)據(jù)

      fWriteState=WriteFile(hPort,buf,dwCharToWrite*sizeof(TCHAR),&dwBytesWritten,NULL);

      if(!fWriteState)

      {

      //不能寫(xiě)數(shù)據(jù)

      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)

      {

      //等待串口的事件發(fā)生

      WaitCommEvent (hPort, &dwCommModemStatus, 0);



      if (dwCommModemStatus & EV_RXCHAR)

      {

      ClearCommError(hPort,&dwErrorFlags,&ComStat);

      //cbInQue返回在串行驅(qū)動(dòng)程序輸入隊(duì)列中的字符數(shù)

      dwLength=ComStat.cbInQue;



      if(dwLength>0)

      {

      //從串口讀取數(shù)據(jù)

      TCHAR* buf=new TCHAR[256];

      fReadState=ReadFile(hPort,buf,dwLength,&dwLength,NULL);

      if(!fReadState)

      {

      //不能從串口讀取數(shù)據(jù)

      MessageBox(NULL,TEXT("Error in read from serial port"),TEXT("Read Error"),MB_OK);

      }

      else

      {

      //把數(shù)據(jù)賦值給全局變量

      strInChar=buf;

      }

      delete[] buf;

      }

      }



      GetCommModemStatus (hPort, &dwCommModemStatus);

      }



      return 0;

      }



      BOOL CSerial::ClosePort(HANDLE hCommPort)

      {

      if (hCommPort != INVALID_HANDLE_VALUE)

      {

      //設(shè)置連接屬性為FALSE

      m_bConnected=FALSE;



      //結(jié)束線(xiàn)程中WaitCommEvent的等待

      SetCommMask(hPort,0);



      //阻塞至線(xiàn)程停止

      if(hReadThread)

      {

      TerminateThread(hReadThread,0);

      CloseHandle(hReadThread);

      }



      //清除端口上指定信號(hào)的狀態(tài)

      EscapeCommFunction(hPort,CLRDTR);

      EscapeCommFunction(hPort,CLRRTS);

      //清除驅(qū)動(dòng)程序內(nèi)部的發(fā)送和接收隊(duì)列

      PurgeComm(hPort,PURGE_TXCLEAR|PURGE_RXCLEAR);



      //關(guān)閉串口

      CloseHandle (hCommPort);

      hCommPort = INVALID_HANDLE_VALUE;



      return TRUE;

      }

      else

      {

      return TRUE;

      }

      }



      BOOL CSerial::InitDCB()

      {

      DCB PortDCB;

      DWORD dwError;



      PortDCB.DCBlength = sizeof (DCB);



      //得到端口的默認(rèn)設(shè)置信息

      GetCommState (hPort, &PortDCB);



      //改變DCB結(jié)構(gòu)設(shè)置

      PortDCB.BaudRate = 19200; //波特率

      PortDCB.fBinary = TRUE; //Win32不支持非二進(jìn)制串行傳輸模式,必須為T(mén)RUE

      PortDCB.fParity = TRUE; //啟用奇偶校驗(yàn)

      PortDCB.fOutxCtsFlow = TRUE; //串行端口的輸出由CTS線(xiàn)控制

      PortDCB.fOutxDsrFlow = FALSE; //關(guān)閉串行端口的DSR流控制

      PortDCB.fDtrControl = DTR_CONTROL_ENABLE; //啟用DTR線(xiàn)

      PortDCB.fDsrSensitivity = FALSE; //如果設(shè)為T(mén)RUE將忽略任何輸入的字節(jié),除非DSR線(xiàn)被啟用

      //PortDCB.fTXContinueOnXoff = TRUE; //當(dāng)為T(mén)RUE時(shí),如果接收緩沖區(qū)已滿(mǎn)且驅(qū)動(dòng)程序已傳送XOFF字符,將使驅(qū)動(dòng)程序停止傳輸字符

      PortDCB.fTXContinueOnXoff = FALSE;

      PortDCB.fOutX = FALSE; //設(shè)為T(mén)RUE指定XON/XOFF控制被用于控制串行輸出

      PortDCB.fInX = FALSE; //設(shè)為T(mén)RUE指定XON/XOFF控制被用于控制串行輸入

      PortDCB.fErrorChar = FALSE; //WINCE串行驅(qū)動(dòng)程序的默認(rèn)執(zhí)行將忽略這個(gè)字段

      PortDCB.fNull = FALSE; //設(shè)為T(mén)RUE將使串行驅(qū)動(dòng)程序忽略收到的空字節(jié)

      PortDCB.fRtsControl = RTS_CONTROL_ENABLE; //啟用RTS線(xiàn)

      PortDCB.fAbortOnError = FALSE; //WINCE串行驅(qū)動(dòng)程序的默認(rèn)執(zhí)行將忽略這個(gè)字段

      PortDCB.ByteSize = 8; //每字節(jié)的位數(shù)

      PortDCB.Parity = NOPARITY; //無(wú)奇偶校驗(yàn)

      PortDCB.StopBits = ONESTOPBIT; //每字節(jié)一位停止位



      //根據(jù)DCB結(jié)構(gòu)配置端口

      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;



      //得到超時(shí)參數(shù)

      GetCommTimeouts (hPort, &CommTimeouts);



      //改變COMMTIMEOUTS結(jié)構(gòu)設(shè)置

      CommTimeouts.ReadIntervalTimeout = MAXDWORD;

      CommTimeouts.ReadTotalTimeoutMultiplier = 0;

      CommTimeouts.ReadTotalTimeoutConstant = 0;

      CommTimeouts.WriteTotalTimeoutMultiplier = 10;

      CommTimeouts.WriteTotalTimeoutConstant = 1000;



      //設(shè)置端口超時(shí)值

      if (!SetCommTimeouts (hPort, &CommTimeouts))

      {

      //不能設(shè)置超時(shí)值

      MessageBox (NULL, TEXT("Unable to set the time-out parameters"),

      TEXT("Error"), MB_OK);

      dwError = GetLastError ();

      return FALSE;

      }



      return TRUE;

      }



        以上類(lèi)代碼在eMbedded Visual C++4.0和基于ARM9的三星S3C2410開(kāi)發(fā)板(運(yùn)行Windows CE.NET 4.1)上測(cè)試通過(guò)。

      免費(fèi)預(yù)約試聽(tīng)課

      亚洲另类欧美综合久久图片区_亚洲中文字幕日产无码2020_欧美日本一区二区三区桃色视频_亚洲AⅤ天堂一区二区三区

      
      

      1. 日韩中文字幕在线视频三区 | 在线人成免费视频69国产 | 亚洲国产人在线播放首页 | 伊人网在线观看动态图 | 久久成人免费精品二区 | 亚洲午夜福利在线网 |