在Visual Studio中打开串行端口:可在调试器中使用,但不能在控制台中使用

时间:2018-10-10 10:04:32

标签: c++ visual-studio debugging command-line serial-port

我已经创建了用于在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    
----------------------------

0 个答案:

没有答案