I searched a lot and tried many different ways, but I cannot send data to gtkterm via virtual serial bridge (for testing!).
My idea is to communicate with an Atmega uC later on, but first I wanted to test the serial communication by setting up a virtual serial bridge with the help of soccat and controlling the output serial port with gtkterm. The problem is that I'm just receiving useless things in gtkterm... (see screenshots)
soccat command:
socat -d -d PTY: PTY:
The soccat virtual serial port bridge seems to be ok, because I can send data from one serial terminal to another...
gtkterm port preferences:
Port: /dev/pts/6
Baudrate: 9600
Parity: none
Bits: 8
Stopbits: 1
Flow control: none
My little GUI compiles and runs fine, with the input path "/dev/pts/6" and the input baudrate 9600. The program seems to run fine, but in gtkterm are just question marks and quadangles with symbols in every corner coming up. Let's say its not interpretable and independent by the signs as input, BUT the lengths of the output in gtkterm changes by the length of the input (the amount of signs I type in).
Finally here's my code:
main.cpp:
#include <iostream>
#include "serial/serial_communication.cpp"
std::string inputStringUser = "";
int inputIntUser = 0;
std::string pathSerial = "/dev/...";
int baudrate = 19200;
int main()
{
std::cout << "main() [communication_serial_uC] started..." << std::endl;
//GETTING STARTED
std::cout << "Use default port? " << pathSerial << " (Yes = y/ change port = insert the new path" << std::endl;
std::cin >> inputStringUser;
if(inputStringUser != "y" && inputStringUser != "Y")
pathSerial = inputStringUser;
std::cout << "Serial Port is set to: " + pathSerial << std::endl;
std::cout << "Use default baudrate? " << baudrate << "Yes = 0/ change baudrate = insert new baudrate" << std::endl;
std::cin >> inputIntUser;
if(inputIntUser > 0)
baudrate = inputIntUser;
std::cout << "Baudrate is set to: " << baudrate << std::endl;
Serial_communication myPort(pathSerial, baudrate);
//OPEN/ CONFIGURATE PORT
if(myPort.openPort(pathSerial, baudrate) < 0)
{
std::cout << "Error: opening" << std::endl;
return -1;
}
//WRITE PORT
std::cout << "Insert your 'message': (exit = 'exit')" << std::endl;
std::cin >> inputStringUser;
while(inputStringUser != "exit")
{
if(myPort.sendPort(inputStringUser) < 0)
{
std::cout << "Error: sending" << std::endl;
return -1;
}
std::cout << "Insert your 'message': (exit = 'exit')" << std::endl;
std::cin >> inputStringUser;
}
//CLOSE PORT
if(myPort.closePort() < 0)
{
std::cout << "Error: closing" << std::endl;
return -1;
}
std::cout << "main() [communication_serial_uC] beendet..." << std::endl;
return 0;
}
serial/serial_communication.hpp:
#include <iostream>
#include <string>
#include <cstring>
#include <fcntl.h>
#include <termios.h>
class Serial_communication{
public:
Serial_communication(std::string paramPathSerial, int paramBaudrate);
~Serial_communication();
int openPort(std::string pathSerial, int baudrate);
int sendPort(std::string testString);
int closePort();
private:
std::string pathSerial;
int baudrate;
//filedescriptors
int fd;
};
serial/serial_communcation.cpp
#include <iostream>
#include "serial_communication.h"
Serial_communication::Serial_communication(std::string paramPathSerial, int paramBaudrate)
{
fd = 0;
pathSerial = paramPathSerial;
baudrate = paramBaudrate;
}
Serial_communication::~Serial_communication()
{
}
int Serial_communication::openPort(std::string pathSerial, int baudrate)
{
std::cout << "openPort() [serial_communication] started with the following paramters... pathSerial = " << pathSerial << ", baudrate = " << baudrate << std::endl;
//OPENING PORT
//open serial port
fd = open(pathSerial.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
if(fd < 0)
{
std::cout << "Error [serial_communcation]: opening Port: " << pathSerial << std::endl;
return -1;
}
//struct termios
struct termios serial, serial_old;
//get parameters associated with the terminal
if(tcgetattr(fd, &serial) < 0)
{
std::cout << "Error [serial_communication]: getting configuration" << std::endl;
return -1;
}
//safe old parameters
serial_old = serial;
std::cout << "[serial_communication]: Port opened" << std::endl;
//SERIAL CONFIGURATION
/* Set Baud Rate */
cfsetospeed (&serial, (speed_t)baudrate);
cfsetispeed (&serial, (speed_t)baudrate);
// Setting other Port Stuff
serial.c_cflag &= ~PARENB; // Make 8n1
serial.c_cflag &= ~CSTOPB;
serial.c_cflag &= ~CSIZE;
serial.c_cflag |= CS8;
serial.c_cflag &= ~CRTSCTS; // no flow control
serial.c_cc[VMIN] = 1; // read doesn't block
serial.c_cc[VTIME] = 5; // 0.5 seconds read timeout
serial.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
/* Make raw */
cfmakeraw(&serial);
/* Flush Port, then applies attributes */
tcflush( fd, TCIFLUSH );
//set attributes to port
if(tcsetattr(fd, TCSANOW, &serial) < 0)
{
std::cout << "Error [serial_communication]: set attributes" << std::endl;
return -1;
}
//CONFIGURATION FINISHED
std::cout << "openPort() [serial_communication] finished..." << std::endl;
return 1;
}
int Serial_communication::sendPort(std::string textString)
{
std::cout << "write() [Serial_communication] started with the following parameter... textString = " << textString << std::endl;
//attempt to send
if(write(fd, &textString, std::strlen(textString.c_str())) < 0)
{
std::cout << "Error [serial_communcation]: write";
return -1;
}
//SENDING FINISHED
std::cout << "write() [serial_communcation] finished..." << std::endl;
return 1;
}
int Serial_communication::closePort()
{
close(fd);
return 1;
}
So... thats all I got. I tried my best and joined the information from many websites and tried a lots of example codes. My problem is that I dont even know where to search for, so I'm appreciate for any clue...
If there are any questions or information missing, pls let me know it!
Thanks in advance
Thorben
BTW: I'm not THAT experienced with C++ and I'm opened up for comments about my style, but that should not be the main problem...
Related
I use libevent to write client-server application, on client side i want to continiusly wait for intput from console. I tried to run event_base_dispatch in thread, and in main thread ask for input string and add it to bufferevent.
std::thread libevthr(libev_start, base);
std::string s;
do
{
cin >> s;
bufferevent_write(bev, "Hello, world!", 13);
} while(s != "xxx");
libevthr.join();
For some reason this doesn't work, but if i put bufferevent_write inside one of callbacks, it works fine
void event_cb(struct bufferevent *bev, short events, void *ptr)
{
if (events & BEV_EVENT_CONNECTED) {
/* We're connected to 127.0.0.1 Ordinarily we'd do
something here, like start reading or writing. */
bufferevent_write(bev, "Hello, world!", 13);
std::cout << "Connected" << std::endl;
}
if (events & BEV_EVENT_ERROR) {
if (EVUTIL_SOCKET_ERROR() == 10054)
cout << "Server stopped working!" << endl;
else
cout << "Error has happened" << endl;
}
if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR))
{
bufferevent_free(bev);
}
}
Can you explain how should i write this correctly?
Sorry if i have any mistakes in english.
Full code here:
#include "UClient.h"
#include <iostream>
#include "event2/event.h"
#include "event2/listener.h"
#include "event2/bufferevent.h"
#include "event2/buffer.h"
#include <thread>
using std::cout, std::cin, std::endl;
void event_cb(struct bufferevent *bev, short events, void *ptr)
{
if (events & BEV_EVENT_CONNECTED) {
/* We're connected to 127.0.0.1 Ordinarily we'd do
something here, like start reading or writing. */
bufferevent_write(bev, "Hello, world!", 13);
std::cout << "Connected" << std::endl;
}
if (events & BEV_EVENT_ERROR) {
if (EVUTIL_SOCKET_ERROR() == 10054)
cout << "Server stopped working!" << endl;
else
cout << "Error has happened" << endl;
}
if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR))
{
bufferevent_free(bev);
}
}
void write_cb(struct bufferevent *bev, void *ctx)
{
cout << 'Data was written' << endl;
}
void libev_start(event_base *base)
{
event_base_dispatch(base);
}
int main()
{
int port = 9554;
struct event_base *base;
struct bufferevent *bev;
struct sockaddr_in cl_inf;
if (!initWinsock()) {
perror("Failed to initialize Winsock");
return 1;
}
base = event_base_new();
ZeroMemory(&cl_inf, sizeof(cl_inf));
in_addr serv_ip;
inet_pton(AF_INET, "127.0.0.1", &serv_ip);
cl_inf.sin_family = AF_INET;
cl_inf.sin_addr = serv_ip;
cl_inf.sin_port = htons(port);
bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, NULL, write_cb, event_cb, NULL);
if (bufferevent_socket_connect(bev,
(struct sockaddr *)&cl_inf, sizeof(cl_inf)) < 0) {
/* Error starting connection */
std::cout << "Can't connect to server!" << std::endl;
bufferevent_free(bev);
return -1;
}
bufferevent_enable(bev, EV_READ | EV_WRITE);
std::thread libevthr(libev_start, base);
std::string s;
do
{
cin >> s;
} while(s != "xxx");
libevthr.join();
std::cout << "client finished working";
return 0;
}
I have a device (rotary measuring table) connected over USB to /dev/ttyACM0, and need to write a simple cpp controller to send the commands to the device and listen for response.
I have no experience with this kind of stuff. I understand I can open the USB device using fstream and send the command using write(). That works.
Question is how can I send the command and start listening for response?
The code below just hangs. I am guessing because it is synchronous and therefore the response is missed.
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::fstream f;
char command[256] = "?ASTAT\n\r";
char response[256];
std::string str;
f.open("/dev/ttyACM0");
if (f.is_open())
{
std::cout << "Port opened" << std::endl;
}
f.write(command, 256);
while(1)
{
while (f >> str)
{
std::cout << str;
}
}
return 0;
}
I have looked into asynchronious libusb-1.0 but have a problem finding my way around http://libusb.sourceforge.net/api-1.0/group__libusb__asyncio.html and figuring out where to start from.
EDIT:
I managed to get the device to respond as follows:
std::string response_value = "";
char response = 0;
std::cout << "response: ";
while(1)
{
f << command;
f.read(&response, 1);
if ((int)response == 13)
{
break;
}
std::cout << (response) << " ";
response_value += response;
}
After talking to the producer and trying out different commands and outputting the message, I figured out that the device should send variable length response which always ends with 0x0D or integer 13.
Currently if I send multiple commands after each other, nothing happens.
From other sources I understand I need to set the baud rate, however, fstream has no file descriptor, and `tcgetattr(2)1 reauires file descriptor to initialize the termios structure. Is there a way to retrieve it?
To answer the question the best I can. It is possible to read/write to usb device as a file because the os has drivers which are handling the communication (please correct me if I understood it wrong).
fstream is capable of reading and writing, however it is not possible to adjust the baud rate (frequency at which the device is communication) because the adjustment mus be done on terminal level and is therefore os dependent. For Linux, we must use fctl.h, termios.h and unistd.h. It allows us to set the rate, as well as a timeout in case there is no response from the device.
Therefore, implementing the reading and writing only using cpp functions is quite a bit more complex.
I am posting here my solution which works for me, but any comments on it are welcome.
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <string>
#include <iostream>
bool init_terminal_interface(struct termios& tty, const int file_descriptor)
{
memset(&tty, 0, sizeof tty); // Init the structure;
if (tcgetattr(file_descriptor, &tty) != 0)
{
std::cout << "Error" << errno << " from tcgetattr: " << strerror(errno) << std::endl;
return false;
}
/* Set Baud Rate */
cfsetospeed (&tty, (speed_t)B9600);
cfsetispeed (&tty, (speed_t)B9600);
/* Setting other Port Stuff */
tty.c_cflag &= ~PARENB; // Make 8n1
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag &= ~ICANON;
tty.c_cflag |= CS8;
tty.c_cflag &= ~CRTSCTS; // no flow control
tty.c_cc[VMIN] = 0; //
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
/* Flush Port, then applies attributes */
tcflush(file_descriptor, TCIFLUSH);
if (tcsetattr(file_descriptor, TCSANOW, &tty) != 0) {
std::cout << "Error " << " from tcsetattr: " << strerror(errno) << std::endl;
return false;
}
return true;
}
void send_command(std::string command, const int file_descriptor)
{
write(file_descriptor, command.c_str(), command.size());
std::cout << "Command sent: " << command << std::endl;
}
std::string check_response(int file_descriptor)
{
std::string response_value = "";
char response = 0;
ssize_t n_read = 0;
do {
// In blocking mode, read() will return 0 after timeout.
n_read = read( file_descriptor, &response, 1 );
if (n_read > 0)
{
response_value += response;
}
} while( response != '\r' && (int)response != 13 && n_read != 0);
// In case of timeout it will return an empty string.
return response_value;
}
int open_serial(const std::string serial_path)
{
int file_descriptor = open(serial_path.c_str(), O_RDWR);
if (file_descriptor == -1)
{
std::cout << "Unable to access the turntable device." << std::endl;
return -1;
}
std::cout << "File opened: " << file_descriptor << std::endl;
struct termios tty;
init_terminal_interface(tty, file_descriptor);
return file_descriptor;
}
int main()
{
int file_descriptor = open_serial("/dev/ttyACM0");
if (file_descriptor == -1)
{
return 1;
}
// Good command.
std::string command = "?baudrate\r\n";
send_command(command, file_descriptor);
std::string response_value = check_response(file_descriptor);
std::cout << "Full response: " << response_value << std::endl;
// Wrong command.
command = "?asasdtat\r\n";
send_command(command, file_descriptor);
response_value = check_response(file_descriptor);
std::cout << "Full response: " << response_value << std::endl;
// Good command.
command = "init1\r\n";
send_command(command, file_descriptor);
response_value = check_response(file_descriptor);
std::cout << "Full response: " << response_value << std::endl;
// Good command.
command = "ref1=4\r\n";
send_command(command, file_descriptor);
response_value = check_response(file_descriptor);
std::cout << "Full response: " << response_value << std::endl;
return 0;
}
This is the first time I am implementing ssh programmatically and I am baffled about why my code does not work -- to be more specific, ssh_channel_read() keeps returning 0 bytes read. I don't know what I am doing wrong! I have been following the API instructions step by step but I am obviously omitting something inadvertently.
I am trying to connect to my Pi with a user name + password. Here is the complete code, you can just copy paste this and compile it with:
g++ main.cpp -lssh -o myapp
After the code, you can see the output I am getting. Please don't be harsh, like I said, this is the first time I am dealing with SSH:
#include <iostream>
#include <string>
#include <libssh/libsshpp.hpp>
int main(int argc, const char **argv)
{
int vbs = SSH_LOG_RARE;
int timeout_ms = 1000;
ssh_session session = ssh_new();
ssh_channel channel;
char buffer[256];
int bytes_red;
if (session == NULL)
{
std::cout << "Failed to create ssh session." << std::endl;
exit(-1);
}
ssh_set_blocking(session, 1);
std::cout << "Created SSH session..." << std::endl;
ssh_options_set(session, SSH_OPTIONS_HOST, "192.168.1.5");
ssh_options_set(session, SSH_OPTIONS_PORT_STR, "22");
ssh_options_set(session, SSH_OPTIONS_USER, "pi#192.168.1.5");
ssh_options_set(session,SSH_OPTIONS_LOG_VERBOSITY, &vbs);
int con_result = ssh_connect(session);
int auth_result = ssh_userauth_password(session, "pi", "1234");
std::cout << "Connecton Result is: " << con_result << std::endl;
std::cout << "Auth Result is: " << auth_result << std::endl;
///////////////////////////////////////////
// Did we create the session successfully?
///////////////////////////////////////////
if (con_result != SSH_OK)
{
std::cout << "SSH connection failed. Error code is: " << con_result << std::endl;
ssh_free(session);
return con_result;
}
///////////////////////////////////////////
// Did we authenticate?
///////////////////////////////////////////
if (auth_result != SSH_AUTH_SUCCESS)
{
std::cout << "SSH authentication failed. Error code is: " << auth_result << std::endl;
ssh_free(session);
return auth_result;
}
///////////////////////////////////////////
// Create a new ssh_channel
///////////////////////////////////////////
channel = ssh_channel_new(session);
if (channel == NULL)
{
std::cout << "Failed to create SSH channel." << std::endl;
ssh_free(session);
return SSH_ERROR;
}
if (ssh_channel_is_open(channel))
std::cout << "Channel is open" << std::endl;
else
std::cout << "Channel is closed" << std::endl;
while(!ssh_channel_is_eof(channel))
{
bytes_red = ssh_channel_read_timeout(channel, buffer, sizeof(buffer), 0, timeout_ms);
// if (bytes_red)
std::cout << "Bytes read: " << bytes_red << std::endl;
}
std::cout << "Exiting ..." << std::endl;
ssh_channel_close(channel);
ssh_channel_free(channel);
ssh_free(session);
return 0;
}
and here is the output I am getting when running it:
$./myapp
Created SSH session...
[2018/05/19 14:57:14.246759, 1] socket_callback_connected: Socket connection callback: 1 (0)
[2018/05/19 14:57:14.301270, 1] ssh_client_connection_callback: SSH server banner: SSH-2.0-OpenSSH_7.4p1 Raspbian-10+deb9u1
[2018/05/19 14:57:14.301321, 1] ssh_analyze_banner: Analyzing banner: SSH-2.0-OpenSSH_7.4p1 Raspbian-10+deb9u1
[2018/05/19 14:57:14.301337, 1] ssh_analyze_banner: We are talking to an OpenSSH client version: 7.4 (70400)
Connecton Result is: 0
Auth Result is: 0
Channel is closed
[2018/05/19 14:57:14.669298, 1] ssh_packet_process: Couldn't do anything with packet type 80
Bytes read: 0
Bytes read: 0
Bytes read: 0
Bytes read: 0
Bytes read: 0
^C
$
I can see the error, "Channel is closed" but why? What am I doing wrong?
After this, I also want to send data to the server and obviously get the feedback. From what I have read, ssh_channel_write() is the function to use.
I haven't dealt with SSH programmatically before and I am learning this as I write this.
All your help is very much appreciated.
Update
Thank to Jarra, I have solved this! Here is the final code that works!
#include <iostream>
#include <string>
#include <libssh/libsshpp.hpp>
int main(int argc, const char **argv)
{
int vbs = SSH_LOG_RARE;
int timeout_ms = 1000;
ssh_session session = ssh_new();
ssh_channel channel;
char buffer[256];
int bytes_red;
if (session == NULL)
{
std::cout << "Failed to create ssh session." << std::endl;
exit(-1);
}
ssh_set_blocking(session, 1);
std::cout << "Created SSH session..." << std::endl;
ssh_options_set(session, SSH_OPTIONS_HOST, "192.168.1.5");
ssh_options_set(session, SSH_OPTIONS_PORT_STR, "22");
ssh_options_set(session, SSH_OPTIONS_USER, "pi#192.168.1.5");
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &vbs);
int con_result = ssh_connect(session);
int auth_result = ssh_userauth_password(session, "pi", "1234");
std::cout << "Connecton Result is: " << con_result << std::endl;
std::cout << "Auth Result is: " << auth_result << std::endl;
///////////////////////////////////////////
// Did we create the session successfully?
///////////////////////////////////////////
if (con_result != SSH_OK)
{
std::cout << "SSH connection failed. Error code is: " << con_result << std::endl;
ssh_free(session);
return con_result;
}
///////////////////////////////////////////
// Did we authenticate?
///////////////////////////////////////////
if (auth_result != SSH_AUTH_SUCCESS)
{
std::cout << "SSH authentication failed. Error code is: " << auth_result << std::endl;
ssh_free(session);
return auth_result;
}
///////////////////////////////////////////
// Create a new ssh_channel
///////////////////////////////////////////
channel = ssh_channel_new(session);
if (channel == NULL)
{
std::cout << "Failed to create SSH channel." << std::endl;
ssh_free(session);
return SSH_ERROR;
}
ssh_channel_open_session(channel);
if (ssh_channel_is_open(channel))
std::cout << "Channel is open" << std::endl;
else
std::cout << "Channel is closed" << std::endl;
int rc = ssh_channel_request_exec(channel, "ls");
while(!ssh_channel_is_eof(channel))
{
bytes_red = ssh_channel_read_timeout(channel, buffer, sizeof(buffer), 0, timeout_ms);
// if (bytes_red)
// std::cout << "Bytes read: " << bytes_red << std::endl;
std::cout << buffer << std::endl;
}
std::cout << "Exiting ..." << std::endl;
ssh_channel_close(channel);
ssh_channel_free(channel);
ssh_free(session);
return 0;
}
To compile: g++ main.cpp -lssh -o myapp and here is what you get when I run it:
./myapp
Created SSH session...
[2018/05/19 16:01:41.830861, 1] socket_callback_connected: Socket connection callback: 1 (0)
[2018/05/19 16:01:41.884875, 1] ssh_client_connection_callback: SSH server banner: SSH-2.0-OpenSSH_7.4p1 Raspbian-10+deb9u1
[2018/05/19 16:01:41.884929, 1] ssh_analyze_banner: Analyzing banner: SSH-2.0-OpenSSH_7.4p1 Raspbian-10+deb9u1
[2018/05/19 16:01:41.884945, 1] ssh_analyze_banner: We are talking to an OpenSSH client version: 7.4 (70400)
Connecton Result is: 0
Auth Result is: 0
[2018/05/19 16:01:42.258668, 1] ssh_packet_process: Couldn't do anything with packet type 80
Channel is open
Desktop
Documents
Downloads
Music
Pictures
Public
python_games
Templates
Videos
����s
Exiting ...
I just need to work on that last bit with the funny chars. This is straight out of my source code editor when I just got it to work, so the code isn't perfect.
ssh_channel_new allocated the resources for a new channel. It does not open it.
Depending on what you are trying to achieve you should then call an appropriate ssh_channel_open_XXXX function on that channel.
A simple example can be found here: https://github.com/substack/libssh/blob/c073979235eb0d0587ac9cb3c192e91e32d34b06/examples/exec.c
First ssh_channel_open_session is called to open a session (shell) channel, and then ssh_channel_request_exec is called to execute the lsof command.
How/when you will write to the channel depends on the type of channel you have opened. An example of writing to a session channel (after calling cat > /dev/null on the host to pipe written data to /dev/null) can be seen here: https://github.com/substack/libssh/blob/c073979235eb0d0587ac9cb3c192e91e32d34b06/examples/senddata.c
I created a program to read serial data from a COM port using C++, however due to changes in my project I have to read data from a BT port. Since Im using a bluetooth adapter to connect my computer to the device I expected the reading process to be the same but apparently it is not. Since Im using the Window OS to perform this task GetLastError() returns 2 which means the specified file is not found. However when I use Arduino's serial monitor the data is read just fine. Does anyone know how to read from a BT port in C++? Im using Windows 8 by the way, here is my code:
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
///-----------------------------Open port-----------------------------------------------------------------
// Name of port where device is found
LPCWSTR port = L"COM40";
// Open port for reading
HANDLE hComm = ::CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
// Check if port has been opened succesfully
if (hComm == INVALID_HANDLE_VALUE) std::cout << "Failed to open " << port << " error: " << GetLastError() << std::endl;
else std::cout << port << " has been opened succesfully\n";
///-----------------------------Configure port------------------------------------------------------------
// Create DCB structure
DCB dcb = { 0 };
// Get Comm state
if (!::GetCommState(hComm, &dcb)) std::cout << "Failed to get Comm state, error: " << GetLastError() << std::endl;
// Configure strcutre
dcb.DCBlength = sizeof(DCB);
// Set Baud rate
dcb.BaudRate = CBR_9600;
// Set number of bytes in bits that are recieved through the port
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
// Check if port has been configured correctly
if (!::SetCommState(hComm, &dcb)) std::cout << "\nFailed to set Comm State, error: " << GetLastError();
else std::cout << "Comm state has been set succesfully\n";
///-----------------------------Read data-------------------------------------------------------------------
char buffer;
DWORD maxBytes = 1;
if (!::ReadFile(hComm, &buffer, maxBytes, NULL, NULL)) std::cout << "\nFailed to read from " << port << " error: " << GetLastError() << std::endl;
else std::cout << "File has been read succesfully\n";
///-----------------------------Write to text file----------------------------------------------------------
std::fstream file;
int counter = 0;
// Writing to text file will be done later
while (ReadFile(hComm, &buffer, maxBytes, NULL, NULL))
{
std::cout << buffer;
}
///-----------------------------Close port------------------------------------------------------------------
CloseHandle(hComm);
file.close();
std::cout << "\nCOM40 has been closed!\n";
return 0;
}
I am trying to make RS-232 communication between the PC and the PC MCU PIC. So I started making the PC program first in C++, and it was errorless, and according to the cout I made to output the status it should be working, but I wanted to be sure. So I downloaded Hyperterminal and connected Tx to Rx pin in serial com port, but whenever I try to connect the hyperterminal it gives an error, saying access denied (error 5) when I try to run my C++ program. I don't understand where the problem really is. Here's the full code, if the problem was the code's, just to make sure:
main.c:
#include <windows.h>
#include <winbase.h>
#include <iostream>
PDWORD sent;
char buf;
int main(){
DCB serial;
HANDLE hserial = CreateFile("\\\\.\\COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
serial.DCBlength = sizeof(DCB);
serial.BaudRate = CBR_9600;
serial.fBinary = true;
serial.fParity = false;
serial.ByteSize = 8;
serial.Parity = NOPARITY;
serial.StopBits = ONESTOPBIT;
char result = BuildCommDCB("baud=9600 parity=N data=8 stop=1", &serial);
if(result != 0){
std::cout << "DCB Structure Successfully Created!" << std::endl;
}else{
std::cout << "DCB Structure Creation Failed!" << std::endl;
}
if(hserial != INVALID_HANDLE_VALUE){
std::cout << "COM Port Handle Successfully Created!" << std::endl;
}else{
std::cout << "COM Port Handle Creation Failed!" << std::endl;
std::cout << GetLastError() << std::endl;
}
char res = WriteFile(hserial, "0xFF", 1, sent, NULL);
if(res != 0){
std::cout << "Writing to COM Port Successfull!" << std::endl;
}else{
std::cout << "Writing to COM Port Failed!" << std::endl;
std::cout << GetLastError() << std::endl;
}
CloseHandle(&hserial);
return 0;
}
Only one program at a time can open a particular COM port. You can do your test if you have two COM ports available.