Chinaunix首页 | 论坛 | 博客
  • 博客访问: 73646
  • 博文数量: 35
  • 博客积分: 1420
  • 博客等级: 上尉
  • 技术积分: 306
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-15 13:33
个人简介

自强不息!

文章分类

全部博文(35)

文章存档

2020年(1)

2017年(1)

2011年(3)

2010年(15)

2009年(2)

2008年(2)

2007年(1)

2006年(10)

我的朋友

分类: WINDOWS

2010-07-04 11:51:04

Windows CE下串口通信整理

    本文整理来自网络,如有侵权,请告知修改


一、打开串口

       hSerial = CreateFile(L"COM1:", 
               GENERIC_READ | GENERIC_WRITE,
               0,
               NULL,
               OPEN_EXISTING,
               0,
               NULL);

if(m_hSerial == NULL)
{
///L"串口打开失败";
return;
}
///配置串口
DCB PortDCB;
PortDCB.DCBlength = sizeof(DCB);
// 默认串口参数
GetCommState(hSerial, &PortDCB);
PortDCB.BaudRate = 115200; // baud
PortDCB.ByteSize = 8; // Number of bits/byte, 4-8
PortDCB.Parity = NOPARITY;
PortDCB.StopBits = ONESTOPBIT;
if (! SetCommState(hSerial, &PortDCB))
{
///L"配置串口失败";
return;
}
////配置超时值
COMMTIMEOUTS CommTimeouts;
GetCommTimeouts(m_hSerial, &CommTimeouts);
CommTimeouts.ReadIntervalTimeout = MAXDWORD;
CommTimeouts.ReadTotalTimeoutMultiplier = 10;
CommTimeouts.ReadTotalTimeoutConstant = 10;
CommTimeouts.WriteTotalTimeoutMultiplier = 50;
CommTimeouts.WriteTotalTimeoutConstant = 100;
if (!SetCommTimeouts(hSerial, &CommTimeouts))
{
///L"不能设置超时参数";
return;
}
  CE的串口驱动不支持重叠,这个大家都知道的。这样的话收和发就要分开。要接收串口数据就必须创建一个线程专门用于接收数据。串口的配置不需要设置很 多参数,默认的配置大部分是不需要修改的。一般改动就是波特率、位数、奇偶校检等几项。超时值是需要改动的,后续说明超时数据结构。

二、关闭串口

关闭串口用关闭句柄函数。
if(hSerial != NULL)  
{
CloseHandle(hSerial);
hSerial = NULL;
}
三、向串口发送数据
WriteFile (hSerial,        // 句柄
&Byte, // 数据缓冲区地址
nByte, // 数据大小
&dwNumBytes, // 返回发送出去的字节数
NULL // 不支持重叠
);
  

四、读取串口数据
UINT  ReadThread(LPVOID pParam) ?////接收串口数据线程
{
HANDLE hPort = *(HANDLE*)pParam;
BYTE Byte;
int iCounter = 0;
DWORD dwBytes;
char ReceiveBuf[1000]; ///缓冲区的大小

SetCommMask (hPort, EV_RXCHAR); ///只接收字符
while (hPort != INVALID_HANDLE_VALUE)
{
DWORD dwCommStatus;
WaitCommEvent(hPort, &dwCommStatus, 0);
SetCommMask (hPort, EV_RXCHAR); ///重新设置要等待的信号
//// 接收数据
do
{
ReadFile(hPort, &Byte, 1, &dwBytes, 0);
if(dwBytes == 1)
{
ReceiveBuf[iCounter++] = Byte;
if(iCounter == 1000)
{
///L"接收缓冲区已满";
return -1;
}
}
} while (dwBytes == 1);
if(iCounter == 0) ?////没接到数据
{
continue;
}
//////保存数据
char* pTmp = new char[iCounter + 1];
if(pTmp == NULL)
{
///L"内存不足,接收串口数据线程关闭";
return -1;
}
memcpy(pTmp, ReceiveBuf, iCounter);
pTmp[iCounter] = NULL; ////字符串结尾
////////创建新线程处理数据

////在ProcessData函数中处理数据。别忘了delete[] pTmp;
AfxBeginThread(ProcessData, pTmp);
iCounter = 0; ////清空计数器
} ///////end while
return 0;
}

五,串口超时的说明

在用ReadFile和WriteFile读写串行口时,需要考虑超时问题。如果在指定

的时间内没有读出或写入指定数量的字符,那么ReadFile或WriteFile的操

作就会结束。要查询当前的超时设置应调用GetCommTimeouts函数,该函数

会填充一个COMMTIMEOUTS结构。调用SetCommTimeouts可以用某一个

COMMTIMEOUTS结构的内容来设置超时。  
    有两种超时:间隔超时和总超时。间隔超时是指在接收时两个字符

之间的最大时延,总超时是指读写操作总共花费的最大时间。写操作只支

持总超时,而读操作两种超时均支持。用COMMTIMEOUTS结构可以规定读/写

操作的超时,该结构的定义为:  
  typedef   struct   _COMMTIMEOUTS   {    
  DWORD   ReadIntervalTimeout;   //   读间隔超时  
  DWORD   ReadTotalTimeoutMultiplier;   //   读时间系数  
  DWORD   ReadTotalTimeoutConstant;   //   读时间常量  
  DWORD   WriteTotalTimeoutMultiplier;   //   写时间系数  
  DWORD   WriteTotalTimeoutConstant;   //   写时间常量  
  }   COMMTIMEOUTS,*LPCOMMTIMEOUTS;  
    COMMTIMEOUTS结构的成员都以毫秒为单位。总超时的计算公式是: 

 
   
  总超时=时间系数×要求读/写的字符数   +   时间常量  
    例如,如果要读入10个字符,那么读操作的总超时的计算公式为: 

 
  读总超时=ReadTotalTimeoutMultiplier×10   +  

ReadTotalTimeoutConstant  
    可以看出,间隔超时和总超时的设置是不相关的,这可以方便通信

程序灵活地设置各种超时。  
    如果所有写超时参数均为0,那么就不使用写超时。如果

ReadIntervalTimeout为0,那么就不使用读间隔超时,如果

ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant都为0,则不使

用读总超时。如果读间隔超时被设置成MAXDWORD并且两个读总超时为0,那

么在读一次输入缓冲区中的内容后读操作就立即完成,而不管是否读入了

要求的字符。  
    在用重叠方式读写串行口时,虽然ReadFile和WriteFile在完成操作

以前就可能返回,但超时仍然是起作用的。在这种情况下,超时规定的是

操作的完成时间,而不是ReadFile和WriteFile的返回时间。



阅读(740) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~