Error while reading data from serial port - c++

I am writing a program in Visual C++ to access serial port.Code is given below:-
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <commdlg.h>
int nread,nwrite;
void main()
{
COMMTIMEOUTS timeouts;
COMMCONFIG dcbSerialParams;
char *words,*buffRead, *buffWrite;
DWORD dwBytesWritten,dwBytesRead;
HANDLE hSerial= CreateFile(L"COM1", GENERIC_READ | GENERIC_WRITE,
0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if ( hSerial == INVALID_HANDLE_VALUE)
{
if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
printf(" serial port does not exist \n");
}
printf(" some other error occured. Inform user.\n");
}
//DCB dcbSerialParams ;
//GetCommState( hSerial, &dcbSerialParams.dcb);
if (!GetCommState(hSerial, &dcbSerialParams.dcb))
{
printf("error getting state \n");
}
dcbSerialParams.dcb.DCBlength = sizeof(dcbSerialParams.dcb);
dcbSerialParams.dcb.BaudRate = CBR_1200;
dcbSerialParams.dcb.ByteSize = 8;
dcbSerialParams.dcb.StopBits = ONESTOPBIT;
dcbSerialParams.dcb.Parity = NOPARITY;
dcbSerialParams.dcb.fBinary = TRUE;
dcbSerialParams.dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcbSerialParams.dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcbSerialParams.dcb.fOutxCtsFlow = FALSE;
dcbSerialParams.dcb.fOutxDsrFlow = FALSE;
dcbSerialParams.dcb.fDsrSensitivity= FALSE;
dcbSerialParams.dcb.fAbortOnError = TRUE;
if (!SetCommState(hSerial, &dcbSerialParams.dcb))
{
printf(" error setting serial port state \n");
}
GetCommTimeouts(hSerial,&timeouts);
timeouts.ReadIntervalTimeout = 1000;
timeouts.ReadTotalTimeoutConstant = 1000;
timeouts.ReadTotalTimeoutMultiplier = 1000;
timeouts.WriteTotalTimeoutConstant = 1000;
timeouts.WriteTotalTimeoutMultiplier= 1000;
if(!SetCommTimeouts(hSerial, &timeouts))
{
printf("error setting port state \n");
}
//****************Write Operation*********************//
words = "B";
nwrite = strlen(words);
buffWrite = words;
dwBytesWritten = 0;
if (!WriteFile(hSerial, buffWrite, nwrite, &dwBytesWritten, NULL))
{
printf("error writing to output buffer \n");
}
printf("Data written to write buffer is\n %s \n",buffWrite);
//***************Read Operation******************//
buffRead = 0;
dwBytesRead = 0;
nread = strlen(words);
if (!ReadFile(hSerial, buffRead, nread, &dwBytesRead, NULL))
{
printf("error reading from input buffer \n");
}
printf("Data read from read buffer is \n %s \n",buffRead);
CloseHandle(hSerial);
}
Above program is working properly while write operation (i.e writing data on serial port) but while read operation its is not reading data from serial port.
I am getting output on console window is given below:-
Data written to write buffer is
B
error reading from input buffer
Data read from read buffer is
<null>
I want to know where I am getting wrong and how to resolve it.

The second ReadFile parameter cannot be NULL. It should be valid pointer to some buffer, for example:
dwBytesRead = 0;
nread = strlen(words);
buffRead = new char[nread + 1];
memset(buffRead, 0, nread+1]; // ensure that string will be null-terminated
if (!ReadFile(hSerial, buffRead, nread, &dwBytesRead, NULL))
{
printf("error reading from input buffer \n");
}
...
delete[] buffRead;

Related

write to com port and read answer immediately in c++ windows7

