Serial IO with posix and write to shared memory - c++

I got a problem with a posix signal, that I use for reading serial data. First here is a small example code how I initialize my serial port, my signal and a shared memory.
#include <unistd.h>
#include <termios.h>
#include <sys/signal.h>
#include <stdint.h>
#include <cassert>
#include <cstdio>
#include <fcntl.h>
#include <iostream>
#include <QSharedMemory>
int fd;
struct termios termAttr;
struct sigaction saio;
char buff[255];
QSharedMemory QShare("IDSTRINGOFTHISMEMORY");
void signal_handler_IO (int status)
{
std::cout << "Got Serial Data!" << std::endl;
int si = read(fd, &buff[0], 255);
if(true) // Works with false here, but then the shared memory ist not used!
{
char TWrite = 't';
QShare.lock();
char *to = (char*)QShare.data();
const char *from = reinterpret_cast<char*>(&TWrite);
memcpy(to, from, 1);
QShare.unlock();
}
}
int main()
{
// Create SharedMemory:
QShare.create(1);
fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
return -1;
}
saio.sa_handler = signal_handler_IO;
saio.sa_flags = 0;
saio.sa_restorer = NULL;
sigemptyset(&saio.sa_mask);
sigaddset(&saio.sa_mask, SIGINT);
sigaction(SIGIO,&saio,NULL);
fcntl(fd, F_SETFL, FNDELAY|FASYNC);
fcntl(fd, F_SETOWN, getpid());
tcgetattr(fd,&termAttr);
cfsetospeed(&termAttr,B57600);
cfsetispeed(&termAttr,B57600);
termAttr.c_cflag &= ~PARENB;
termAttr.c_cflag &= ~CSTOPB;
termAttr.c_cflag &= ~CSIZE;
termAttr.c_cflag |= CS8;
termAttr.c_cflag |= (CLOCAL | CREAD);
termAttr.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
termAttr.c_iflag &= ~(IXON | IXOFF | IXANY);
termAttr.c_oflag &= ~OPOST;
termAttr.c_cc[VMIN] = 5;
tcsetattr(fd,TCSANOW,&termAttr);
while(true)
{
usleep(1000000);
}
return 0;
}
I had this code in use for a while and it did work quite well. Now for a different project I want to store the serial data in shared memory block, so I can read the current datapoint from multiple processes. In the signal_handler_IO I try to write the data to a shared memory that is created by sys/shm.h. The moment I started using shared memory the posix signal stopped working. Since I was unsure about the use of the shared memory I also tried to use the QSharedMemory class from qt, which created the same result.
Can you tell me, what the shared memory does to my posix signal?

Related

Why does this serial/modem code mess up my terminal display?

