#include “pch.h”
#include “serial_com.h”
#include <stdio.h>
#include
#include
#include
#include <Windows.h>
#include <tchar.h>
#include
#include <afx.h>
#include <devguid.h>
#include “setupapi.h”
#pragma comment(lib,“setupapi”)
using namespace std;
HANDLE hSerial = NULL;
TCHAR connect_default[] = L"USB 串行设备";
//
serial_com::serial_com()
{
GetComName();
//auto_connect();
connect_with_name(connect_default, _tcslen(connect_default));
}
serial_com::~serial_com()
{
disconnect_com();
}
//获取串口号
int serial_com::GetComName(void) // std::vector& comList
{
#if USE_REG == 1u
HKEY hkey;
int result;
GetComFriendlyName();
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
_T("Hardware\\DeviceMap\\SerialComm"),
NULL,
KEY_READ,
&hkey);
com_cnt = 0;
if (ERROR_SUCCESS == result) // 打开串口注册表
{
DWORD dwLong, dwSize;
do
{
dwSize = sizeof(portName[com_cnt]) / sizeof(TCHAR);
dwLong = dwSize;
result = RegEnumValue(hkey, com_cnt, portName[com_cnt], &dwLong, NULL, NULL, (LPBYTE)commName[com_cnt], &dwSize);
if (ERROR_NO_MORE_ITEMS == result)
{
break; // commName就是串口名字,如"COM4"
}
com_cnt++;
if (com_cnt >= MAX_NUM)
{
break;
}
} while (1);
RegCloseKey(hkey);
}
return com_cnt;
#endif
#if USE_SETIPAPI == 1u
DWORD i;
TCHAR szBuf[256] = { 0 };
//TCHAR FriendlyName[256] = { 0 };
//构建系统存在的所有设备列表
HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
return 0;
};
SP_DEVINFO_DATA SpDevInfoData = { 0 };
SpDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
com_cnt = 0;
for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &SpDevInfoData); i++)
{
if (!SetupDiGetDeviceRegistryProperty(hDevInfo, &SpDevInfoData, SPDRP_CLASS, NULL, (PBYTE)szBuf, sizeof(szBuf), 0))
{
continue;
}
else
{
if (_tcscmp(szBuf, _T("Ports"))) //过滤端口
{
continue;
}
}
if (SetupDiGetDeviceRegistryProperty(hDevInfo, &SpDevInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)friendly_name[com_cnt], sizeof(friendly_name[com_cnt]), 0))
{
com_cnt++;
//printf("%s\n", FriendlyName);
}
}
if (hDevInfo)
{
SetupDiDestroyDeviceInfoList(hDevInfo); //释放资源
}
return 0;
#endif
}
int serial_com::auto_connect(void)
{
int ret;
int index;
#if USE_REG == 1u
for (index = 0; index < com_cnt; index++)
{
ret = _tcsncmp(portName[index], L"\Device\Serial3", 15);
if (ret == 0)
{
break;
}
}
if (index != com_cnt)
{
connect_com(commName[index]);
}
#endif
#if USE_SETIPAPI == 1u
for (index = 0; index < com_cnt; index++)
{
ret = _tcsncmp(friendly_name[index], L"USB-SERIAL CH340", 16); // USB-SERIAL CH340(COM10)
if (ret == 0)
{
break;
}
}
if (index != com_cnt)
{
CString com(friendly_name[index]);
int start = com.Find(‘(’);
int end = com.Find(‘)’);
friendly_name[index][start] = 0;
friendly_name[index][end] = 0;
TCHAR* com_name = &friendly_name[index][start + 1];
CString s_com_name(com_name);
connect_com(s_com_name);
}
#endif
return 0;
}
int serial_com::connect_with_name(TCHAR* name, int len)
{
int ret;
int index;
#if USE_SETIPAPI == 1u
for (index = 0; index < com_cnt; index++)
{
ret = _tcsncmp(friendly_name[index], name, len); // USB-SERIAL CH340(COM10)
if (ret == 0)
{
break;
}
}
if (index != com_cnt)
{
CString com(friendly_name[index]);
int start = com.Find(‘(’);
int end = com.Find(‘)’);
friendly_name[index][start] = 0;
friendly_name[index][end] = 0;
TCHAR* com_name = &friendly_name[index][start + 1];
CString s_com_name(com_name);
if (connect_com(s_com_name) == 0)
{
is_connect = true;
}
}
#endif
return 0;
}
int serial_com::connect_com(CString com)
{
DWORD baudRate = 2000000; // 波特率CBR_9600 测试2M
CString strComName;
// 打开串口
if (hSerial == NULL)
{
if (com.GetLength() > 4)
{
strComName += "\\\\.\\"; //端口号大于9时,必须加入该字符串
strComName += com;
}
else
{
strComName = com;
}
hSerial = CreateFile(strComName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hSerial == INVALID_HANDLE_VALUE) {
AfxMessageBox(_T("打开串口失败"));
hSerial = NULL;
return -1;
}
}
// 配置串口参数
DCB dcbSerialParams = { 0 };
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
GetCommState(hSerial, &dcbSerialParams);
dcbSerialParams.BaudRate = baudRate; // 设置波特率
dcbSerialParams.ByteSize = 8; // 数据位
dcbSerialParams.StopBits = ONESTOPBIT; // 停止位
dcbSerialParams.Parity = NOPARITY; // 无校验位
SetCommState(hSerial, &dcbSerialParams);
// 清空串口
PurgeComm(hSerial, PURGE_RXCLEAR | PURGE_TXCLEAR);
return 0;
}
int serial_com::disconnect_com(void)
{
// 关闭串口
if (is_connect)
{
is_connect = false;
CloseHandle(hSerial);
}
return 0;
}
int serial_com::com_clear(void)
{
if (is_connect)
{
PurgeComm(hSerial, PURGE_RXCLEAR | PURGE_TXCLEAR);
}
return 0;
}
int serial_com::com_send(CString &buffer, DWORD* write_len)
{
// 发送数据
if (is_connect)
{
WriteFile(hSerial, buffer, buffer.GetLength(), write_len, NULL);
}
return 0;
}
int serial_com::com_send(BYTE* buffer, int len, int* write_len)
{
if (is_connect)
{
WriteFile(hSerial, buffer, len, (DWORD*)write_len, NULL);
}
return 0;
}
int serial_com::com_recv(CString &szBufferRx, DWORD *dwBytesRead)
{
BYTE bytBuffer[1024] = { 0 };
(void)ReadFile(hSerial, bytBuffer, 1024, dwBytesRead, NULL);
szBufferRx = CString(bytBuffer);
return 0;
}
/*
使用示例
CString send(“test send”);
DWORD send_len;
ch_com.com.com_send(send, &send_len);
CString recv;
DWORD recv_len;
ch_com.com.com_recv(recv, &recv_len);
/
int serial_com::com_recv(BYTE szBufferRx, int len, DWORD* dwBytesRead)
{
(void)ReadFile(hSerial, szBufferRx, len, dwBytesRead, NULL);
return 0;
}
int serial_com::com_recv_block(CString& szBufferRx, DWORD need_cnt)
{
BYTE bytBuffer[1024] = { 0 };
DWORD cur = 0, cnt;
while (cur < need_cnt)
{
(void)ReadFile(hSerial, bytBuffer + cur, 1024, &cnt, NULL);
cur += cnt;
}
szBufferRx = CString(bytBuffer);
return 0;
}