简体   繁体   中英

C++ Serial COM Port Access

in uPyCraft IDE or Putty, just sending km.press('a') then it works fine, but in my C++, i tried to writefile with km.press('a'), it doesn't work. i can't find what is wrong

uPyCraft Successfull

`bool CSerialPort::OpenPort(CString portname)
{
    m_hComm = CreateFile(L"//./" + portname,
        GENERIC_READ | GENERIC_WRITE,
        0,
        0,
        OPEN_EXISTING,
        0,
        0);
    if (m_hComm == INVALID_HANDLE_VALUE)
    {
        std::cout << "INVALID HANDLE" << std::endl;
        return false;
    }
    else
        return true;
}

bool CSerialPort::WriteByte(const char * bybyte)
{
    byte iBytesWritten = 0;
    if (WriteFile(m_hComm, &bybyte, 1, &m_iBytesWritten, NULL) == 0)
        return false;
    else
        return true;
}

int main()
{
CSerialPort _serial;

_serial.OpenPort(L"COM4");

_serial.WriteByte("km.press('a')");
}`

i tried this,

but it doesn't work, i also check _serial Isn't INVALID HANDLE.

someone help me for sending "km.press('a')" to serial

and sending km.move(0,1) with using Putty and uPyCraft,

it works fine but

string test = "km.move(0,1)";
DWORD dwBytesWritten;
WriteFile(m_hComm,&test,sizeof(test),dwBytesWritten,NULL);

it doesn't work. just changing km.move(0,1) to km.move(0,10) , then i don't know why but it works fine. what is different with uPyCraft(Putty) and C++?

By the looks of it, I'm assuming your class definition looks something like this:

class CSerialPort {
public:
    bool OpenPort(CString portname);
    bool WriteByte(const char* bybyte);

private:
    HANDLE m_hComm;
    byte m_iBytesWritten;
};
  • byte is not the proper type. DWORD is.
  • CString may be used, but you are using wide string literals anyway so you could just use CreateFileW , std::wstring s and std::wstring_view s.
  • WriteByte implies that you only want to write one byte - and indeed, your implementation does only write one byte - but it's the wrong byte. It writes one byte out of the memory of the bybyte variable, not the memory it points at.

A minor redefinition of the class:

#include <string_view> // added header

class CSerialPort {
public:
    // take a `std::wstring` instead
    bool OpenPort(const std::wstring& portname);

    // WriteBytes instead of WriteByte:
    bool WriteBytes(const void* bytesPtr, DWORD bytesToWrite);

    // write both wide and non-wide string_views    
    bool WriteString(std::string_view str);
    bool WriteString(std::wstring_view str);

private:
    HANDLE m_hComm;
    DWORD m_iBytesWritten; // the proper type
};

The implementation in the .cpp file then becomes:

bool CSerialPort::OpenPort(const std::wstring& portname) {
    // Use CreateFileW since you've hardcoded wide string literals anyway:
    m_hComm = CreateFileW((L"//./" + portname).c_str(),
        GENERIC_READ | GENERIC_WRITE,
        0,
        0,
        OPEN_EXISTING,
        0,
        0);
    return m_hComm != INVALID_HANDLE_VALUE;
}

bool CSerialPort::WriteBytes(const void* bytesPtr, DWORD bytesToWrite)
{
    return
        WriteFile(m_hComm, bytesPtr, bytesToWrite, &m_iBytesWritten, nullptr) != 0;
}

// the WriteString overloads taking string_views pass on the pointer
// and length to `WriteBytes`:
bool CSerialPort::WriteString(std::string_view str) {
    return WriteBytes(str.data(), str.size());
}

bool CSerialPort::WriteString(std::wstring_view str) {
    return WriteBytes(str.data(), str.size() * // wchar_t's are more than 1 byte:
                                  sizeof(std::wstring_view::value_type));
}

And your main would then use the WriteString overload taking a std::string_view (by passing a const char* to WriteString ):

int main()
{
    CSerialPort _serial;

    if(_serial.OpenPort(L"COM4")) {
        _serial.WriteString("km.press('a')");
    } else {
        std::cerr << "failed opening COM4\n";
    }
}

Note: The section you added at the end has several errors:

string test = "km.move(0,1)";
DWORD dwBytesWritten;
WriteFile(m_hComm,&test,sizeof(test),dwBytesWritten,NULL);
  • &test takes the address of the std::string object. You should use test.c_str() to get a const char* to the first character in the string.
  • sizeof(test) gets the size of the std::string object, not the length of the actual string. You should use test.size() instead.
  • dwBytesWritten is passed by value but the function expects a pointer to a DWORD that it can write to. You should use &dwBytesWritten instead.
WriteFile(m_hComm, test.c_str(), test.size(), &dwBytesWritten, NULL);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2025 STACKOOM.COM