I have a measurment device and want to make a series of measurments and store them to a file.
For this I need to read out the com port properly. All I get back with this code is some weird signs.
#include <windows.h>
#include <process.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
int main() {
// opening the serial port
HANDLE hSerial;
fprintf(stderr, "Opening serial port...");
hSerial = CreateFile("\\\\.\\COM2",
GENERIC_READ | GENERIC_WRITE, 0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hSerial == INVALID_HANDLE_VALUE) {
fprintf(stderr, "Error\n");
CloseHandle(hSerial);
return 1;
} else
fprintf(stderr, "OK\n");
// settings to communicate with device
DCB dcbSerialParams;
ZeroMemory(&dcbSerialParams, sizeof(dcbSerialParams));
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (!GetCommState(hSerial, &dcbSerialParams)) {
//error getting state
fprintf(stderr,"error getting state ... ");
}
dcbSerialParams.BaudRate = 9600;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
if (!SetCommState(hSerial, &dcbSerialParams)) {
//error setting state
fprintf(stderr,"error setting state ...");
}
char out_message[] = "fetch?"; // request for the device to send voltage and
current
char in_message[32];
DWORD BytesToWrite = sizeof(out_message);
DWORD BytesWritten;
DWORD BytesToRead = sizeof(in_message);
DWORD BytesRead;
WriteFile(hSerial, out_message, BytesToWrite, &BytesWritten, NULL);
ReadFile(hSerial, &in_message, BytesToRead, &BytesRead, NULL);
string buffer;
for (unsigned int i = 0; i < sizeof(in_message); i++) {
buffer += in_message[i];
}
buffer[sizeof(in_message) - 1] = '\0';
// try outs of different outputs
cout << buffer << "\n";
const char*c = buffer.c_str();
printf("%s\n",c);
CloseHandle(hSerial);
return 0;
}
I guess I cannot write to com an read out immediately?
Or is there a mistake in the conversion in_message to buffer?

Serial port communication read function cannot read full response

I am having issues with reading complete return string after sending an "ATZ" command to my OBDII dongle device with an STN1100 chip in it. Here is the return response of sending "ATZ" command on putty:
Here is my COM setting code:
LPCWSTR port = L"COM6";
device = CreateFile(port,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
NULL,
0);
if (device == INVALID_HANDLE_VALUE) {
printf("Failed to open port\n");
printf("error code is %i\n", device);
return false;
}
else
printf("Port is open successfully!\n");
//Settings
/*Timeout*/
COMMTIMEOUTS timeout;
timeout.ReadIntervalTimeout = 1;
timeout.ReadTotalTimeoutConstant = 1;
timeout.ReadTotalTimeoutMultiplier = 1;
timeout.WriteTotalTimeoutConstant = 1;
timeout.WriteTotalTimeoutMultiplier = 1;
if (!SetCommTimeouts(serialHandle, &timeout)) {
printf("Error setting the timeout\n");
printf("Error code: %i\n", GetLastError());
}
/**/
DCB serialParams;
serialParams.DCBlength = sizeof(serialParams);
if (!GetCommState(device, &serialParams)) //need this getCommState before setCommState
printf("Error getting current DCB settings\n");
serialParams.BaudRate = CBR_9600;
serialParams.ByteSize = 8;
serialParams.StopBits = ONESTOPBIT;
serialParams.Parity = NOPARITY;
serialParams.fOutX = FALSE;
serialParams.fInX = FALSE;
serialParams.fBinary = TRUE;
serialParams.fNull = TRUE;
serialParams.fRtsControl = RTS_CONTROL_DISABLE;
if (!SetCommState(device, &serialParams)) {
printf("Error setting the DCB\n");
printf("Error code: %i\n", GetLastError());
}
Here is my Write and Read function:
bool Write(HANDLE device) {
bool bErrorFlag = FALSE;
char DataBuffer[] = "ATZ\n";
//char* cmd = DataBuffer;
DWORD dwBytesToWrite = (DWORD)strlen(DataBuffer);
DWORD dwBytesWritten = 0;
bErrorFlag = WriteFile(
device,
DataBuffer,
3,
&dwBytesWritten,
NULL);
if (!bErrorFlag) {
printf("Failed to write to device\n");
printf("Error code: %i\n", GetLastError());
return false;
}
return true;
}
bool Read(HANDLE device) {
char ReadBuffer[256] = { 0 };
int BUFFERSIZE = 256;
DWORD dwBytesRead = 0;
DWORD read;
OVERLAPPED ol = { 0 };
if (!ReadFile(device, ReadBuffer, BUFFERSIZE - 1, &read, 0))
{
printf("Terminal failure: Unable to read from device.\n GetLastError=%08x\n", GetLastError());
CloseHandle(device);
return false;
}
printf("Response is %s\n", ReadBuffer);
return true;
}
I can only receive returned echo command "ATZ" by running the code above, does anyone know what setting I did wrong? It looks like the read function stops reading from the buffer after receiving the first line.

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.

sending data through serial port in c++

