我已经创建了用于在Visual Studio C ++ v 14中打开串行端口的代码框架。我需要将其作为DLL,因此我创建了DLL项目,然后将控制台项目添加到解决方案中进行测试,需要输出作为链接的静态库。我遵循了StackOverflow和其他地方提供的串行通信概述,并且在Visual Studio中以“调试”模式运行时,程序的行为符合预期。例如我可以打开一个端口并进行所有设置,如果该端口正在被TeraTerm之类的另一个程序使用,它将给我一个拒绝访问错误,并且如果我尝试打开一个未使用的端口,则会得到相应的IO错误。由于不相关的实际原因,我还没有尝试进行全面的交流。
但是,当我尝试从命令行运行可执行文件时,尝试打开端口(Invalid_handle_value)时出现访问被拒绝错误(#5)。同样,如果我尝试打开其他随机端口,则会收到相应的错误,但是我永远无法连接到所需的端口。重新启动后,此行为仍然存在,然后再次打开Visual Studio。我已经尝试过在x64,x86,Debug和Release编译模式下运行,并且以管理员身份运行。
任何方向将不胜感激。我还将注意到,我已经从这台计算机上完全相同的Visual Studio版本成功测试了C#串行通信。
编辑:这部分是硬件问题。我连接了新设备,并能够从控制台进行连接。然而,问题仍然在于为什么调试器可以连接而控制台却不能连接。尽管我的特定问题已解决,但我会保留此开放状态,因为这可能会对其他人有所帮助。
为简洁起见,此处未复制完整的代码。
类定义IMUComms.cpp
from PyQt4 import QtCore, QtGui
import time
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_Dialog1(object):
def setupUi(self, Dialog):
self.frame = QtGui.QFrame(Dialog)
self.frame.setGeometry(QtCore.QRect(40, 20, 311, 391))
self.frame.setFrameShape(QtGui.QFrame.StyledPanel)
self.frame.setFrameShadow(QtGui.QFrame.Raised)
self.frame.setObjectName(_fromUtf8("frame"))
self.label = QtGui.QLabel(self.frame)
self.label.setGeometry(QtCore.QRect(120, 180, 72, 23))
self.label.setObjectName(_fromUtf8("label"))
self.label.setText(_translate("Dialog", "omniOS", None))
Dialog.setObjectName(_fromUtf8("Dialog"))
Dialog.resize(391, 437)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
Dialog.setWindowTitle(_translate("Dialog", "OmniOS", None))
class Ui_Dialog2(object):
def setupUi(self, Dialog):
self.frame_2 = QtGui.QFrame(Dialog)
self.frame_2.setGeometry(QtCore.QRect(30, 30, 311, 391))
self.frame_2.setFrameShape(QtGui.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtGui.QFrame.Raised)
self.frame_2.setObjectName(_fromUtf8("frame_2"))
self.label_2 = QtGui.QLabel(self.frame_2)
self.label_2.setGeometry(QtCore.QRect(50, 230, 72, 31))
self.label_2.setObjectName(_fromUtf8("label_2"))
self.lineEdit = QtGui.QLineEdit(self.frame_2)
self.lineEdit.setGeometry(QtCore.QRect(150, 230, 113, 33))
self.lineEdit.setObjectName(_fromUtf8("lineEdit"))
self.label_2.setText(_translate("Dialog", "Login", None))
Dialog.setObjectName(_fromUtf8("Dialog"))
Dialog.resize(391, 437)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
self.retranslateUi(Dialog)
def retranslateUi(self, Dialog):
Dialog.setWindowTitle(_translate("Dialog", "OmniOS", None))
class Dialog1(QtGui.QDialog, Ui_Dialog1):
def __init__(self, parent=None):
super(Dialog1, self).__init__(parent)
self.setupUi(self)
class Dialog2(QtGui.QDialog, Ui_Dialog2):
def __init__(self, parent=None):
super(Dialog2, self).__init__(parent)
self.setupUi(self)
if __name__=="__main__":
import sys
a = QtGui.QApplication(sys.argv)
w1 = Dialog1()
w2 = Dialog2()
def on_timeout():
w1.hide()
w2.show()
w1.show()
QtCore.QTimer.singleShot(3000, on_timeout)
sys.exit(a.exec_())
头文件
#include "stdafx.h"
#include "IMUComms.h"
namespace Magnolia {
std::ostream &operator<<(std::ostream &stream,
IMUComms &ob) {
stream << "Class: IMUComms\r\n";
stream << ob.getCfgFromObj() << std::endl;
return stream;
}
IMUComms::IMUComms()
{
this->portSet = FALSE;
}
IMUComms::~IMUComms()
{
}
IMUComms* IMUComms::New() {
return new IMUComms;
}
void IMUComms::Delete() {
delete this;
}
void IMUComms::setCOMParams(std::string p, int baud,std::string pm)
{
this->setComPort(p);
this->setBaudRate(baud);
this->setPortMode(pm);
this->portSet = true;
}
void IMUComms::setComPort(std::string comPort) {
std::string cp;
#ifdef _WIN32
cp = "\\\\.\\" + comPort;
//cp = comPort;
#else
cp = comPort;
#endif
this->comPort = cp;
}
void IMUComms::setBaudRate(int baud) {
this->baudRate = baud;
}
void IMUComms::setPortMode(std::string pm) {
//Check port mode first
if (pm.length() != 3) {
throw std::invalid_argument("Invalid port mode");
}
//\TODO perform better checks
std::string mode;
mode = "baud=" + std::to_string(this->baudRate);
mode = mode + " data=" + pm.at(0);
mode = mode + " parity=" + pm.at(1);
mode = mode + " stop=" + pm.at(2);
mode = mode + " dtr=on rts=on";
this->portMode = mode;
}
void IMUComms::openCOMPort() {
if (this->portSet == false) {
throw std::invalid_argument("Com port parameters not set");
return;
}
//std::wstring temp = std::wstring(this->comPort.begin(), this->comPort.end());
this->Cport = CreateFileA(this->comPort.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
std::cout << "Cport object created" << std::endl;
std::chrono::seconds dura(1);
std::this_thread::sleep_for(dura);
if (this->Cport == INVALID_HANDLE_VALUE) {
DWORD e = GetLastError();
if (e == 5) {
std::string emsg;
emsg = "Unable to open Com port (" + this->comPort + "). Access is denied.\r\n";
throw std::invalid_argument(emsg);
return;
}
else if (e == 2) {
throw std::invalid_argument("Unable to open Com port. Port not found.\r\n");
return;
}
else {
throw std::invalid_argument("Unable to open Com port. Invalid handle value.\r\n");
return;
}
}
std::cout << "Com port opened." << std::endl;
//DCB port_settings;
memset(&this->port_settings, 0, sizeof(this->port_settings));
this->port_settings.DCBlength = sizeof(this->port_settings);
if (!BuildCommDCBA(this->portMode.c_str(), &this->port_settings)) {
throw std::invalid_argument("Unable to set DCB settings.");
CloseHandle(this->Cport);
return;
}
std::cout << "DCB settings set." << std::endl;
if (!SetCommState(this->Cport, &this->port_settings)) {
throw std::invalid_argument("Unable to set Com port cfg settings.");
CloseHandle(this->Cport);
return;
}
std::cout << "Cfg settings set." << std::endl;
//COMMTIMEOUTS Cptimeouts;
this->Cptimeouts.ReadIntervalTimeout = MAXDWORD;
this->Cptimeouts.ReadTotalTimeoutMultiplier = 0;
this->Cptimeouts.ReadTotalTimeoutConstant = 0;
this->Cptimeouts.WriteTotalTimeoutMultiplier = 0;
this->Cptimeouts.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(this->Cport, &this->Cptimeouts)) {
throw std::invalid_argument("Unable to set Com port timeout settings.");
CloseHandle(this->Cport);
return;
}
std::cout << "Timeout settings set." << std::endl;
}
void IMUComms::closeCOMPort() {
CloseHandle(this->Cport);
}
std::string IMUComms::getCfgFromObj() {
std::string outp;
outp = "----------------------------\r\n";
outp = outp + "User defined parameters:\r\n";
outp = outp + "Port: " + this->comPort + "\r\n";
outp = outp + "Baud rate: " + std::to_string(this->baudRate) + "\r\n";
outp = outp + "Cfg: " + this->portMode + "\r\n";
outp = outp + "----------------------------\r\n";
outp = outp + "Parameters set in Com object:\r\n";
if (this->Cport != INVALID_HANDLE_VALUE) {
outp = outp + "Baud rate: " + std::to_string(this->port_settings.BaudRate) + "\r\n";
outp = outp + "Byte length: " + std::to_string(this->port_settings.ByteSize) + "\r\n";
outp = outp + "Parity (0-4: none, odd, even, mark, space): " + std::to_string(this->port_settings.Parity) + "\r\n";
outp = outp + "Stop bits (0-2: 1, 1.5, 2): " + std::to_string(this->port_settings.StopBits) + "\r\n";
outp = outp + "DTR control: " + std::to_string(this->port_settings.fDtrControl) + "\r\n";
outp = outp + "RTS control: " + std::to_string(this->port_settings.fRtsControl) + "\r\n";
outp = outp + "----------------------------\r\n";
return outp;
}
outp = outp + "No available settings.\r\n";
outp = outp + "----------------------------\r\n";
return outp;
}
}
“木兰”头文件
#ifndef __IMUComms_h
#define __IMUComms_h
#include "IMUC.h"
#include "Magnolia.h"
#include <chrono>
namespace Magnolia {
class IMUComms : public IMUC
{
friend std::ostream &operator<<(std::ostream &stream,
IMUComms &ob);
public:
static IMUComms* New();
void Delete();
void setCOMParams(std::string p, int baud, std::string pm);
void openCOMPort();
void closeCOMPort();
std::string getCfgFromObj();
protected:
IMUComms();
~IMUComms();
void setComPort(std::string comPort);
void setBaudRate(int baud);
void setPortMode(std::string pm);
// ========== Data Members ==========
std::string comPort;
int baudRate;
int dataLen;
std::string portMode;
bool portSet;
HANDLE Cport;
DCB port_settings;
COMMTIMEOUTS Cptimeouts;
};
}
#endif
测试代码
#ifndef __magnolia_h
#define __magnolia_h
#include <complex>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <stdexcept>
#include <memory>
#include <thread>
#include "stdafx.h"
//#include <Eigen/Core>
//#include <Eigen/StdVector>
#if defined(__linux__) || defined(__FreeBSD__)
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <errno.h>
#else
#include<Windows.h>
#endif
namespace Magnolia {
///Typedef Real set as double
typedef double Real;
///Typedef Complex set as double
typedef std::complex<Real> Complex;
//typedef Eigen::Matrix<Real, Eigen::Dynamic, 1> VectorXr;
//typedef Eigen::Matrix<Real, 3, Eigen::Dynamic> Vector3Xr;
//typedef Eigen::Matrix<Real, 4, Eigen::Dynamic> Vector4Xr;
//For the UM7 IMU
typedef struct UM7_packet_struct
{
uint8_t Address;
uint8_t PT;
uint16_t Checksum;
uint8_t data_length;
uint8_t data[30];
} UM7_packet;
}
#endif
在Visual Studio中运行时的输出:
#include "stdafx.h"
#include "../IMURead/IMURead/Magnolia_base"
#include <iostream>
using namespace Magnolia;
int main(int argc, char **argv)
{
IMUComms *comms = IMUComms::New();
std::string port = argv[1];
int baud = std::stoi(argv[2]);
std::string pm = argv[3];
comms->setCOMParams(port,baud,pm);
std::cout << *comms << "\r\n";
try {
comms->openCOMPort();
}
catch (const std::invalid_argument& e ) {
std::cout << e.what() << std::endl;
//std::cout << GetLastError() << std::endl;
}
std::cout << *comms << std::endl;
std::cin.ignore();
comms->closeCOMPort();
comms->Delete();
return 0;
}
并在命令提示符下运行时输出(请注意,当流* comms对象时,它将检查无效的句柄并打印您在下面看到的内容):
Class: IMUComms
----------------------------
User defined parameters:
Port: \\.\COM8
Baud rate: 9600
Cfg: baud=9600 data=8 parity=n stop=1 dtr=on rts=on
----------------------------
Parameters set in Com object:
Baud rate: 0
Byte length: 0
Parity (0-4: none, odd, even, mark, space): 0
Stop bits (0-2: 1, 1.5, 2): 0
DTR control: 0
RTS control: 0
----------------------------
Cport object created
Com port opened.
DCB settings set.
Cfg settings set.
Timeout settings set.
Class: IMUComms
----------------------------
User defined parameters:
Port: \\.\COM8
Baud rate: 9600
Cfg: baud=9600 data=8 parity=n stop=1 dtr=on rts=on
----------------------------
Parameters set in Com object:
Baud rate: 9600
Byte length: 8
Parity (0-4: none, odd, even, mark, space): 0
Stop bits (0-2: 1, 1.5, 2): 0
DTR control: 1
RTS control: 1
----------------------------