I have written some code to find any modems on a unix system using the regex /dev/tty* basically and then for any matches see if can open the port and if so send an AT command and check if the response message contains the characters 'OK'.
The code does find a modem but unfortunately it messes up the terminal display. See below. I notice that it also prints the AT command - see output below. Why is my terminal display altered and how can I fix that?
After running the program, if you enter a command and enter, eg ls, the command is not shown but when you press enter you do see the output.
Here is the code:
#include <iostream>
#include <string>
#include <unordered_map>
#include <iomanip>
#include <memory>
#include <sstream>
#include <thread>
#include <iostream>
#include <filesystem>
#include <regex>
#include <unistd.h> // close
#include <fcntl.h> // open, O_RDWR, etc
#include <termios.h>
#include <string.h>
#include <sys/select.h> // timeouts for read
#include <sys/timeb.h> // measure time taken
int set_interface_attribs(int fd, int speed)
{
struct termios tty;
if (tcgetattr(fd, &tty) < 0) {
// Error from tcgetattr - can use strerror(errno)
return -1;
}
cfsetospeed(&tty, (speed_t)speed);
cfsetispeed(&tty, (speed_t)speed);
tty.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8; /* 8-bit characters */
tty.c_cflag &= ~PARENB; /* no parity bit */
tty.c_cflag &= ~CSTOPB; /* only need 1 stop bit */
tty.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */
/* setup for non-canonical mode */
tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
tty.c_oflag &= ~OPOST;
/* fetch bytes as they become available */
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 1;
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
// Error from tcsetattr- use strerror(errno)
return -1;
}
return 0;
}
long enumerate_ports(std::unordered_map <std::string, std::string>& ports) {
// ls /dev | grep ^tty.*
const std::regex my_filter( "^tty.*" );
std::string path = "/dev/";
for (const auto & entry : std::filesystem::directory_iterator(path)) {
std::smatch sm;
std::string tmp = entry.path().filename().string();
// if we have a regex match attempt to open port and send AT command
if (std::regex_match(tmp, sm, my_filter)) {
std::string portname = entry.path().string();
int fd = ::open(portname.c_str(), O_RDWR | O_NOCTTY);
if (fd < 0) {
// Error opening port
continue;
} else {
// port was opened successfully
// try to write AT command and do we get an OK response
// baudrate 9600, 8 bits, no parity, 1 stop bit
if(set_interface_attribs(fd, B9600) != 0) {
::close(fd);
continue;
}
int wlen = ::write(fd, "AT\r\n", 4);
if (wlen != 4) {
// Error from write
::close(fd);
continue;
}
// tcdrain() waits until all output written to the object referred
// to by fd has been transmitted.
tcdrain(fd);
fd_set set;
struct timeval timeout;
FD_ZERO(&set); /* clear the set */
FD_SET(fd, &set); /* add our file descriptor to the set */
timeout.tv_sec = 0;
timeout.tv_usec = 100000; // 100 milliseconds
// wait for data to be read or timeout
int rv = select(fd + 1, &set, NULL, NULL, &timeout);
if(rv > 0) { // no timeout or error
unsigned char buf[80];
const int bytes_read = ::read(fd, buf, sizeof(buf) - 1);
if (bytes_read > 0) {
buf[bytes_read] = 0;
unsigned char* p = buf;
// scan for "OK"
for (int i = 0; i < bytes_read; ++i) {
if (*p == 'O' && i < bytes_read - 1 && *(p+1) == 'K') {
// we have a positive response from device so add to ports
ports[portname] = "";
break;
}
p++;
}
}
}
::close(fd);
}
}
}
return ports.size();
}
int main() {
struct timeb start, end;
int diff;
ftime(&start);
// get list of ports available on system
std::unordered_map <std::string, std::string> ports;
long result = enumerate_ports(ports);
std::cout << "No. found modems: " << result << std::endl;
for (const auto& item : ports) {
std::cout << item.first << "->" << item.second << std::endl;
}
ftime(&end);
diff = (int) (1000.0 * (end.time - start.time)
+ (end.millitm - start.millitm));
printf("Operation took %u milliseconds\n", diff);
}
And the output:
acomber#mail:~/Documents/projects/modem/serial/gdbplay$ ls
main.cpp main.o Makefile serial
acomber#mail:~/Documents/projects/modem/serial/gdbplay$ make serial
g++ -Wall -Werror -ggdb3 -std=c++17 -pedantic -c main.cpp
g++ -o serial -Wall -Werror -ggdb3 -std=c++17 -pedantic main.o -L/usr/lib -lstdc++fs
acomber#mail:~/Documents/projects/modem/serial/gdbplay$ sudo ./serial
[sudo] password for acomber:
AT
No. found modems: 1
/dev/ttyACM0->
Operation took 8643 milliseconds
acomber#mail:~/Documents/projects/modem/serial/gdbplay$
Why does this serial/modem code mess up my terminal display?
A precise answer requires you to post the terminal's settings prior to executing your code, i.e. stty -a.
The code does find a modem but unfortunately it messes up the terminal display.
The simplest (i.e. straightforward) workaround/solution is to adhere to the old (but rarely followed) advice of saving and then restoring the terminal's termios settings, as in this example.
The simple changes needed in your code would be something like (please overlook mixing of C and C++; I only know C) the following patch.
struct termios savetty;
int set_interface_attribs(int fd, int speed)
{
+ struct termios tty;
if (tcgetattr(fd, &tty) < 0) {
// Error from tcgetattr - can use strerror(errno)
return -1;
}
+ savetty = tty; /* preserve original settings for restoration */
cfsetospeed(&tty, (speed_t)speed);
cfsetispeed(&tty, (speed_t)speed);
Then in enumerate_ports(), the last two instances of ::close(fd); need to be replaced with the sequence that will perform the restoration:
+ if (tcsetattr(fd, &savetty) < 0) {
+ // report cannot restore attributes
+ }
::close(fd);
After running the program, if you enter a command and enter, eg ls, the command is not shown ...
That is obviously the result of leaving the ECHO attribute cleared.
The "missing" carriage returns are probably due to a cleared OPOST.
Other salient attributes that were cleared by your program but probably are expected to be set by the shell are ICANON, ICRNL, and IEXTEN.
But rather than try to determine what exactly needs to be undone, the proper and guaranteed fix is to simply restore the termios settings back to its original state.
An alternative (lazy) approach would to use the stty sane command after you execute your program.

Linux C++ Serial Programming Not Working Why?

#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>
#include <cerrno>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fstream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <cstdlib>
#include <ctime>
using namespace std;
typedef struct termios ComSet;
int main()
{
int acm=-1;
acm=open("/dev/ttyACM0",O_RDWR | O_NOCTTY);
if(acm == -1)
{
cout<<"Error Opening ttyACM0"<<endl;
exit(1);
}
else
{
cout<<"Preparing ttyACM0..."<<endl;
ComSet SerialSettings;
tcgetattr(acm, &SerialSettings);
cfsetispeed(&SerialSettings,B115200);
cfsetospeed(&SerialSettings,B115200);
/* 8N1 Mode */
SerialSettings.c_cflag &= ~PARENB;
SerialSettings.c_cflag &= ~CSTOPB;
SerialSettings.c_cflag &= ~CSIZE;
SerialSettings.c_cflag |= CS8;
SerialSettings.c_cflag &= ~CRTSCTS;
SerialSettings.c_cflag |= CREAD | CLOCAL;
SerialSettings.c_iflag &= ~(IXON | IXOFF | IXANY);
SerialSettings.c_iflag &=ICANON;
SerialSettings.c_iflag &= ~(ECHO | ECHOE | ISIG);
SerialSettings.c_oflag &= ~OPOST;
/* Setting Time outs */
SerialSettings.c_cc[VMIN] = 1;
SerialSettings.c_cc[VTIME] = 0;
if((tcsetattr(acm,TCSANOW,&SerialSettings)) != 0)
{
cout<< " ERROR ! in Setting attributes"<<endl;
}
else
{
cout<< "=======ttyACM0 Setting====="<<endl;
cout<<"BaudRate = 115200 StopBits = 1 Parity = none"<<endl;
cout<<"Reading ttyACM0... "<<endl;
char read_buffer[1024];
bzero(read_buffer,1024);
int read_bytes=0;
while(1)
{
write(acm,"Hello World !",13);
read_bytes=read(acm,&read_buffer,1024);
if(read_bytes>0)
{
cout<<read_buffer;
bzero(read_buffer,1024);
}
else
{
cout<<"No-Data"<<endl;
}
tcflush(acm, TCOFLUSH);
tcflush(acm, TCIFLUSH);
}
}
close(acm); /* Close the serial port */
}
return 0;
}
Why is this code not working ? i m trying to receive same message from the arduino but it will not work.it completely ignores write.i have also found that it works if i use cin.get() before write.
it works if i want to read from arduino only.
Here is my arduino code
String Input;
boolean done=false;
void setup()
{
Serial.begin(115200);
}
void loop()
{
Serial.println(GetSerial());
Input="";
}
String GetSerial()
{
done=false;
Input="";
while(!done)
{
while(Serial.available()>0)
{
Input=Serial.readStringUntil('\n'); //Block Reading
done=true;
}
}
return Input;
}
i want to receive whatever is sent on serial port as it is with as much less delay as possible

Wrong data transmission in serial communication between Arduino and Raspberry

I'm trying to sendo datas from Arduino Uno to RaspberryPi 3B. I need to send 14 int (max value: 6000) from Arduino as soon as Raspberry ask for them. Each one of this 14 number came from ad ADC (SPI communication).
ARDUINO SIDE
#include "SPI.h"
byte incomingByte = 0; // for incoming serial data
const int N_SENSORI=14;
const int DATAOUT = 11;
const int DATAIN = 12;
const int SPICLOCK = 13;
const int SLAVESELECT = 10;
//===============SPI COMMUNICATION================
short write_read_spi16(short what) {
digitalWrite(SS, LOW);
short res = SPI.transfer16(what);
digitalWrite(SS, HIGH);
return res;
}
//===============CONVERT INT IN BYTE AND SEND IT================
void longInt2Byte( int x){
unsigned char buf[sizeof( int)];
memcpy(buf,&x,sizeof(int));
Serial.write(buf,sizeof(buf));
}
//=======================================
void setup() {
Serial.begin(115200);
SPI.begin();
pinMode(DATAOUT, OUTPUT);
pinMode(DATAIN, INPUT);
pinMode(SPICLOCK,OUTPUT);
pinMode(SLAVESELECT,OUTPUT);
}
void loop() {
if (Serial.available() > 0) {
incomingByte= Serial.read();
if (incomingByte=='E') {
write_read_spi16(0b1000001101110000); //THIS IS FOR THE ADC COMMUNICATION
for (int i = 1; i<N_SENSORI+1; i++) { //DONE 14 TIMES.
short s = write_read_spi16(0b1000001101110000 | (i<<10));
int Data = s&0xFFF;
longInt2Byte(Data);
}
}
}}
// C++ SIDE
void stimulationController::SetupDario(){
cout<<"Dentro al setupDario"<<endl<<flush;
buffer=new char [1000];
const char* _portNameSensorsDario="/dev/ttyACM1";
//SERIAL PORT FOR HAND SENSORS
struct termios options;
SerialHandleSensors=open(_portNameSensorsDario, O_RDWR | O_NOCTTY | O_NDELAY); //SerialHandleSensors=open(_portNameSensors, O_RDWR | O_NOCTTY | O_NDELAY); non blocking
if (SerialHandleSensors == -1 )
{
cout<<endl<<"......ERROR: Unable to open: "<<_portNameSensorsDario<<endl;
return;
}
else
{
fcntl(SerialHandleSensors, F_SETFL,0);
cout<<"......OPENED PORT: Succesfully opened: "<<_portNameSensorsDario<<endl;
}
//GET THE OPTIONS, MODIFY AND SET
tcgetattr(SerialHandleSensors,&options);
cfsetispeed(&options,B115200); //BAUD RATE IN
cfsetospeed(&options,B115200); //BAUD RATE OUT
// options.c_lflag |= (ICANON | ECHO | ECHOE);
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~PARENB;
options.c_cflag |= CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
tcsetattr(SerialHandleSensors,TCSANOW,&options);
usleep(3000000);
cout<<"Fine Setup"<<endl<<flush;
}
int stimulationController::Dario( )
{
{
cout<<" NUOVA FUNZIONE"<<endl;
unsigned char bytes[4];
bytes[0]=0x45; // 'E'
int tempWrite=write(SerialHandleSensors,bytes,1);
if(tempWrite==-1)
{
cout<<"......ERROR: PROBLEM WRITING TO ROBOTIC HAND"<<endl;
failure=true;
return 0;
}
int value=0;
int tempRead=read(SerialHandleSensors,buffer,28);
if(tempRead==-1)
{
cout<<"......ERROR: PROBLEM READING FROM ROBOTIC HAND"<<endl;
failure=true;
return 0;
}
int j=0;
for( int i=0; i<28; i=i+2){
value= buffer[i] | ((int)buffer[i+1]<<8);
//ensorDataFoot.push_back(value); //Aggiunge un elemento
j=j+1;
cout<<"Dato "<<j <<"vale: "<<value<<endl<<flush;
}
return value;
}
}
The problem is that or the raspberry side some time it prints the right values, some time (the most of the times, actually) it doesn't. Data seems to be repeated or (2500 insted of 2000 for example).
I can't figure it out the problem.Could it be a matter of timing between the request of sending data and the reading? if so, there is a way to get rid of it?
I've added a do-while cycle in order to be sure that all the 28 bytes are read
int TotByte=28;
int ByteRead=0;
int TempRead=0;
do{ TempRead= read(SerialHandleSensors, buffer, (TotByte-ReadByte));
ReadByte= ReadByte+TempRead;
cout<<"ReadByte is: "<<ReadByte<<endl<<flush;
}while(ByteRead<TotByte);
Output:
ReadByte is: 5
ReadByte is: 15
ReadByte is: 25
and then it stay like that without doing anything
(Posted answer on behalf of the OP):
I figured it out; the problem were the settings of the serial port. For future reference, here is the working version.
bufferTemp=new char [1000];
bufferDEF = new char[1000];
const char* _portNameSensorsBT="/dev/rfcomm0";
struct termios options;
SerialHandleSensorsFoot=open(_portNameSensorsBT, O_RDWR ); //SerialHandleSensors=open(_portNameSensors, O_RDWR | O_NOCTTY | O_NDELAY); non blocking
if (SerialHandleSensorsFoot == -1 )
{
cout<<endl<<"......ERROR: Unable to open: "<<_portNameSensorsBT<<endl;
return 0;
}
else
{
fcntl(SerialHandleSensorsFoot, F_SETFL,0);
cout<<"......OPENED PORT: Succesfully opened: "<<_portNameSensorsBT<<endl;
}
//GET THE OPTIONS, MODIFY AND SET
tcgetattr(SerialHandleSensorsFoot,&options);
cfsetispeed(&options,B115200); //BAUD RATE IN
cfsetospeed(&options,B115200); //BAUD RATE OUT
// options.c_lflag |= (ICANON | ECHO | ECHOE);
options.c_iflag = IGNBRK | IGNPAR;
options.c_oflag = 0;
options.c_lflag = 0;
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~PARENB;
options.c_cflag |= CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
tcsetattr(SerialHandleSensorsFoot,TCSAFLUSH,&options);
usleep(5000000);
with these setting I'm able to communicate with bluetooth even though there might be some velocity problem.

Serial port in c++ , Unix

I wrote a code to connect, throught a serial port, mi computer to arduino.
This is arduino's code:
#include <Servo.h>
Servo servo;
const int pinServo = 2;
unsigned int angle;
void setup()
{
Serial.begin(9600);
servo.attach(pinServo);
servo.write(0);
}
void loop()
{
if(Serial.available()>0)
{
angle = Serial.read();
if(angle <= 179)
{
servo.write(angle);
}
}
}
And this is c++'s:
#include <iostream>
#include <unistd.h>
#include <fstream>
#include <termios.h>
using namespace std;
int main()
{
unsigned int angle;
ofstream arduino;
struct termios ttable;
cout<<"\n\ntest1\n\n";
arduino.open("/dev/tty.usbmodem3a21");
cout<<"\n\ntest2\n\n";
if(!arduino)
{
cout<<"\n\nERR: could not open port\n\n";
}
else
{
if(tcgetattr(arduino,&ttable)<0)
{
cout<<"\n\nERR: could not get terminal options\n\n";
}
else
{
ttable.c_cflag &= ~PARENB;
ttable.c_cflag &= ~CSTOPB;
ttable.c_cflag &= ~CSIZE;
ttable.c_cflag |= CS8;
ttable.c_cflag &= ~CRTSCTS;
ttable.c_cflag |= CREAD | CLOCAL;
ttable.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
ttable.c_oflag &= ~OPOST;
ttable.c_cc[VMIN] = 0;
ttable.c_cc[VTIME] = 0;
cfsetospeed(&ttable,9600);
if(tcsetattr(arduino,TCSANOW,&ttable)<0)
{
cout<<"\n\nERR: could not set new terminal options\n\n";
}
else
{
do
{
cout<<"\n\ninsert a number between 0 and 179";
cin>>angle;
arduino<<angle;
}while(angle<=179);
arduino.close();
}
}
}
}
It should connect to arduino , then ask me a number between 0 an 179 and the send that number to arduino which aplly that number as an angle to a servo motor;
But it stops at arduino.open("/dev/tty.usbmodem3a21") .What can i do ?
I think your problems appear in these lines of code
if(tcgetattr(arduino,&ttable)<0) {
// ...
}
else {
// ...
if(tcsetattr(arduino,TCSANOW,&ttable)<0) {
// ...
}
}
The arduino variable is of type ofstream, where tcgetattr() and tcsetattr() expect a file descriptor obtained with open() at this point.
ofstream provides an automatic conversion to bool and thus int implicitely. Supposed the
arduino.open("/dev/tty.usbmodem3a21");
went OK, you are effectively passing 1 to tcgetattr() and tcsetattr(), which is the standard input file descriptor.
Solution is not to use a ofstream for arduino, but an ordinary file descriptor
int arduino = open("/dev/tty.usbmodem3a21",O_WRONLY);

How can I set and clear the RTS line of a serial port. C++ POSIX

I want to control the RTS line on the serial port to wake up a device. Here is some rough test code to open the serial port. I need to set the RTS line low for 500ms. I'm having trouble googleing/understanding how to control the lines. Any Hints?
EDIT: OR controlling the CTS/DTR, any other line besides the Tx/Rx lines to connect to a pin of the robot.
#include <iostream>
#include <string.h>
#include <cstdio>
#include <fstream>
#include <sys/types.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <stdint.h> /* Standard types */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <sys/ioctl.h>
#include <getopt.h>
using namespace std;
int fd_global;
FILE* fp_global;
int serialport_init(const char* serialport, int baud);
int serialport_read_until(int fd);
int fpeek(FILE* stream);
bool fexists(const char *filename);
void* screen_thread(void* arg) {
while(1) {
}
}
int main(void) {
pthread_t screen_thread_id;
int flags;
int baudrate = B9600; // default
fd_global = serialport_init((char*)"/dev/ttyUSB0", baudrate);
if(fd_global==-1) {
cout << "Open port: error\n";
return -1;
}
fp_global = fdopen(fd_global, "r");
if (-1 == (flags = fcntl(fd_global, F_GETFL, 0))) flags = 0;
fcntl(fd_global, F_SETFL, flags | O_NONBLOCK);
//pthread_create(&screen_thread_id, NULL, screen_thread, (void*)NULL);
serialport_read_until(fd_global);
return 0;
}
int serialport_read_until(int fd)
{
char b[1];
while(1) {
int n = read(fd, b, 1); //Read byte at a time
if(n==-1) {
printf("N");fflush(stdout);
perror("READ: ");
}
else if( n==0 ) {
printf("Z");fflush(stdout);
} else if(n>0) {
printf(":%d:",n);fflush(stdout);
}
usleep(100*1000);
if (fexists("/dev/ttyUSB0"))
printf("CONNECTED\n");
else
printf("NOT CONNECTED\n");
}
return 0;
}
bool fexists(const char *filename)
{
ifstream ifile(filename);
return ifile;
}
int serialport_init(const char* serialport, int baud)
{
struct termios toptions;
int fd;
// Open port
fd = open(serialport, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
perror("init_serialport: Unable to open port ");
return -1;
}
// Read current termios settings
if (tcgetattr(fd, &toptions) < 0) {
perror("init_serialport: Couldn't get term attributes");
return -1;
}
// Set baud rate variable
speed_t brate = baud;
switch(baud) {
case 2400: brate=B2400; break;
case 4800: brate=B4800; break;
case 9600: brate=B9600; break;
#ifdef B14400
case 14400: brate=B14400; break;
#endif
case 19200: brate=B19200; break;
#ifdef B28800
case 28800: brate=B28800; break;
#endif
case 38400: brate=B38400; break;
case 57600: brate=B57600; break;
case 115200: brate=B115200; break;
}
cfsetispeed(&toptions, brate);
cfsetospeed(&toptions, brate);
// Setup termios for 8N1
toptions.c_cflag &= ~PARENB;
toptions.c_cflag &= ~CSTOPB;
toptions.c_cflag &= ~CSIZE;
toptions.c_cflag |= CS8;
// Reccomended settings
toptions.c_cflag &= ~CRTSCTS; // no flow control
toptions.c_cflag |= CREAD | CLOCAL; // turn on read & ignore ctrl lines
toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
toptions.c_oflag &= ~OPOST; // make raw
// Setting when read() releases
// see: http://unixwiz.net/techtips/termios-vmin-vtime.html (Still a little confusing)
toptions.c_cc[VMIN] = 0;
toptions.c_cc[VTIME] = 20;
// Apply settings
if( tcsetattr(fd, TCSANOW, &toptions) < 0) {
perror("init_serialport: Couldn't set term attributes");
return -1;
}
return fd;
}
Would this work? I'll test it tomorrow.
int status;
status |= TIOCM_RTS;
ioctl(fd, TIOCMSET, &status);
usleep(500*1000);
status &= ~TIOCM_RTS;
ioctl(fd, TIOCMSET, &status);