📄 serialport.cpp
字号:
// SerialPort.cpp: implementation of the CSerialPort class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "sms.h"
#include "SerialPort.h"
#include <Winreg.h> //RegEnumValue所在头文件
#include <atlbase.h> //CRegKey所在头文件
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSerialPort::CSerialPort()
{
hCom=NULL;
}
CSerialPort::~CSerialPort()
{
CloseHandle(hCom);
hCom=NULL;
}
//////////////////////////////////////////////////////////////////////////
//取得系统上的所有COM口
void CSerialPort::GetCOMList(vector<CString> & PortList)
{
CRegKey RegKey;
int nCount = 0;
//CString * pNameList=new CString[5];
//CString * pPortList=new CString[5];
if(RegKey.Open(HKEY_LOCAL_MACHINE, "Hardware\\DeviceMap\\SerialComm") == ERROR_SUCCESS)
{
while(true)
{
char ValueName[_MAX_PATH];
unsigned char ValueData[_MAX_PATH];
DWORD nValueSize = _MAX_PATH;
DWORD nDataSize = _MAX_PATH;
DWORD nType;
//RegEnumValue函数的作用是,从被指定打开的注册表项中列举所有的值
//这函数每调用一次就会拷贝一个索引值的名称和数据块
if(::RegEnumValue(HKEY(RegKey), nCount, ValueName, &nValueSize, NULL, &nType, ValueData, &nDataSize) == ERROR_NO_MORE_ITEMS)
{
break;
}
// if(pNameList)
// pNameList[nCount] = ValueName;
//
// if(pPortList)
// pPortList[nCount] = ValueData;
CString temp=ValueData;
PortList.push_back(temp);
TRACE(PortList[nCount]+"\n");
nCount++;
}
}
}
BOOL CSerialPort::OpenCOMPort(CString sPort,int nBaudRate,int nByteSize,int nParity,int nStopBit)
{
BOOL result=FALSE;
//打开文件
hCom=CreateFile((LPCSTR)(LPCTSTR(sPort)), //指定要找开或创建的文件 这里指定串口名或设置的路径
GENERIC_READ|GENERIC_WRITE, //提供读写方式
0, //这里设置共享方式,这里采用独占方式
NULL, //设置安全属性,我们采用默认的设置
OPEN_EXISTING, //指定打开一个已存在的文件,由于COM口在系统中被认为是一个以存在的文件 打开而不是创建
NULL ,
NULL ); //不需要参照模板文件
if(INVALID_HANDLE_VALUE==hCom) //如果打开COM口文件失改,将会返回INVALID_HANDLE_VALUE这个错误
{
TRACE("打开COM失败!");
return FALSE;
}
//////////////////////////////////////////////////////////////////////////
//清空异步读写参数
memset(&m_OverlappedRead,0,sizeof(OVERLAPPED));
memset(&m_OverlappedWrite,0,sizeof(OVERLAPPED));
//////////////////////////////////////////////////////////////////////////
//读取通信状态,并对特定属性进行修改
DCB dcb;
//通过GetCommState函数可获取指定通信端口的状态
GetCommState(hCom,&dcb); //取得打开COM口的状态
dcb.BaudRate=nBaudRate; //波特率
dcb.ByteSize=nByteSize; //字节大小
dcb.Parity=nParity; //奇偶校验
dcb.StopBits=nStopBit; //停止位
//通过dcb结构体来重置一下通信状态
//SetCommState(hCom,&dcb);
//////////////////////////////////////////////////////////////////////////
//设置通信超时
//设置通信超时信息结构体
COMMTIMEOUTS commTimeouts;
commTimeouts.ReadIntervalTimeout=100; // 读字符间隔超时时间: 100 ms
commTimeouts.ReadTotalTimeoutConstant=500 ; // 基本的(额外的)读超时时间: 500 ms
commTimeouts.ReadTotalTimeoutMultiplier=1; // 读操作时每字符的时间: 1 ms (n个字符总共为n ms)
commTimeouts.WriteTotalTimeoutConstant=100; // 基本的(额外的)写超时时间: 100 ms
commTimeouts.WriteTotalTimeoutMultiplier=1;// 写操作时每字符的时间: 1 ms (n个字符总共为n ms)
//将超时信信息结构体的内容设置到指定的通信设备上去
SetCommTimeouts(hCom,&commTimeouts);
//////////////////////////////////////////////////////////////////////////
//初始化通信设备的缓冲区
//SetupComm函数来初始化一个指定通信设备的通信参数 通过句柄来指明要修改参数的设备
//SetupComm(hCom/*设备的句柄*/ ,4096 /*输入缓冲区大小*/,1024 /*输出缓冲区大小*/);
if( !SetCommState(hCom,&dcb) || //通过dcb结构体来重置一下通信状态
!SetupComm(hCom/*设备的句柄*/ ,4096 /*输入缓冲区大小*/,1024 /*输出缓冲区大小*/) )
{
CloseHandle(hCom);
hCom=NULL;
return FALSE;
}
//删除指定通信资源的输入和输出缓冲区中的所有字符
PurgeComm(hCom,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
TRACE("连接串口成功");
return TRUE;
}
BOOL CSerialPort::CloseSerialPort()
{
if (hCom != NULL)
{
PurgeComm(hCom,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
CloseHandle(hCom);
hCom = NULL;
}
return true;
}
BOOL CSerialPort::IsOpen()
{
return hCom != INVALID_HANDLE_VALUE;
//return hCom!=NULL;
}
int CSerialPort::ReadCom(LPVOID buffer, DWORD bufferLength)
{
//判断是否连接
if(hCom == NULL)
{
TRACE("串口以关闭\n");
return (DWORD)0;
}
DWORD dwError;
COMSTAT comStat;
DWORD readLength=0;
if(!ClearCommError(hCom,&dwError,&comStat))
{
return FALSE;
}
//在该读取中使用了同步方式,因些要传递readLength以返回引响的字节数
//对于异步方式要指定重叠结构,可不指定已读取节数 将读取操作跟m_OverlappedRead结构体中的hEvent事件关连起来
if(!::ReadFile(hCom,buffer,bufferLength,&readLength,NULL))
{
TRACE("读串口出错\n");
return FALSE;
}
return readLength;
}
DWORD CSerialPort::WriteCom(LPVOID buffer, DWORD bufferLength)
{
//判断是否连接
if(hCom == NULL)
{
TRACE("串口以关闭\n");
return (DWORD)0;
}
DWORD writeLength;
DWORD dwError;
COMSTAT comStat;
if(!ClearCommError(hCom,&dwError,&comStat))
return FALSE;
//对于同步来说要定读这次读取的字节数,即第三个参数
//对于异步方式要指定重叠结构,可不指定已写入字节数 将写入操作跟m_OverlappedWrite结构体中的hEvent事件关连起来
if(!WriteFile(hCom,buffer,bufferLength,&writeLength,&m_OverlappedWrite))
{
TRACE("写入串口出错");
return FALSE;
}
return writeLength;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -