本人才学习串口,现在将自己用API写的串口通信类的源代码公布,以供大家参考。
//头文件件
// SerialAPI.h: interface for the CSerialAPI class.
//
//
#if !defined(AFX_SERIALAPI_H__9B5A3F02_39E2_478D_8AA9_AB0A7775FE3D__INCLUDED_)
#define AFX_SERIALAPI_H__9B5A3F02_39E2_478D_8AA9_AB0A7775FE3D__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CSerialAPI
{
public:
int i ;
// unsigned char* receiveData();
int receiveData(unsigned char * lpBuf);
BOOL WriteABuffer(unsigned char *lpBuf, DWORD dwToWrite);
HANDLE openPort(char* port,char* dataSet);
HANDLE hComm;
DCB dcb;
//用来存放当前的串口的数据,来返回
unsigned char* curentBufferData;
CSerialAPI();
virtual ~CSerialAPI();
};
#endif // !defined(AFX_SERIALAPI_H__9B5A3F02_39E2_478D_8AA9_AB0A7775FE3D__INCLUDED_)
//。CPP文件
// SerialAPI.cpp: implementation of the CSerialAPI class.
//
//
#include "stdafx.h"
#include "showData.h"
#include "SerialAPI.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//
// Construction/Destruction
//
CSerialAPI::CSerialAPI()
{
}
CSerialAPI::~CSerialAPI()
{
}
//打开端口的方法
HANDLE CSerialAPI::openPort(char *port, char *dataSet)
{
hComm = CreateFile(port,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE)
{
AfxMessageBox("打开串口失败!!!");
}
else
{
AfxMessageBox("成功打开串口!!!");
}
//设置为1024字节的缓冲区
SetupComm(hComm,1024,1024);
COMMTIMEOUTS TimeOuts;
//设定读超时
TimeOuts.ReadIntervalTimeout=MAXDWORD;
TimeOuts.ReadTotalTimeoutMultiplier=MAXDWORD;
TimeOuts.ReadTotalTimeoutConstant=63;
//在读一次输入缓冲区的内容后读操作就立即返回,
//而不管是否读入了要求的字符。
//设定写超时
SetCommTimeouts(hComm,&TimeOuts); //设置超时
FillMemory(&dcb, sizeof(dcb), 0);
dcb.DCBlength = sizeof(dcb);
if (!BuildCommDCB(dataSet, &dcb))
{
AfxMessageBox("不能成功的设置DCB!!!");
}
else
{
AfxMessageBox("DCB设置成功!!!");
SetCommState(hComm, &dcb);
}
//清空
PurgeComm(hComm, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
return hComm;
}
//写数据
BOOL CSerialAPI::WriteABuffer(unsigned char *lpBuf, DWORD dwToWrite)
{
OVERLAPPED osWrite = {0};//重叠方式
DWORD dwWritten;
DWORD dwRes;
BOOL fRes;
//写之前清除
PurgeComm(hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);
osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osWrite.hEvent == NULL)
{
AfxMessageBox("无法创建事件!!!");
return FALSE;
}
//向指定的口写数据
//如果这个时候不能及时返回的话,那么就会返回FALSE
if (!WriteFile(hComm, lpBuf, dwToWrite, &dwWritten, &osWrite))
{
//得到错误的代码,以下说明不是因为发送延时出错,报错
if (GetLastError() != ERROR_IO_PENDING)
{
AfxMessageBox("发送数据到指定端口错误!!!");
fRes = FALSE;
return FALSE;
}
//如果发生的是因为写入数据时的延时错误
else
{
//那么就等待信号,有两种,一种是有信号了,一种是超时
dwRes = WaitForSingleObject(osWrite.hEvent, INFINITE);
//看返回值是什么以做下一步
switch(dwRes)
{
//表明是有信号了
case WAIT_OBJECT_0:
//得到重叠的结果,如果为真的话,那么发送成功
if (!GetOverlappedResult(hComm, &osWrite, &dwWritten, FALSE))
{
fRes = FALSE;
AfxMessageBox("发送失败!!!");
return FALSE;
}
//如果发送成功完成
else
{
fRes = TRUE;
//AfxMessageBox("发送成功!!!");
}
break;
//其他处理
default:
AfxMessageBox("发生不可预知错误!!!");
}
}
}
//出现这种情况说明立刻返回了
else
{
AfxMessageBox("立即返回,发送成功!!!");
fRes = TRUE;
}
//关闭事件
CloseHandle(osWrite.hEvent);
return fRes;
}
int CSerialAPI::receiveData(unsigned char * lpBuf)
{
DWORD dwRead;
DWORD dwRes;
//错误标志
COMSTAT ComStat;
//错误
DWORD dwErrorFlags;
BOOL fWaitingOnRead = FALSE;
OVERLAPPED osReader = {0};
//读之前清除缓冲区
//
//清除错误
ClearCommError(hComm,&dwErrorFlags,&ComStat);
// unsigned char lpBuf;
//创建一个事件
osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osReader.hEvent == NULL)
{
AfxMessageBox("创建事件失败!!!");
}
//如果并没有阻塞在读上面,那么执行以下代码
if (!fWaitingOnRead)
{
//从串口中读入数据
BOOL bk = ReadFile(hComm,lpBuf,65,&dwRead,&osReader);
//如果读取不成功
if(!bk){
//如果读入不成功是因为阻塞了
if(GetLastError() == ERROR_IO_PENDING){
//fWaitingOnRead = TRUE;
dwRes = WaitForSingleObject(osReader.hEvent,10);
switch (dwRes)
{
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hComm, &osReader, &dwRead, TRUE))
{
// AfxMessageBox("读数据产生错误!!!");
::OutputDebugString("读数据产生错误!!!/n");
}
else
{
::OutputDebugString("读数据成功!!!");
//PurgeComm(hComm, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
//i ++;
//this->curentBufferData[i++] = lpBuf;
//AfxMessageBox("读数据成功!!!");
}
//fWaitingOnRead = FALSE;
break;
//读写超时
case WAIT_TIMEOUT:
::OutputDebugString("读超时!!!/n");
//AfxMessageBox("读超时!!");
break;
default:
::OutputDebugString("出现不可预知错误!!!/n");
// AfxMessageBox("出现不可预知错误!!!");
break;
}
}
}
/*
do
{
if (!ReadFile(hComm,&lpBuf[i],1, &dwRead,&osReader))
{
//AfxMessageBox("开始读数据!");
if (GetLastError() != ERROR_IO_PENDING)
{
::OutputDebugString("出现读错误!!!/n");
//AfxMessageBox("出现读错误!!!")
}
//否则说明数据在读的时候正在阻塞
else
{
::OutputDebugString("读数据的时候发生了阻塞!!!/n");
//AfxMessageBox("读数据的时候发生了阻塞!!!");
fWaitingOnRead = TRUE;
//看在等待的时候返回什么
dwRes = WaitForSingleObject(osReader.hEvent,-1);
switch (dwRes)
{
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hComm, &osReader, &dwRead, FALSE))
{
// AfxMessageBox("读数据产生错误!!!");
::OutputDebugString("读数据产生错误!!!/n");
}
else
{
::OutputDebugString("读数据成功!!!");
i ++;
//this->curentBufferData[i++] = lpBuf;
//AfxMessageBox("读数据成功!!!");
}
fWaitingOnRead = FALSE;
break;
//读写超时
case WAIT_TIMEOUT:
::OutputDebugString("读超时!!!/n");
//AfxMessageBox("读超时!!");
break;
default:
::OutputDebugString("出现不可预知错误!!!/n");
// AfxMessageBox("出现不可预知错误!!!");
break;
}
}
}
else
{
::OutputDebugString("读数据成功!!!/n");
i ++;
// this->curentBufferData[i++] = lpBuf;
//AfxMessageBox("读数据成功!!!");
}
//CString theString = lpBuf;
//AfxMessageBox(lpBuf);
//AfxMessageBox("读数据成功!!!");
} while(dwRead);
//如果很快就读完了并且返回了
CloseHandle(osReader.hEvent);
// return curentBufferData;
*/
}
//返回读入的字节
CloseHandle(osReader.hEvent);
//清空缓冲区
PurgeComm(hComm, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
return dwRead;
}
//用来接收数据
/*
unsigned char* CSerialAPI::receiveData()
{
int i = 0;
DWORD dwRead;
DWORD dwRes;
BOOL fWaitingOnRead = FALSE;
OVERLAPPED osReader = {0};
unsigned char lpBuf;
//创建一个事件
osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osReader.hEvent == NULL)
{
AfxMessageBox("创建事件失败!!!");
}
//如果并没有阻塞在读上面,那么执行以下代码
if (!fWaitingOnRead)
{
do
{
if (!ReadFile(hComm,&lpBuf,1, &dwRead,&osReader))
{
//AfxMessageBox("开始读数据!");
if (GetLastError() != ERROR_IO_PENDING)
{
::OutputDebugString("出现读错误!!!/n");
//AfxMessageBox("出现读错误!!!")
}
//否则说明数据在读的时候正在阻塞
else
{
::OutputDebugString("读数据的时候发生了阻塞!!!/n");
//AfxMessageBox("读数据的时候发生了阻塞!!!");
fWaitingOnRead = TRUE;
//看在等待的时候返回什么
dwRes = WaitForSingleObject(osReader.hEvent,10);
switch (dwRes)
{
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hComm, &osReader, &dwRead, FALSE))
{
// AfxMessageBox("读数据产生错误!!!");
::OutputDebugString("读数据产生错误!!!/n");
}
else
{
::OutputDebugString("读数据成功!!!");
this->curentBufferData[i++] = lpBuf;
//AfxMessageBox("读数据成功!!!");
}
fWaitingOnRead = FALSE;
break;
//读写超时
case WAIT_TIMEOUT:
::OutputDebugString("读超时!!!/n");
//AfxMessageBox("读超时!!");
break;
default:
::OutputDebugString("出现不可预知错误!!!/n");
// AfxMessageBox("出现不可预知错误!!!");
break;
}
}
}
else
{
::OutputDebugString("读数据成功!!!/n");
this->curentBufferData[i++] = lpBuf;
//AfxMessageBox("读数据成功!!!");
}
//CString theString = lpBuf;
//AfxMessageBox(lpBuf);
//AfxMessageBox("读数据成功!!!");
} while(dwRead);
//如果很快就读完了并且返回了
CloseHandle(osReader.hEvent);
return curentBufferData;
}
return 0;
}
*/