【发布时间】:2017-09-22 13:41:20
【问题描述】:
我的程序通常会在启动时检测操作系统中可用的串行端口。如果端口可以通过名称访问,这是一种简单的轮询方法。
项目定义为串口
std::string COMPortNumber[MAXPORTS] {"\\\\.\\COM1", "\\\\.\\COM2", "\\\\.\\COM3", "\\\\.\\COM4", "\\\\.\\COM5",
"\\\\.\\COM6", "\\\\.\\COM7", "\\\\.\\COM8", "\\\\.\\COM9", "\\\\.\\COM10",
"\\\\.\\COM11", "\\\\.\\COM12", "\\\\.\\COM13", "\\\\.\\COM14", "\\\\.\\COM15",
"\\\\.\\COM16", "\\\\.\\COM17", "\\\\.\\COM18", "\\\\.\\COM19", "\\\\.\\COM20"};
std::string COMPortName[MAXPORTS] = {"com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9", "com10",
"com11", "com12", "com13", "com14", "com15", "com16", "com17", "com18", "com19", "com20"};
轮询功能:
void updateSerialList(){
ComboBox_ResetContent(SerialPortDropDown); //clears all content from drop down box
//int iresult = ComboBox_AddString(SerialPortDropDown, "Update Port List\0");
for(int n=0; n<MAXPORTS; n++)
{
COMPortAvailable[n] = serial.getComPortList( COMPortNumber[n] );
if(COMPortAvailable[n] == true)
{
char* tempBuf = new char[COMPortName[n].length() + 1];
for(unsigned int t=0; t<COMPortName[n].length(); t++)
{
tempBuf[t] = COMPortName[n][t];
}
tempBuf[COMPortName[n].length()] = '\0';
int iResult = ComboBox_AddString(SerialPortDropDown, tempBuf);
{
if(iResult == CB_ERR){std::cout << "error adding string" << std::endl;}
else if(iResult == CB_ERRSPACE){std::cout << "error no room" << std::endl;}
}
delete[] tempBuf;
}
}
//place baud rates in select box
for(int n=NUMBERBAUDRATES-1; n>-1; n--)
{
char* tempBuf = new char[BaudRateName[n].length() + 1];
for(unsigned int t=0; t<BaudRateName[n].length(); t++)
{
tempBuf[t] = BaudRateName[n][t];
}
tempBuf[BaudRateName[n].length()] = '\0';
int iResult = ComboBox_AddString(BaudRateDropDown, tempBuf);
{
if(iResult == CB_ERR){std::cout << "error adding string" << std::endl;}
else if(iResult == CB_ERRSPACE){std::cout << "error no room" << std::endl;}
}
delete[] tempBuf;
}
这会在下拉框中编译一个列表供用户选择。它使用类中的函数作为串行实例。这是类内部的函数调用。
bool getComPortList(std::string portName)
{
bool test;
HANDLE testSerial;
testSerial = CreateFile( (portName.c_str()) , GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, NULL, NULL);
if(testSerial == INVALID_HANDLE_VALUE)
{
test = false;
}
else
{
test = true;
cout << "port number " << portName << " is available" << endl;
}
CloseHandle(testSerial);
return test;
}
在我尝试在 Windows 10 上运行该程序之前,此方法一直运行良好。它之前已在 Vista、Win7、Win 8.1 上进行过测试和使用,但是即使 Windows10 设备管理器显示系统上有可用的通讯端口,我的程序也不能获取它们的列表。
Win10串口访问有什么不同?
【问题讨论】:
-
起初这种方法很丑陋,而且不正确。如果“不工作”,您第二次需要
CM_Get_Device_Interface_ListW(&GUID_DEVINTERFACE_COMPORT,..)- 查看错误返回的位置 -
这种情况正在发生变化,物联网正在大肆宣传,Windows.Devices 命名空间很好地支持,没有人愿意再支持这些传统的虚拟 COM 端口了。您需要为您使用的任何设备找到另一个驱动程序。
-
如果
CreateFile返回INVALID_HANDLE_VALUE这并不意味着该文件不存在。你需要调用GetLastError()并且只有当它返回ERROR_FILE_NOT_FOUND- 文件真的不存在。我猜你得到的是ERROR_ACCESS_DENIED -
此程序仅用于从嵌入式设备发送和接收串行 ASCII 消息。它还允许向设备发送配置消息,也严格使用 ASCII 行。我的设备最终用户并非都拥有 win10 笔记本电脑。所以问题是如果我确实实现了 windows.devices 命名空间,它会向后兼容吗?不是每个人都购买新笔记本电脑。我还有一个正在运行的 Vista。关于调用 get last 错误,如果我被拒绝访问,那么该端口仍然不可供我使用,那该怎么办?
-
您尝试做什么 - 确定所有 com 端口的列表或使用某个端口?对于第一个任务,您需要使用
CM_Get_Device_Interface_ListW(&GUID_DEVINTERFACE_COMPORT,..)。 com 设备通常是专有的。这意味着 - 只有一个客户可以打开它。如果两次调用CreateFile,您可以轻松测试这个 - 如果第一次调用返回您确定(处理),第二次返回给您ERROR_ACCESS_DENIED。 那该怎么办? - 什么都没有 - 或向有此错误的用户显示消息
标签: c++ winapi serial-port