#include "stdafx.h"
#include "SerialPort.h"
CSerialPort::CSerialPort()
{
m_hComm = NULL;
}
//串口初始化函数
int CSerialPort::InitPort(CString Com,UINT BaudRate,UINT DtataBits,UINT Parity,UINT StopBits)
{
m_hComm = CreateFile(Com, //打开串口
GENERIC_READ | GENERIC_WRITE, //读写
0,
NULL, //使用默认安全属性
OPEN_EXISTING, //打开一个现有的文件
FILE_ATTRIBUTE_NORMAL| FILE_FLAG_OVERLAPPED, //使用重叠IO方式
NULL );
if(m_hComm == INVALID_HANDLE_VALUE) //判断句柄是否有效,若判断是否为空可能出错。
{
return NET_ERROR;
}
SetupComm(m_hComm,1024,1024); //输入缓冲区和输出缓冲区的大小都是1024
DCB m_DCB; //DCB结构定义了串行通信设备控制设置
GetCommState(m_hComm, &m_DCB );
m_DCB.BaudRate=DWORD(BaudRate); //指定当前采用的波特率,应与所连接的通讯设备相匹配
m_DCB.fBinary=TRUE; //指定是否允许二进制模式
m_DCB.fParity=TRUE; //指定奇偶校验是否允许,在为true时具体采用何种校验看Parity 设置
m_DCB.Parity=BYTE(Parity); //奇偶校验的方式
m_DCB.ByteSize=BYTE(DtataBits); //数据位数
m_DCB.StopBits=BYTE(StopBits); //停止位数
SetCommState(m_hComm,&m_DCB); //函数设置COM口的设备控制块
COMMTIMEOUTS TimeOuts; //设定读写超时值 (以下几个超时值会影响读写的数据是否成功)
GetCommTimeouts(m_hComm,&TimeOuts);
TimeOuts.ReadIntervalTimeout=10; //通讯过程中接收两个字符之间的最长超时时间,按毫秒计算
TimeOuts.ReadTotalTimeoutMultiplier=10;
TimeOuts.ReadTotalTimeoutConstant=50;
TimeOuts.WriteTotalTimeoutMultiplier=10; //设定写超时
TimeOuts.WriteTotalTimeoutConstant=10;
SetCommTimeouts(m_hComm,&TimeOuts); //设定通讯设备读写时的超时参数
PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR); //清空输入输出缓存区
return NET_SUCCESS;
}
//写入数据
int CSerialPort::SerialWrite(char* pWriteBuf,UINT length)
{
DWORD dwBytesWritten= length;
COMSTAT ComStat; //包含信息通讯设备的结构体
DWORD dwErrorFlags;
OVERLAPPED m_osWrite; //OVERLAPPED结构主要用于异步I/O操作
m_osWrite.Internal=0; //系统保留,存放系统设置的状态
m_osWrite.InternalHigh=0; //系统保留,存放被传输数据的长度
m_osWrite.Offset=0; //指定文件的位置,文件位置是相对文件开始处的字节偏移量
m_osWrite.OffsetHigh=0; //指定开始传送数据的字节偏移量的高位字
m_osWrite.hEvent = CreateEventA(NULL,TRUE,FALSE,NULL); //标识事件,数据传送完成时把它设为信号状态
if (m_osWrite.hEvent == NULL)
{
AfxMessageBox(_T("写入数据重叠IO,hEvent为空"));
return NET_ERROR;
}
BOOL bWriteState;
ClearCommError(m_hComm,&dwErrorFlags,&ComStat);
bWriteState = WriteFile(m_hComm,pWriteBuf,dwBytesWritten, NULL,&m_osWrite); //成功返回非0
if(!bWriteState)
{
dwErrorFlags=GetLastError(); //获取当前IO错误标志,返回值[997]-重叠 I/O 操作在进行中。
if(dwErrorFlags==ERROR_IO_PENDING)
{
WaitForSingleObject(m_osWrite.hEvent,1000);
BOOL Rtn;
Rtn = GetOverlappedResult(m_hComm,&m_osWrite,&dwBytesWritten,FALSE);
if(FALSE == Rtn)
{
return NET_ERROR;
}
}
}
return NET_SUCCESS;
}
//读取数据
int CSerialPort::SerialRead(char* pReadBuf,UINT* length)
{
DWORD dwBytesRead = MAX_DATA_LEN;
COMSTAT ComStat; //COMSTAT结构包含串口的信息
DWORD dwErrorFlags;
OVERLAPPED m_osRead;
memset(&m_osRead,0,sizeof(OVERLAPPED));
m_osRead.hEvent=CreateEventA(NULL,TRUE,FALSE,NULL); //创建一个人工重置事件对象,初始为无信号状态
if (m_osRead.hEvent == NULL)
{
AfxMessageBox(_T("读取数据重叠IO,hEvent为空"));
return NET_ERROR;
}
ClearCommError(m_hComm,&dwErrorFlags,&ComStat); //清除硬件的通讯错误以及获取通讯设备的当前信息
PurgeComm(m_hComm, PURGE_TXABORT| PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
BOOL bReadState;
bReadState = ReadFile(m_hComm,pReadBuf, dwBytesRead,NULL,&m_osRead);//如果函数执行成功返回非零
if(!bReadState)
{
dwErrorFlags = GetLastError();
if(dwErrorFlags == ERROR_IO_PENDING) //GetLastError()函数返回ERROR_IO_PENDING,表明重叠 I/O 操作在进行中。
{
//使用WaitForSingleObject函数等待,直到读操作完成或延时已达到1秒钟
//当串口读操作进行完毕后,m_osRead的hEvent事件会变为有信号
WaitForSingleObject(m_osRead.hEvent,1000);
*length = m_osRead.InternalHigh;
PurgeComm(m_hComm, PURGE_TXABORT| PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); //清空读写缓冲区,禁止读写操作
BOOL Rtn;
Rtn = GetOverlappedResult(m_hComm,&m_osRead,&dwBytesRead,FALSE);
if(FALSE == Rtn)
{
return NET_ERROR;
}
}
}
PurgeComm(m_hComm, PURGE_TXABORT| PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
return NET_SUCCESS;
}
//关闭串口
int CSerialPort::SerialClose()
{
int Rtn;
if(m_hComm != INVALID_HANDLE_VALUE || m_hComm != NULL)
{
Rtn = CloseHandle(m_hComm);
if(Rtn == 0)
{
AfxMessageBox(_T("关闭串口失败"));
return NET_ERROR;
}
m_hComm = INVALID_HANDLE_VALUE;
}
return NET_SUCCESS;
}
//转换成16进制字符形式发送
//CString CSerialPort::ChangeCharstrToHexstr(CString Charstr)
//{
// CString Hexstr=_T("");
// Charstr.MakeUpper(); //转换成大写字母
// HexStringFilter(Charstr);
// int Length=Charstr.GetLength();
// if(Length%2)
// Charstr.Delete(Length-1);
// Length=Charstr.GetLength();
// for(int i=0;i<Length/2;i++)
// {
// Hexstr += CombineHexChar(Charstr.GetAt(i*2),Charstr.GetAt(i*2+1));
// }
// return Hexstr;
//}
//void CSerialPort::HexStringFilter(CString &str)
//{
// BOOL CheckBit;
// for(int i=0;i<str.GetLength();)
// {
// CheckBit=((str.GetAt(i)>='0')&&(str.GetAt(i)<='9'))||
// ((str.GetAt(i)>='A')&&(str.GetAt(i)<='F'))||
// ((str.GetAt(i)>='a')&&(str.GetAt(i)<='f'));
// if(!CheckBit)
// str.Delete(i);
// else i++;
// }
//}
//char CSerialPort::CombineHexChar(char CharH,char CharL)
//{
// char result;
// CString temp;
// if(CharH>='0'&&CharH<='9') result=(CharH-'0');
// else if(CharH>='a'&&CharH<='f') result=(CharH-'a'+10);
// else if(CharH>='A'&&CharH<='F') result=(CharH-'A'+10);
// else result=0;
// result<<=4;
// if(CharL>='0'&&CharL<='9') result+=(CharL-'0');
// else if(CharL>='a'&&CharL<='f') result+=(CharL-'a'+10);
// else if(CharL>='A'&&CharL<='F') result+=(CharL-'A'+10);
// else result+=0;
//
// return result;
//}