/*
** FILENAME CSerialPort.cpp
**
** PURPOSE This class can read, write and watch one serial port.
** It sends messages to its owner when something happends on the port
** The class creates a thread for reading and writing so the main
** program is not blocked.
**
** CREATION DATE 15-09-1997
** LAST MODIFICATION 12-11-1997
**
** AUTHOR Remon Spekreijse
**
** 2007-12-25 mrlong https://code.google.com/p/mycom/
** 2011-11-06 liquanhai http://blog.csdn.net/liquanhai/article/details/6941574
** 2013-12-04 viruscamp https://github.com/viruscamp
** 2014-01-10 itas109 http://blog.csdn.net/itas109
** 2014-12-18 liquanhai http://blog.csdn.net/liquanhai/article/details/6941574
** 2016-05-06 itas109 http://blog.csdn.net/itas109
** 2016-06-22 itas109 http://blog.csdn.net/itas109
** 2016-06-29 itas109 http://blog.csdn.net/itas109
** 2016-08-02 itas109 http://blog.csdn.net/itas109
** 2016-08-10 itas109 http://blog.csdn.net/itas109
** 2017-02-14 itas109 http://blog.csdn.net/itas109
** 2017-03-12 itas109 http://blog.csdn.net/itas109
** 2017-12-16 itas109 http://blog.csdn.net/itas109
** 2017-02-14 itas109 http://blog.csdn.net/itas109
*/
#include "SerialPort.h"
#include "assert.h"
using namespace itas109;
//获取注册表指定数据到list
bool getRegKeyValues(std::string regKeyPath, std::list<std::string> & portsList)
{
#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383
HKEY hKey;
TCHAR achValue[MAX_VALUE_NAME]; // buffer for subkey name
DWORD cchValue = MAX_VALUE_NAME; // size of name string
TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name
DWORD cchClassName = MAX_PATH; // size of class string
DWORD cSubKeys = 0; // number of subkeys
DWORD cbMaxSubKey; // longest subkey size
DWORD cchMaxClass; // longest class string
DWORD cKeyNum; // number of values for key
DWORD cchMaxValue; // longest value name
DWORD cbMaxValueData; // longest value data
DWORD cbSecurityDescriptor; // size of security descriptor
FILETIME ftLastWriteTime; // last write time
int iRet = -1;
bool bRet = false;
std::string m_keyValue;
TCHAR m_regKeyPath[MAX_KEY_LENGTH];
TCHAR strDSName[MAX_VALUE_NAME];
memset(strDSName, 0, MAX_VALUE_NAME);
DWORD nValueType = 0;
DWORD nBuffLen = 10;
#ifdef UNICODE
int iLength;
const char * _char = regKeyPath.c_str();
iLength = MultiByteToWideChar(CP_ACP, 0, _char, strlen(_char) + 1, NULL, 0);
MultiByteToWideChar(CP_ACP, 0, _char, strlen(_char) + 1, m_regKeyPath, iLength);
#else
strcpy_s(m_regKeyPath, MAX_KEY_LENGTH, regKeyPath.c_str());
#endif
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, m_regKeyPath, 0, KEY_READ, &hKey))
{
// Get the class name and the value count.
iRet = RegQueryInfoKey(
hKey, // key handle
achClass, // buffer for class name
&cchClassName, // size of class string
NULL, // reserved
&cSubKeys, // number of subkeys
&cbMaxSubKey, // longest subkey size
&cchMaxClass, // longest class string
&cKeyNum, // number of values for this key
&cchMaxValue, // longest value name
&cbMaxValueData, // longest value data
&cbSecurityDescriptor, // security descriptor
&ftLastWriteTime); // last write time
if (!portsList.empty())
{
portsList.clear();
}
// Enumerate the key values.
if (cKeyNum > 0 && ERROR_SUCCESS == iRet)
{
for (int i = 0; i < (int)cKeyNum; i++)
{
cchValue = MAX_VALUE_NAME;
achValue[0] = '\0';
if (ERROR_SUCCESS == RegEnumValue(hKey, i, achValue, &cchValue, NULL, NULL, NULL, NULL))
{
if (ERROR_SUCCESS == RegQueryValueEx(hKey, (LPCTSTR)achValue, NULL, &nValueType, (LPBYTE)strDSName, &nBuffLen))
{
#ifdef UNICODE
int iLen = WideCharToMultiByte(CP_ACP, 0, strDSName, -1, NULL, 0, NULL, NULL);
char* chRtn = new char[iLen*sizeof(char)];
WideCharToMultiByte(CP_ACP, 0, strDSName, -1, chRtn, iLen, NULL, NULL);
m_keyValue = std::string(chRtn);
delete chRtn;
chRtn = NULL;
#else
m_keyValue = std::string(strDSName);
#endif
portsList.push_back(m_keyValue);
}
}
}
}
else
{
}
}
if (portsList.empty())
{
bRet = false;
}
else
{
bRet = true;
}
RegCloseKey(hKey);
return bRet;
}
//
// Constructor
//
CSerialPort::CSerialPort()
{
m_hComm = NULL;
// initialize overlapped structure members to zero
///初始化异步结构体
m_ov.Offset = 0;
m_ov.OffsetHigh = 0;
// create events
m_ov.hEvent = NULL;
m_hWriteEvent = NULL;
m_hShutdownEvent = NULL;
m_szWriteBuffer = NULL;
m_bThreadAlive = FALSE;
m_nWriteSize = 1;
m_bIsSuspened = FALSE;
// create events
m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
// initialize the event objects
///事件数组初始化,设定优先级别
m_hEventArray[0] = m_hShutdownEvent; // highest priority
//为避免有些串口设备无数据输入,但一直返回读事件,使监听线程阻塞,
//可以将读写放在两个线程中,或者修改读写事件优先级
//修改优先级有两个方案:
//方案一为监听线程中WaitCommEvent()后,添加如下两条语句:
//if (WAIT_OBJECT_O == WaitForSingleObject(port->m_hWriteEvent, 0))
// ResetEvent(port->m_ov.hEvent);
//方案二为初始化时即修改,即下面两条语句:
m_hEventArray[1] = m_hWriteEvent;
m_hEventArray[2] = m_ov.hEvent;
// initialize critical section
///初始化临界资源
InitializeCriticalSection(&m_csCommunicationSync);
}
//
// Delete dynamic memory
//
CSerialPort::~CSerialPort()
{
ClosePort();
// close Handles
if (m_hShutdownEvent != NULL)
{
CloseHandle(m_hShutdownEvent);
}
if (m_ov.hEvent != NULL)
{
CloseHandle(m_ov.hEvent);
}
if (m_hWriteEvent != NULL)
{
CloseHandle(m_hWriteEvent);
}
// delete critical section
//释放临界资源
DeleteCriticalSection(&m_csCommunicationSync);
}
//
// Initialize the port. This can be port 1 to MaxSerialPortNum.
///初始化串口。只能是1-MaxSerialPortNum
//
//parity:
// n=none
// e=even
// o=odd
// m=mark
// s=space
//data:
// 5,6,7,8
//stop:
// 1,1.5,2
//
BOOL CSerialPort::InitPort(HWND pPortOwner, // the owner (CWnd) of the port (receives message)
UINT portnr, // portnumber (1..MaxSerialPortNum)
UINT baud, // baudrate
TCHAR parity, // parity
UINT databits, // databits
UINT stopbits, // stopbits
DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etc
UINT writebuffersize,// size to the writebuffer
DWORD ReadIntervalTimeout,
DWORD ReadTotalTimeoutMultiplier,
DWORD ReadTotalTimeoutConstant,
DWORD WriteTotalTimeoutMultiplier,
DWORD WriteTotalTimeoutConstant)
{
assert(portnr > 0 && portnr < MaxSerialPortNum);
assert(pPortOwner != NULL);
ClosePort();
// set buffersize for writing and save the owner
m_pOwner = pPortOwner;
if (m_szWriteBuffer != NULL)
{
delete[] m_szWriteBuffer;
m_szWriteBuffer = NULL;
}
m_szWriteBuffer = new BYTE[writebuffersize];
m_nPortNr = portnr;
m_nWriteBufferSize = writebuffersize;
m_dwCommEvents = dwCommEvents;
BOOL bResult = FALSE;
TCHAR *szPort = new TCHAR[MAX_PATH];
TCHAR *szBaud = new TCHAR[MAX_PATH];
/*
多个线程操作相同的数据时,一般是需要按顺序访问的,否则会引导数据错乱,
无法控制数据,变成随机变量。为解决这个问题,就需要引入互斥变量,让每
个线程都按顺序地访问变量。这样就需要使用EnterCriticalSection和
LeaveCriticalSection函数。
*/
// now it critical!
EnterCriticalSection(&m_csCommunicationSync);
// if the port is already opened: close it
///串口已打开就关掉
if (m_hComm != NULL)
{
CloseHandle(m_hComm);
m_hComm = NULL;
}
// prepare port strings
_stprintf_s(szPort, MAX_PATH, _T("\\\\.\\COM%d"), portnr);///可以显示COM10以上端口//add by itas109 2014-01-09
// stop is index 0 = 1 1=1.5 2=2
int mystop;
int myparity;
switch (stopbits)
{
case 0:
mystop = O
没有合适的资源?快使用搜索试试~ 我知道了~
VC2017串口通讯实例
共22个文件
h:6个
cpp:4个
bmp:2个
需积分: 25 36 下载量 46 浏览量
2018-11-27
19:33:35
上传
评论 1
收藏 27.07MB ZIP 举报
温馨提示
SerialPort在VC上实现串口通讯相对来说比较简便,有许多用C++做上位机开发的,不可避免的使用到串口。这里根据itas109维护的3.02版本编写了一个实例。希望对大家有帮助。代码在VC2017上编写测试,能够正常使用,请大家放心。
资源推荐
资源详情
资源评论
收起资源包目录
SerialPortTest.zip (22个子文件)
SerialPortTest
Debug
SerialPortTest.sln 1KB
.vs
SerialPortTest
v15
.suo 17KB
Browse.VC.db 73.36MB
SerialPortTest
SerialPortTest.vcxproj.filters 2KB
SerialPortTest.cpp 6KB
SerialPortTest.rc 11KB
resource.h 1KB
SerialPort.cpp 39KB
SerialPortTestDlg.h 2KB
SerialPortTest.h 1KB
SerialPortTestDlg.cpp 12KB
Debug
SerialPort.h 11KB
stdafx.h 3KB
SerialPortTest.vcxproj.user 237B
res
Toolbar.bmp 598B
Toolbar256.bmp 3KB
SerialPortTest.ico 66KB
SerialPortTest.rc2 812B
SerialPortTest.aps 106KB
stdafx.cpp 434B
SerialPortTest.vcxproj 10KB
targetver.h 630B
共 22 条
- 1
资源评论
河西石头
- 粉丝: 4w+
- 资源: 34
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功