/*
** 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 "stdafx.h"
#include "pch.h"
#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;
serialport.zip
需积分: 29 75 浏览量
2021-06-09
09:11:00
上传
评论
收藏 16KB ZIP 举报
qq_40657570
- 粉丝: 1
- 资源: 7
最新资源
- python-leetcode面试题解之第157题用Read4读取N个字符-题解.zip
- python-leetcode面试题解之第156题上下翻转二叉树-题解.zip
- python-leetcode面试题解之第155题最小栈-题解.zip
- python-leetcode面试题解之第153题寻找旋转排序数组中的最小值-题解.zip
- python-leetcode面试题解之第152题乘积最大子数组-题解.zip
- python-leetcode面试题解之第151题反转字符串中的单词-题解.zip
- python-leetcode面试题解之第150题逆波兰表达式求值-题解.zip
- python-leetcode面试题解之第149题直线上最多的点数-题解.zip
- python-leetcode面试题解之第148题排序链表-题解.zip
- python-leetcode面试题解之第147题对链表进行插入排序-题解.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
评论0