您的位置:软件 > 开发者网络 > 开发工具 > 移动开发 > 正文
Windows CE串口通讯类的实现
[文章信息]
作者:bobo编译
时间:2003-12-13
出处:
责任编辑:方舟
[文章导读]
advertisement
热点推荐
· 好友上线通知——QQ千里眼
· 解析Windows操作系统的管理
· 剑走偏锋——灵巧的旁注攻击
· Mail Notifier邮件提醒工具
· Linux操作系统网络应用解疑
[正文]
  串行通讯是目前计算机、通信和控制领域最基本的通信方式。但采用那种串口通讯类呢?一般的情况下是给你提供一个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)上测试通过。

·"WAP天极之IT新闻资讯,50万元等你拿"    ·天极WAP之游戏狂图,50万元等你下载


发表评论推荐给朋友我想参加相关培训打印我对此感兴趣订阅电子杂志
相关内容阅读排行榜
  • 让手机帮你抱得美人归
  • 光棍节、孙悟空 配件也能分公母
  • 好友上线通知——QQ千里眼
  • 解析Windows操作系统的管理
  • 史前巨鳄 超频三散热器
  • 明花有主 飞利浦LCD有奖活动完美收场
  • 剑走偏锋——灵巧的旁注攻击
  • 统统闪开,最超值5700LE登场
  • Advertisement

    天极无线
    待机彩图    >>更多
    多彩动画    >>更多
    美妙和弦    >>更多
    天使在唱歌
    壁虎漫步
    PrettyBoy
    LoveLoveLove
    我是你的小小狗
    单身情歌
    十面埋伏
    祝酒歌
    回心转意
    波斯猫
    太委屈
    S.H.E
    潘玮柏
    M2M
    蔡依林
    阿牛
    林志炫
    陈弈迅
    刀郎
    黑龙
    S.H.E
    陶晶莹
    情人玫瑰坊
    音乐风云
    新片速递
    神秘测试
    都市约会
    ·天极彩信天天精彩
    ·图铃梦工厂下载无限!
    ·找寻童真,卡通专题
    ·夏日激情交友社区!
    ·星座运程,预测人生

    CSEEK搜索