Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

access serial port by visual C++

I want to access serial port by visual c++ I get the program from internet but when I run the program, it seems the port can not open

here my program serialClass.cpp

#ifndef SERIALCLASS_H_INCLUDED
#define SERIALCLASS_H_INCLUDED
#define ARDUINO_WAIT_TIME 2000
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

class Serial
{
private:
    HANDLE hSerial;
    bool connected;
    COMSTAT status;
    DWORD errors;

public:
    Serial(char *portName);
    //Serial();
    ~Serial();
    int ReadData(char *buffer, unsigned int nbChar);
    bool WriteData(char *buffer, unsigned int nbChar);
    bool IsConnected();
};
#endif // SERIALCLASS_H_INCLUDED

and my Serial.cpp

#include "SerialClass.h"
 Serial::Serial(char *portName)
 //Serial::Serial()
{
//We're not yet connected
this->connected = false;

//Try to connect to the given port throuh CreateFile
this->hSerial = CreateFile((LPCWSTR) portName,
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        0);

//Check if the connection was successfull
if(this->hSerial==INVALID_HANDLE_VALUE)
{
    //If not success full display an Error
    if(GetLastError()==ERROR_FILE_NOT_FOUND){

     printf("ERROR: Handle was not attached. Reason: COM1 not available.\n");
    }
    else
    {
        printf("ERROR!!!");
    }
}
else
{
    //If connected we try to set the comm parameters
    DCB dcbSerialParams = {0};

    //Try to get the current
    if (!GetCommState(this->hSerial, &dcbSerialParams))
    {
        //If impossible, show an error
        printf("failed to get current serial parameters!");
    }
    else
    {
        //Define serial connection parameters for the arduino board
        dcbSerialParams.BaudRate=CBR_19200;
        dcbSerialParams.ByteSize=8;
        dcbSerialParams.StopBits=ONESTOPBIT;
        dcbSerialParams.Parity=NOPARITY;
        dcbSerialParams.fOutX=TRUE;
        dcbSerialParams.fInX=TRUE;


         //Set the parameters and check for their proper application
         if(!SetCommState(hSerial, &dcbSerialParams))
         {
            printf("ALERT: Could not set Serial Port parameters");
         }
         else
         {
             //If everything went fine we're connected
             this->connected = true;
             //We wait 2s as the arduino board will be reseting
             //Sleep(ARDUINO_WAIT_TIME);
             printf("Current Settings\n Baud Rate %d\n Parity %d\n Byte Size %d\n Stop Bits %d", dcbSerialParams.BaudRate, 
    dcbSerialParams.Parity, dcbSerialParams.ByteSize, dcbSerialParams.StopBits);
         }
    }
}
}

Serial::~Serial()
{
//Check if we are connected before trying to disconnect
if(this->connected)
{
    //We're no longer connected
    this->connected = false;
    //Close the serial handler
    CloseHandle(this->hSerial);
}
}

 int Serial::ReadData(char *buffer, unsigned int nbChar)
 {
//Number of bytes we'll have read
DWORD bytesRead;
//Number of bytes we'll really ask to read
unsigned int toRead;

//Use the ClearCommError function to get status info on the Serial port
ClearCommError(this->hSerial, &this->errors, &this->status);

//Check if there is something to read
if(this->status.cbInQue>0)
{
    //If there is we check if there is enough data to read the required number
    //of characters, if not we'll read only the available characters to prevent
    //locking of the application.
    if(this->status.cbInQue>nbChar)
    {
        toRead = nbChar;
    }
    else
    {
        toRead = this->status.cbInQue;
    }

    //Try to read the require number of chars, and return the number of read bytes on success
    if(ReadFile(this->hSerial, buffer, toRead, &bytesRead, NULL) && bytesRead != 0)
    {
        return bytesRead;
    }
}
//If nothing has been read, or that an error was detected return -1
return -1;
}

bool Serial::WriteData(char *buffer, unsigned int nbChar)
{
DWORD bytesSend;

//Try to write the buffer on the Serial port
if(!WriteFile(this->hSerial, (void *)buffer, nbChar, &bytesSend, 0))
{
    //In case it don't work get comm error and return false
    ClearCommError(this->hSerial, &this->errors, &this->status);

    return false;
}
else
    return true;
}

bool Serial::IsConnected()
{
     //Simply return the connection status
return this->connected;
 }

The result is always

ERROR: Handle was not attached. Reason: COM1 not available.

any body can help?

like image 226
Limavolt Avatar asked Dec 24 '12 03:12

Limavolt


1 Answers

The problem is with casting to a wide string instead of converting, I replaced that part of the code opening the port with the following and it worked:

wchar_t wcPort[64];
size_t convertedChars = 0;
mbstowcs_s(&convertedChars, wcPort, strlen(portName), portName, _TRUNCATE);

this->hSerial = CreateFile(wcPort,
    GENERIC_READ | GENERIC_WRITE,
    0,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    0);

Or as Ben Voigt has pointed out in a comment you could also call the CreateFileA variant so that Windows performs the conversion for you.

like image 64
PeterJ Avatar answered Oct 16 '22 09:10

PeterJ