C++: Serial interfacing with Arduino - c++

I've been trying to communicate with Arduino through its serial port and with the C++ code below.
The only thing is: it is always returning an invalid_handle_value.
I've looked everywhere, and all people are using kind of the same code... except it's working for them.
P.S: Arduino is on COM15. This code worked with port COM4 (Bluetooth).
The code
#include "SerialClass.h"
Serial::Serial(char *portName)
{
//We're not yet connected
this->connected = false;
//Try to connect to the given port throuh CreateFile
this->hSerial = CreateFile(portName,
/*GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);*/
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
0);
//Check if the connection was successful.
if (this->hSerial==INVALID_HANDLE_VALUE)
{
//If not success full display an Error.
if (GetLastError()==ERROR_FILE_NOT_FOUND){
//Print Error if neccessary
printf("ERROR: Handle was not attached. Reason: %s not available.\n", portName);
}
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_9600;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=ONESTOPBIT;
dcbSerialParams.Parity=NOPARITY;
//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);
}
}
}
}
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;
}
int main() {
Serial serial("COM15");
if (serial.IsConnected()){
serial.WriteData("1",1);
printf("\nData sent successfully!\n");
}
system("pause");
return 0;
}

Try using a filename of "\\\\.\\COM15" (see http://support.microsoft.com/kb/115831).

Related

C++ Serial communication with Arduino

I am working on a project that has a serial communication between a Windows PC and an Arduino Uno card.
In the C++ code I have a SerialClass.h and a Serial.cpp
My problem is that I get a compiler fault: identifier "SP" undefined
in the function
void Serial::SendtoArd(int val, int var)
{
if (SP->IsConnected())
{
bool writeData = false;
writeData = SP->WriteData("test",4);
}
I know if I define the SP in this function I get rid of this fault, but
I do not want to activate the Serial port in that function . I want to activate the serial port in this function
bool Serial::OpenPtoArd()
{
Serial* SP = new Serial("\\\\.\\COM3"); // adjust as needed
if (SP->IsConnected())
{
bool status = true;
}
}
and keep it active as long as my app is running.
Can anyone help me out here?
Here is the SerialClass.h
#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:
//Serial comm handler
HANDLE hSerial;
//Connection status
bool connected;
//Get various information about the connection
COMSTAT status;
//Keep track of last error
DWORD errors;
public:
//Initialize Serial communication with the given COM port
Serial(char *portName);
//Close the connection
~Serial();
//Read data in a buffer, if nbChar is greater than the
//maximum number of bytes available, it will return only the
//bytes available. The function return -1 when nothing could
//be read, the number of bytes actually read.
int ReadData(char *buffer, unsigned int nbChar);
//Writes data from a buffer through the Serial connection
//return true on success.
bool WriteData(char *buffer, unsigned int nbChar);
//Check if we are actually connected
bool IsConnected();
bool OpenPtoArd();
void SendtoArd(int val, int var);
};
Here is the Serial.cpp
#endif // SERIALCLASS_H_INCLUDED
#include "stdafx.h"
#include "SerialClass.h"
#define LEN 1
bool status = false;
Serial::Serial(char *portName)
{
//We're not yet connected
this->connected = false;
//Try to connect to the given port throuh CreateFile
this->hSerial = CreateFile(portName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
//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) {
//Print Error if neccessary
printf("ERROR: Handle was not attached. Reason: %s not available.\n", portName);
}
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_9600;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
//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);
}
}
}
}
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;
}
void readme()
{
Serial serial("COM3");
char c[LEN + 1];
int numBytes = 0;
while (true)
{
numBytes = serial.ReadData(c, LEN);
if (numBytes != -1)
{
// Terminate the string if we want to use c variable as a string
c[numBytes] = 0;
break;
}
}
}
bool Serial::OpenPtoArd()
{
Serial* SP = new Serial("\\\\.\\COM3"); // adjust as needed
if (SP->IsConnected())
{
bool status = true;
}
}
void Serial::SendtoArd(int val, int var)
{
if (SP->IsConnected())
{
bool writeData = false;
writeData = SP->WriteData("test",4);
}
}
The problem with this code
bool Serial::OpenPtoArd()
{
Serial* SP = new Serial("\\\\.\\COM3"); // adjust as needed
if (SP->IsConnected())
{
bool status = true;
}
}
is that you are creating the new Serial - and then losing the pointer to that Serial when the function exits. If you want other functions to be able to access it, you need the SP variable to be outside the OpenPtoArd() function.
You can (should?) either make it a member of your class (which by the way will clash with Arduino's Serial class - call it something else!), or make it a global variable: put the following line near the top of the file:
YourSerialClass *SP = NULL;
Note that I set the variable to NULL. Your other code needs to know whether the SP port has been created yet or not - and to not use it if it hasn't been:
if ((SP!=NULL) && (SP->IsConnected()) {
... do SP things
} // if

setting up serial port and writing to following online tutorials

i was reading some online tutorials on how to send a few bytes via the com port.
i solved some problems, but i get stuck on:
WriteFile(hSerial, bytes_to_send, 5, &bytes_written, NULL);
fprintf(stderr, "%d bytes written\n", bytes_written);
the code will output:
- Opening serial port...OK
- Sending bytes...0 bytes written
i would like to send some bytes via the com port to the uart on the micro controller.
this code looks very useful for what i need to do.
the code i'm using:
//
// serial.c / serial.cpp
// A simple serial port writing example
// Written by Ted Burke - last updated 13-2-2013
//
// To compile with MinGW:
//
// gcc -o serial.exe serial.c
//
// To compile with cl, the Microsoft compiler:
//
// cl serial.cpp
//
// To run:
//
// serial.exe
//
#include <windows.h>
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
// Define the five bytes to send ("hello")
char bytes_to_send[5];
bytes_to_send[0] = 104;
bytes_to_send[1] = 101;
bytes_to_send[2] = 108;
bytes_to_send[3] = 108;
bytes_to_send[4] = 111;
// Declare variables and structures
HANDLE hSerial;
DCB dcbSerialParams = {0};
COMMTIMEOUTS timeouts = {0};
TCHAR *pcCommPort = TEXT("COM1");
// Open the highest available serial port number
fprintf(stderr, "Opening serial port...");
//hSerial = CreateFile( ComPortName,
// GENERIC_READ | GENERIC_WRITE,
// 0,
// NULL,
// OPEN_EXISTING,
// FILE_ATTRIBUTE_NORMAL,
// NULL);
hSerial = CreateFile(
pcCommPort, GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if (hSerial == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "Error\n");
return 1;
}
else fprintf(stderr, "OK\n");
// Set device parameters (38400 baud, 1 start bit,
// 1 stop bit, no parity)
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (GetCommState(hSerial, &dcbSerialParams) == 0)
{
fprintf(stderr, "Error getting device state\n");
CloseHandle(hSerial);
return 1;
}
dcbSerialParams.BaudRate = CBR_38400;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
if(SetCommState(hSerial, &dcbSerialParams) == 0)
{
fprintf(stderr, "Error setting device parameters\n");
CloseHandle(hSerial);
return 1;
}
// Set COM port timeout settings
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if(SetCommTimeouts(hSerial, &timeouts) == 0)
{
fprintf(stderr, "Error setting timeouts\n");
CloseHandle(hSerial);
return 1;
}
// Send specified text (remaining command line arguments)
DWORD bytes_written, total_bytes_written = 0;
fprintf(stderr, "Sending bytes...");
if(!WriteFile(hSerial, bytes_to_send, 5, &bytes_written, NULL))
{
fprintf(stderr, "Error\n");
CloseHandle(hSerial);
return 1;
}
fprintf(stderr, "%d bytes written\n", bytes_written);
// Close serial port
fprintf(stderr, "Closing serial port...");
if (CloseHandle(hSerial) == 0)
{
fprintf(stderr, "Error\n");
return 1;
}
fprintf(stderr, "OK\n");
// exit normally
std::cin.get();
return 0;
}
further editing the code using GetLastError() results in:
OVERLAPPED o;
std::memset(&o, 0, sizeof(o));
o.Offset = FILE_WRITE_TO_END_OF_FILE;
o.OffsetHigh = -1;
if(!WriteFile(hSerial, bytes_to_send, 5, &bytes_written, &o))
{
//DWORD WINAPI GetLastError(void);
//wprintf(L"Format message failed with 0x%x\n", GetLastError()); // 0x3e3
printf("Error number: %ld\n", GetLastError()); 995 (0x3E3)
// The I/O operation has been aborted because of either a thread exit or an application request.
fprintf(stderr, "Error\n");
CloseHandle(hSerial);
return 1;
}
fprintf(stderr, "%d bytes written\n", bytes_written);
hyperterminal, can detect my app and want me to close it.
regards and thank you.

Use of Select() cpp with tracking client data needs

First off I am still very new to c++. I am trying to write a GNSS internet radio caster program. Basically when a client logs in and is accepted my program stores what data stream source the client requests in a Client class. I was going to match an array of Client objects and an array of clientSockets using the index number of both arrays however trying to use Select() to check nonblocking sockets has made that complicated. I have found some examples of implementing Select() but I'm not certain how to track the original clientSocket from my array that I use to accept the connection from the listenSocket with.
class Client{
public:
std::string source;
std::string user; //stored in txt file as name:password
boolean connected;
int IndexNumber;
};
typedef struct _MYSOCKET_INFORMATION{
char Buffer[BUFFERSIZE];
WSABUF DataBuf;
SOCKET Socket;
DWORD SendBytes;
DWORD RecvBytes;
}SOCKET_INFORMATION, *LPSOCKET_INFORMATION;
// creates number of objects of this structure
LPSOCKET_INFORMATION SocketList[NUMBER_CLIENTS];
FD_SET Writer;
FD_SET Reader;
DWORD TotalSockets = 0;
DWORD Flags;
u_long NonBlock = 1;
timeval tv;
long tv_sec = 1;
long tv_usec = 0;
//intiate objects
Caster caster;
DataStream datastream[NUMBER_BASES]; //100 base stations max
Client client[NUMBER_CLIENTS];
SOCKET listenSocket;
SOCKET clientSocket[NUMBER_CLIENTS];
SOCKET serverSocket;
char recvArray[BUFFERSIZE];
using namespace std;
int main()
{
//initialize the Read and Write socket sets
FD_ZERO(&Reader);
FD_ZERO(&Writer);
//check for connection attempt
FD_SET(listenSocket, &Reader);
FD_SET(serverSocket, &Reader);
//set read and write state based on state of buffer
for( unsigned int i=0; i<TotalSockets; i++){
if( SocketList[i]->RecvBytes < SocketList[i]->SendBytes){
FD_SET(SocketList[i]->Socket,&Writer);
}
else{
FD_SET(SocketList[i]->Socket,&Reader);
}
}
//Select returns number of sockets ready to be read/writen
Total = select(0, &Reader, &Writer, NULL, &tv);
if(Total == SOCKET_ERROR){
printf("Error select function %d\n", WSAGetLastError());
return 1;
}
if( FD_ISSET(listenSocket, &Reader)){
Total--;
//set current client no
while(client[current].connected == true){
current++;
if(current >= NUMBER_CLIENTS){
current = 0;
count++;
if(count >= 2){//has cylcled twice all must be set to true, can add no more.
count =0;
printf("client limit reached.\n");
break;
}
}
}
clientSocket[current] = accept(listenSocket, NULL, NULL); //setup client connection for further use
if( clientSocket[current] != INVALID_SOCKET){
//set new client to non blocking
check = ioctlsocket(clientSocket[current], FIONBIO, &NonBlock);
if( check == SOCKET_ERROR){
printf("Error setting client to nonblocking mode. %d.\n", WSAGetLastError());
closesocket(clientSocket[current]);
continue;
}
else{
printf("Accepted client connection request \n");
//recieve data
check = recv(clientSocket[current], recvArray, BUFFERSIZE, 0);
if( check == SOCKET_ERROR){ //close connection if error
printf("error recieving login data. %d \n", WSAGetLastError());
closesocket(clientSocket[current]);
continue;
}
if( check == 0){//no data is recieved then client disconnected
printf("ERROR no data, client dsiconnected.\n");
closesocket(clientSocket[current]);
continue;
}
else{
for(int n=0; n<check +1 ; n++){ //must be request message for data per NTRIP 1.0
clientRequest << recvArray[n]; //place read char bytes into stringstream object for parsing.
}
//if request is good returns a client requested source, username, and true false for data send.
checkClientRequest(clientSocket[current], client[current].source, client[current].connected, client[current].user);
}
}
}
}//end of check client listen socket
for(unsigned int i=0; Total>0 && i<TotalSockets; i++){
LPSOCKET_INFORMATION SocketInfo = SocketList[i];
//check if client sends GGA string
if(FD_ISSET(SocketInfo->Socket, &Reader)){
Total--;
SocketInfo->DataBuf.buf = SocketInfo->Buffer;
SocketInfo->DataBuf.len = BUFFERSIZE;
Flags = 0;
SocketInfo->RecvBytes = sizeof(SocketInfo->DataBuf);
check = WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &(SocketInfo->RecvBytes), &Flags, NULL, NULL);
if( check == SOCKET_ERROR){
FreeSocketInformation(i); //shuts down client socket if socket error
continue;
}
else{
memcpy(recvArray, SocketInfo->DataBuf.buf, SocketInfo->RecvBytes +1);
//print data on screen change to sort lines
printf("%s \n", SocketInfo->DataBuf.buf);
}
}
There's more to it than just this but how do I track the structure SocketInfo with my clientSocket[]'s?

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?
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.

Some problem with serial programming in vc++ mfc

When I connect my embedded device to my system, I am running my program which will write to the port my embedded is connect and it prints the reply to console.
When I connect my device and run this program it is not giving any output.
But when I connect my device and use PUTTY to send some commands first and then run my program it is working.
Maybe there is a problem in the way I am starting communication?
My source code is:
#include "stdafx.h"
#include <iostream>
//#include <windows.h>
#include <afx.h>
int main()
{
using namespace std;
int i=0;
// cout << "Hello world!" << endl;
HANDLE hSerial;
hSerial = CreateFile("COM5",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if(hSerial==INVALID_HANDLE_VALUE)
{
if(GetLastError()==ERROR_FILE_NOT_FOUND)
{
// TRACE("serial port does not exist for reading\n");
//serial port does not exist. Inform user.
}
// TRACE("some other error,serial port does not exist for reading\n");
//some other error occurred. Inform user.
}
DCB dcbSerialParams = {0};
dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
if (!GetCommState(hSerial, &dcbSerialParams))
{
// TRACE("error getting state for reading\n");
//error getting state
}
dcbSerialParams.BaudRate=9600;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=ONESTOPBIT;
dcbSerialParams.Parity=NOPARITY;
if(!SetCommState(hSerial, &dcbSerialParams))
{
//TRACE("error setting state for reading\n");
//error setting serial port state
}
COMMTIMEOUTS timeouts={0};
timeouts.ReadIntervalTimeout=50;
timeouts.ReadTotalTimeoutConstant=50;
timeouts.ReadTotalTimeoutMultiplier=10;
timeouts.WriteTotalTimeoutConstant=50;
timeouts.WriteTotalTimeoutMultiplier=10;
if(!SetCommTimeouts(hSerial, &timeouts))
{
// TRACE("some error occured for reading\n");
//error occureed. Inform user
}
int n=100,n1=100;
char szBuff[100];
DWORD dwBytesRead = 0;
char szBuff1[100];
DWORD dwByteswrote = 0;
memset(szBuff1,0,100);
memcpy(szBuff1,"LIST\r",5);
if(!WriteFile(hSerial, szBuff1,5, &dwByteswrote, NULL))
{
cout << "error writing" ;
}
cout << szBuff1 << endl;
cout << dwByteswrote << endl;
while(1)
{
if(!ReadFile(hSerial, szBuff, n1, &dwBytesRead, NULL))
{
cout << "error reading";
break;
}
else
{
cout << dwBytesRead << endl;
szBuff[dwBytesRead]='\0';
if(dwBytesRead>0)
{
cout << (szBuff);
break;
}
}
}
cin >> i;
}
Try this... you will probably need to do the code for exceptions (ex: if the response is bigger than 2024)
bool SendModemATCommand(const string &strCommand, int iModemPort, string &strRetValue)
{
bool bRetValue = false;
strRetValue = "";
char cBuffer[2024];
HANDLE hCom = NULL;
char cComPort[64];
sprintf_s(cComPort,"\\\\.\\COM%d", iModemPort);
hCom = CreateFile( cComPort,
GENERIC_READ | GENERIC_WRITE,
0, // must be opened with exclusive-access
NULL, // no security attributes
OPEN_EXISTING, // must use OPEN_EXISTING
0, // not overlapped I/O
NULL // hTemplate must be NULL for comm devices
);
if (hCom != INVALID_HANDLE_VALUE)
{
COMMTIMEOUTS comTimeOuts;
comTimeOuts.ReadIntervalTimeout = MAXDWORD;
comTimeOuts.ReadTotalTimeoutMultiplier = MAXDWORD;
comTimeOuts.ReadTotalTimeoutConstant = 0;//MAXDWORD;
comTimeOuts.WriteTotalTimeoutMultiplier = 0;
comTimeOuts.WriteTotalTimeoutConstant = 0;
if(SetCommTimeouts(hCom, &comTimeOuts))
{
DCB dcb;
dcb.DCBlength = sizeof(DCB);
if(GetCommState(hCom, &dcb))
{
DWORD dwBytesWritten = 0;
DWORD dwBytesRead = 0;
DWORD dwBytesTotal = 0;
if( WriteFile(hCom, strCommand.c_str(), (int)strCommand.size(), &dwBytesWritten, NULL) )
{
if(dwBytesWritten == strCommand.size())
{
dwBytesRead = 0;
DWORD tickStart = GetTickCount();
bool bTimeOut = false;
while(true)
{
while(ReadFile(hCom, cBuffer + dwBytesTotal, 1, &dwBytesRead, NULL))
{
if(dwBytesRead == 0 && dwBytesTotal != dwBytesWritten)
break;
dwBytesTotal += dwBytesRead;
}
if ( dwBytesTotal == 0 )
{
// timeout
if ( GetTickCount() - tickStart > 10000) // 10 Seconds
{
bTimeOut = true;
break;
}
}
else
break;
}
cBuffer[dwBytesTotal] = '\0';
strRetValue = cBuffer;
if(bTimeOut)
strRetValue = "Timed out:" + strCommand;
else
bRetValue = true;
}
}
}
}
CloseHandle(hCom);
}
return bRetValue;
}
Most likely the problem is with your initialization.
I recall having this type of trouble before and Com Timeouts structure was particularly troublesome.
I suggest you get a null modem cable from COM5 to another port on the machine (if you have one), or to another computer. Then use a terminal program to open up the other port and see you can see the "List" command coming through when you run the program. If not then it's very likely to be related to the way you are initializing & opening the com port.
This link may prove useful. Just strip out the Afx stuff and look particularly at the initialization.
http://www.codeproject.com/KB/system/chaiyasit_t.aspx
One other suggestion, you only send List once. If the device is not already plugged in and ready, nothing will happen. Maybe it should keep sending the list command until it gets a
Response.
Also, do you need "List\r\n" or just "List\r"? What is the other ends expecting?