I have copied this code to write through the serial port in c++. It works properly, but what I need now is to know how to convert a string into an array of bytes, because I want to write several strings to communicate with an arduino. I paste the code here:
#include <windows.h>
#include <stdio.h>
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};
// Open the highest available serial port number
fprintf(stderr, "Opening serial port...");
hSerial = CreateFile(
"\\\\.\\COM1", 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
return 0;
}
Here is the part I want to change:
// 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;
I want to use my own strings and a method to transform them into bytes, so that I can send them through the serial port.
A string already is an array of bytes.
char bytes_to_send[] = "hello";

serial port Reading in c++

I am trying to write code in c++ to write and read from serial port i wrote the following code and i am now trying to test this by making loop back on USB to serial cable and when i write any thing except zero i read it successfully but when write zero the program stops reading and doesnot read any thing after the zero and give me zeroes when displaying the read buffer (in this program it displays zeroes for reading buffer but if i write any thing like making writing loop write "words=127-i" the reader buffer will display all i write till it reaches zero) plz any help quickly
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <commdlg.h>
#include <iostream>
//#include <windef.h>
using namespace std;
int nread,nwrite;
void main()
{
HANDLE hSerial;
COMMTIMEOUTS timeouts;
COMMCONFIG dcbSerialParams;
char words[128], *buffWrite;
DWORD dwBytesWritten, dwBytesRead;
hSerial = CreateFile(TEXT("COM1"),GENERIC_READ |GNERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hSerial == INVALID_HANDLE_VALUE)
{
if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
printf(" serial port does not exist \n");
}
printf(" some other error occured. Inform user.\n");
}
// DCB dcbSerialParams ;
//GetCommState( hSerial, &dcbSerialParams.dcb);
if (!GetCommState(hSerial, &dcbSerialParams.dcb))
{
printf("error getting state \n");
}
dcbSerialParams.dcb.DCBlength = sizeof(dcbSerialParams.dcb);
dcbSerialParams.dcb.BaudRate = CBR_2400;
dcbSerialParams.dcb.ByteSize = 8;
dcbSerialParams.dcb.StopBits = ONESTOPBIT;
dcbSerialParams.dcb.Parity = NOPARITY;
dcbSerialParams.dcb.fBinary = TRUE;
dcbSerialParams.dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcbSerialParams.dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcbSerialParams.dcb.fOutxCtsFlow = TRUE;
dcbSerialParams.dcb.fOutxDsrFlow = TRUE;
dcbSerialParams.dcb.fDsrSensitivity= FALSE;
dcbSerialParams.dcb.fAbortOnError = TRUE;
if(!SetCommState(hSerial, &dcbSerialParams.dcb))
{
printf(" error setting serial port state \n");
}
SetCommMask( hSerial,EV_RXCHAR);
GetCommTimeouts(hSerial,&timeouts);
//COMMTIMEOUTS timeouts = {0};
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier= 10;
if(!SetCommTimeouts(hSerial, &timeouts))
{
printf("error setting port state \n");
}
// printf("This is a string to be written to serial port COM1 \n\n\n");
//****************Write Operation*********************//
//words = "This is a string to be written to serial port COM1";
//dwBytesWritten=1;
cout<<"Data written to write buffer is \n";
for(int i=0;i<128;i++)
{
words[i]=i;
cout<<(int)words[i]<<",";
}
cout<<endl;
nwrite = strlen(words);
buffWrite = words;
dwBytesWritten = 0;
if (!WriteFile(hSerial, buffWrite, nwrite, &dwBytesWritten, NULL))
{
printf("error writing to output buffer \n");
}
//***************Read Operation******************//
char buffsRead[128]="0",*buffRead;
dwBytesRead = 0;
nread = strlen(buffsRead);
buffRead = buffsRead;
//ReadFile(hSerial, buffRead, nread, &dwBytesRead, NULL);
if (!ReadFile(hSerial, buffRead, nread, &dwBytesRead, NULL))
{
printf("error reading from input buffer \n");
}
// printf("Data read from read buffer is \n %s \n",(int)buffsRead);
cout<<"Data read from read buffer is \n ";
for(int j=0;j<128;j++)
{
cout<<(int)buffsRead[j]<<",";
}
cout<<endl;
CloseHandle(hSerial);
// system("PAUSE");
}
The problem is in your calculation of the number of bytes to write. You have
nwrite = strlen(words);
and that does not work on binary data, because strlen stops at the first '\0' (NUL character).
Just adjust nwrite inside your loop, so that it ends up with the number of characters added. Replace
words[i]=i;
with
words[nwrite++] = i;
and get rid of nwrite = strlen(words); and things will work better.