Difficulty communicating over serial ports in Linux - c++

I have success writing code in Windows and performing serial port communication. But not in Linux so far.
Here is the code I wrote:
I have used Picocom to verify that I can communicate over the serial ports via my (USB to NULL Modem to USB) cable.
Setting the code to None blocking yields "errno: 11 Resource temporarily unavailable" on both client and server."
When I set to Blocking, it hangs in code at the Read File method. If I comment that line out it runs... but not getting data.
Server sends packets continuous.
Client receives packets continuous.
Problem seems to be bytes aren't received at the client. They are sent, however at the server.
CLIENT:
RECV(1611912): NumChars: 0 String:
RECV(1611913): NumChars: 0 String:
RECV(1611918): NumChars: 0 String:
RECV(1611919): NumChars: 0 String:
RECV(1611920): NumChars: 0 String:
SERVER:
SENT(106775): NumChars: 10 String: 0123456789
SENT(106776): NumChars: 10 String: 0123456789
SENT(106777): NumChars: 10 String: 0123456789
SENT(106778): NumChars: 10 String: 0123456789
SENT(106779): NumChars: 10 String: 0123456789
to run:
g++ -o sp serialport.cpp
client: ./sp /dev/ttyS0 c
server: ./sp /dev/ttyS4 s
#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
class C_SerialPort
{
private:
int giFD;
char gpcDevice[100] = {0};
public:
//------------------------------------------------
//
//------------------------------------------------
int GetError(char* pcMessage = (char*)"")
{
char pcError[100] = {0};
sprintf(pcError, " (%s): errno: %d %s\n", pcMessage, errno, strerror(errno));
if(errno > 0)
{
printf("%s", pcError);
}
return errno;
}
//------------------------------------------------
//
//------------------------------------------------
int Connect()
{
return Connect((char*)"/dev/ttyS0");
//return Connect((char*)"/dev/ttyUSB0");
}
//------------------------------------------------
//
//------------------------------------------------
int Connect(char *pcDevice)
{
strcpy(gpcDevice, pcDevice);
struct termios s_TA;
// Open the serial port
giFD = open(gpcDevice, O_RDWR | O_NOCTTY | O_NDELAY | O_FSYNC );
if(giFD < 0)
{
printf("open_port: Unable to open %s\n%s", gpcDevice, strerror(errno));
printf("EXITING...\n");
return 1;
}
else
{
printf("Connect Device: %s\n", gpcDevice);
}
// get attributes
if(tcgetattr(giFD, &s_TA) != 0)
{
GetError((char*)"tcgetattr");
printf("EXITING...\n");
return 1;
}
// clear terminalAttributes data
//memset(&s_TA, 0, sizeof(struct termios));
if(0)
{
// 57600 bauds; 8 bits per word; Ignore modem control lines; Enable receiver.
s_TA.c_cflag = B57600 | CS8 | CLOCAL | CREAD;
// Ignore framing errors and parity errors.
s_TA.c_iflag = IGNPAR | ONLCR;
//Enable implementation-defined output processing.
s_TA.c_oflag = OPOST;
// min time; min bytes to read
s_TA.c_cc[VTIME] = 1;
s_TA.c_cc[VMIN] = 1;// none zero blocks
}
else
{
cfsetospeed(&s_TA, B9600);
cfsetispeed(&s_TA, B9600);
s_TA.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */
s_TA.c_cflag &= ~CSIZE;
s_TA.c_cflag |= CS8; /* 8-bit characters */
s_TA.c_cflag &= ~PARENB; /* no parity bit */
s_TA.c_cflag &= ~CSTOPB; /* only need 1 stop bit */
s_TA.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */
/* setup for non-canonical mode */
s_TA.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
s_TA.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
s_TA.c_oflag &= ~OPOST;
/* fetch bytes as they become available */
s_TA.c_cc[VMIN] = 1; // 0 1
s_TA.c_cc[VTIME] = 1; // 0 1
}
//int iVal = fcntl(giFD, F_SETFL, 0); // set blocking?
//printf("file status = 0x%x\n", iVal);
//GetError((char*)"fcntl");
// Set the port to our state
if (tcsetattr(giFD, TCSANOW, &s_TA) != 0)
{
GetError((char*)"tcsetattr");
printf("EXITING...\n");
return 1;
}
// flushes data written but not transmitted.
// flushes data received but not read.
tcflush(giFD, TCOFLUSH);
tcflush(giFD, TCIFLUSH);
printf("CONNECTION OK\n");
//return giFD;
return 0;
}
//------------------------------------------------
//
//------------------------------------------------
void Disconnect(void)
{
close(giFD);
printf("nPort 1 has been CLOSED and %d is the file descriptionn", giFD);
GetError((char*)"Disconnect");
}
//------------------------------------------------
//
//------------------------------------------------
int SendArray(unsigned char *buffer, int len)
{
int n = write(giFD, buffer, len);
// error catch
if(n < 0)
GetError((char*)"write");
return n;
}
//------------------------------------------------
//
//------------------------------------------------
int GetArray (unsigned char *buffer, int len)
{
int n = 0;
int len2 = BytesToRead();
n = read(giFD, buffer, len2); // this line is an issue? with settings?
// error catch
//if(n < 0)
// GetError((char*)"read");
return n;
}
//------------------------------------------------
//
//------------------------------------------------
void Clear()
{
tcflush(giFD, TCIFLUSH);
tcflush(giFD, TCOFLUSH);
}
//------------------------------------------------
//
//------------------------------------------------
int BytesToRead()
{
int iBytes = 0;
ioctl(giFD, FIONREAD, &iBytes);
//printf("Byte2Read: %d\n", iBytes);
// error catch
GetError((char*)"BytesToRead");
return iBytes;
}
};
//------------------------------------------------
//
//------------------------------------------------
int main(int argc, char const *argv[])
{
// device
char *pcDevice = (char*)argv[1];
printf("init:device:%s\n", pcDevice);
// connection type
char cConnType = argv[2][0];
printf("ConnectionType:%c\n", cConnType);
// instantiate SerialPort
C_SerialPort c_SP;
// connect
int iReturn = c_SP.Connect(pcDevice);
if(iReturn != 0)
{
printf("EXITING...\n");
return 1;
}
// clear buffer
c_SP.Clear();
printf("clear\n");
printf("prior...\n");
// main loop
while(1)
{
int iSleep_ms = 200;
usleep(iSleep_ms);
char pcArray[100] = {0};
int iNumChars = 0;
if(cConnType == 's')
{
static long lCount = 0;
// Send
strcpy(pcArray, "0123456789");
iNumChars = c_SP.SendArray((unsigned char*)pcArray, 10);
if(iNumChars > 0)
{
printf("SENT(%ld): NumChars: %d String: %s\n", lCount, iNumChars, pcArray);
}
lCount++;
}
if(cConnType == 'c')
{
static long lCount = 0;
// Receive
iNumChars = c_SP.GetArray((unsigned char*)pcArray, sizeof(pcArray));
if(iNumChars > 0)
{
printf("RECV(%ld): NumChars: %d String: %s\n", lCount, iNumChars, pcArray);
}
else
{
//printf("RECV: NumChars: %d String: %s\n", iNumChars, pcArray);
}
lCount++;
}
}
c_SP.Disconnect();
return 0;
}

You have four major bugs:
Your GetArray function ignores the return value of BytesToRead. It should read the lesser of the buffer size or the number of bytes available.
Your code has no ability to sanely handle the case where BytesToRead returns zero.
You ignore the return value of GetArray. When you print pcArray, you do not tell printf how many characters to output. So how is it supposed to know what to print?
You overwrite the returned values from tcgetattr by calling memset.

The issue is the serial port to communicate through.
The /dev/ttyS0 and /dev/ttyS4 are the serial ports after the USB in the NULL modem cable hook up. But to communicate I had to use /dev/ttyUSB0 and /dev/ttyUSB1

Related

Serial data sniffer not working as expected

I'm trying to get serial data from one port /dev/ttyUSB0 and pass it to the second one /dev/ttyUSB1 and vice versa. By my, apparently, flaunted logic the code below should work as expected. But the data seems not to reach the second port correctly, as I am not getting a correct response. I need my own program because I need to control the flow of data between the two serial devices.
#include <iostream>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
using namespace std;
int set_interface_attribs(int fd, int speed)
{
struct termios tty;
if (tcgetattr(fd, &tty) < 0) {
printf("Error from tcgetattr: %s\n", 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) {
printf("Error from tcsetattr: %s\n", strerror(errno));
return -1;
}
return 0;
}
void set_mincount(int fd, int mcount)
{
struct termios tty;
if (tcgetattr(fd, &tty) < 0) {
printf("Error tcgetattr: %s\n", strerror(errno));
return;
}
tty.c_cc[VMIN] = mcount ? 1 : 0;
tty.c_cc[VTIME] = 5; /* half second timer */
if (tcsetattr(fd, TCSANOW, &tty) < 0)
printf("Error tcsetattr: %s\n", strerror(errno));
}
void read_send(int port1, int port2)
{
unsigned char buf[1024];
int rdlen;
int wlen;
printf("Reading port 1\n");
rdlen = read(port1, buf, sizeof(buf) - 1);
if (rdlen > 0) {
unsigned char *p;
printf("Writing %d:\n", rdlen);
wlen = write (port2, buf, rdlen);
tcdrain(port2);
if (wlen != rdlen) {
printf("Error from write: %d, %s\n", wlen, strerror(errno));
}
} else if (rdlen < 0) {
printf("Error from read: %d: %s\n", rdlen, strerror(errno));
}
}
void connect_data(int port1, int port2)
{
//read 1 write on 2; read 2 write on 1
read_send(port1, port2);
read_send(port2, port1);
}
int main()
{
char *portname_cp = "/dev/ttyUSB0";
char *portname_rfid = "/dev/ttyUSB1";
int fd_cp;
int fd_rfid;
int wlen;
fd_rfid = open(portname_rfid, O_RDWR | O_NOCTTY | O_SYNC);
fd_cp = open(portname_cp, O_RDWR | O_NOCTTY | O_SYNC);
if (fd_rfid < 0) {
printf("Error opening %s: %s\n", portname_rfid, strerror(errno));
return -1;
}
if (fd_cp < 0) {
printf("Error opening %s: %s\n", portname_cp, strerror(errno));
return -1;
}
printf("Ports opened\n");
/*baudrate 115200, 8 bits, no parity, 1 stop bit */
set_interface_attribs(fd_rfid, B115200);
//set_mincount(fd_rfid, 0); /* set to pure timed read */
set_interface_attribs(fd_cp, B115200);
//set_mincount(fd_cp, 0); /* set to pure timed read */
do {
connect_data(fd_cp, fd_rfid);
} while(true);
return 0;
}

How to change this code to read all data from serial port in one part (not 2 part)?

This code is reading data from RFID module(EM-18) .I have a big problem here. When my application was running and I was passing RFID card from em module, It was reading data in 2 part. First read 8 byte's card ID then send 4 bytes. Like this:
[root#FriendlyARM /fgit]# ./RFIDMonitor -qws
enter the port name:
ttySAC3
open_port: succesfully open port
open_port: succesfully open port
RFID MONITORING => '010B7528'
RFID MONITORING => '297E'
RFID MONITORING => '010B7528'
RFID MONITORING => '297E'
I changed VMIN and VTime but the result did not change.
This is my code:
if(!fork())
{
while(1)
{
memset(buf2,'\0',MAXDATASIZE);
//------------------------------------------------
if ((numbytes = read(fd,buf2, MAXDATASIZE-1)) != -1)
{
buf2[numbytes] = '\0';
printf("RFID MONITORING => '%s'\n",buf2);
}
}
}
This is my config :
int openport(void)
{
cout<<"enter the port name:\n";
string portname="";
cin>>portname;
portname="/dev/"+portname;
fd=open(portname.c_str(),O_RDWR|O_NOCTTY|O_NDELAY);
if (fd==-1)
{
//printf("open_port: unable to open port \n");
return -1;
}
else
{
//printf("open_port: succesfully open port \n");
fcntl(fd,F_SETFL,0);
return 1;
}
}
//-------------------------------------
void closeport(void)
{
close(fd);
}
//-------------------------------------
void configport(void)
{
struct termios tty;
struct termios tty_old;
memset (&tty, 0, sizeof tty);
/* Error Handling */
if ( tcgetattr ( fd, &tty ) != 0 ) {
std::cout << "Error " << errno << " from tcgetattr: " << strerror(errno) << std::endl;
}
/* Save old tty parameters */
tty_old = tty;
/* 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 |= CS8;
tty.c_cflag &= ~CRTSCTS; // no flow control
tty.c_cc[VMIN] =1;// change to 0 and 5
tty.c_cc[VTIME] = 10;// change to 0 and 5
tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
/* Make raw */
cfmakeraw(&tty);
/* Flush Port, then applies attributes */
tcflush( fd, TCIFLUSH );
if ( tcsetattr ( fd, TCSANOW, &tty ) != 0) {
std::cout << "Error " << errno << " from tcsetattr" << std::endl;
}
}
I want to show like this (all data in one part)
RFID MONITORING => '010B7528297E
read only reads what is available to be read. If you have to read the whole the whole thing, keep reading until you have the whole thing.
while(1)
{
memset(buf2,'\0',MAXDATASIZE);
int bytesread = 0;
//------------------------------------------------
//Keep going until the whole message has been read
while (bytesread != MAXDATASIZE-1)
{
//read less on successive reads, but write further into buffer
if ((numbytes = read(fd,buf2[bytesread], MAXDATASIZE-1-bytesread)) == -1)
{
printf("Error in reading data");
// handle error. Probably reopen port and resynch with RFID
}
else
{
// keep track of where we are in accumulating
bytesread += numbytes;
}
}
buf2[bytesread] = '\0';
printf("RFID MONITORING => '%s'\n",buf2);
}
I solve the problem ( just append that with sleep 1 second)
int numbytes;
char buf2[MAXDATASIZE];
//*****************************
// SerialCodes
//*****************************]
fd=-1;
while(fd==-1)
{
int a=openport();
if(a==1)
{
pid_t pid;
if((pid=fork()))
{
qDebug()<<("%d",pid);
while(1)
{
//------------------------------------------------
if ((numbytes = read(fd,buf2, MAXDATASIZE-1)) == -1)
{
//qDebug()<<("Error in reading data");
}
else
{
buf2[numbytes] = '\0';
usleep(10000);
QString s1(buf2);
memset(buf2,'\0',MAXDATASIZE);
read(fd,buf2, MAXDATASIZE-1) ;
QString s2(buf2);
memset(buf2,'\0',MAXDATASIZE);
qDebug()<<("RFID MONITORING => '%s'\n",s1+s2);
kill(pid,SIGTERM);
break;
}
}
}
}
}

Serial port polling not working on Beaglebone Black

I simply cannot get the poll() function to respond to data being sent over UART1 / /dev/ttyO1. Code as follows, maybe someone can spot my silly mistake?
#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/poll.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
int openPort()
{
struct termios oldtio, newtio;
int fd = open("/dev/ttyO1",O_RDWR|O_NOCTTY|O_NONBLOCK|O_NDELAY);
if (fd == -1)
{
printf( "could not open tty" );
return -1;
}
if ( tcgetattr( fd, &oldtio ) == -1 )
{
printf( "error getting tcattr\n" );
close( fd );
return -1;
}
cfmakeraw( &newtio );
cfsetispeed( &newtio, B9600 );
cfsetospeed( &newtio, B9600 );
newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS8 | B9600;
newtio.c_cflag |= (CLOCAL | CREAD);
newtio.c_cflag &= ~(PARENB | PARODD);
newtio.c_cflag &= ~CRTSCTS;
newtio.c_cflag &= ~CSTOPB;
newtio.c_iflag = 0;//IGNPAR;
//newtio.c_iflag &= ~(IXON | IXOFF | IXANY);
newtio.c_lflag = 0;
newtio.c_oflag = 0;
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 1;
tcflush( fd, TCIOFLUSH );
if ( tcsetattr( fd, TCSANOW, &newtio ) == -1 )
{
close( fd );
printf( "error setting attrs\n" );
return -1;
}
return fd;
}
void selectLoop( int fd )
{
struct pollfd fds[1];
fds[0].fd = fd;
fds[0].events = POLLIN;
int rc = poll( fds, 1, 100000 );
if (rc < 0)
{
perror( "poll" );
}
else if (rc > 0)
{
char buffer[32] = {0};
int r = read( fd, buffer, sizeof(buffer) );
if (r == -1)
{
printf( "error: %s\n", strerror( errno ) );
}
else
{
printf( buffer );
}
}
else
{
printf( "No data\n" );
}
//close( fd );
sleep( 1 );
}
int main( int c, char ** v )
{
int fd = openPort();
if (fd >= 0)
{
while(1)
{
selectLoop(fd);
}
}
return 0;
}
I get the same result using select(). However if I attach a signal to "data received" then the signal fires, though this is a scenario I am trying to avoid as it plays havoc with Netbeans' debug environment.
FYI: board revision is B6, UART1 is connected by TX/RX only. The "screen" program successfully receives and sends characters from the UART, so I know that it fundamentally works.
Replace this with something sensible:
printf( buffer );
Perhaps:
for (int i = 0; i < r; ++i)
putchar(buffer[i]);
fflush(stdout);
This flushes and doesn't risk printing more characters than read if the buffer is full.

C++ code to send messages with GSM

I just connected my raspberry Pi with a SM5100b GSM. I would like to test it sending a simple message in my mobile. I can do it with emulators like cutecom and minicom (because I have raspbian linux version). But Is there any code in C++ which does this job? I do not use Arduino, only a SM5100B. I wrote this code until now and of course it does not work yet
#include <stdio.h> // standard input / output functions
#include <string.h> // string function definitions
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitionss
#include <time.h> // time calls
int open_port(void)
{
int fd; // file description for the serial port
fd = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY);
if(fd == -1) // if open is unsucessful
{
//perror("open_port: Unable to open /dev/ttyAMA0 - ");
printf("open_port: Unable to open /dev/ttyAMA0. \n");
}
else
{
fcntl(fd, F_SETFL, 0);
printf("port is open.\n");
}
return(fd);
} //open_port
int configure_port(int fd) // configure the port
{
struct termios port_settings; // structure to store the port settings in
cfsetispeed(&port_settings, B9600); // set baud rates
cfsetospeed(&port_settings, B9600);
port_settings.c_cflag &= ~PARENB; // set no parity, stop bits, data bits
port_settings.c_cflag &= ~CSTOPB;
port_settings.c_cflag &= ~CSIZE;
port_settings.c_cflag |= CS8;
tcsetattr(fd, TCSANOW, &port_settings); // apply the settings to the port
return(fd);
} //configure_port
int query_modem(int fd) // query modem with an AT command
{
char n;
fd_set rdfs;
struct timeval timeout;
// initialise the timeout structure
timeout.tv_sec = 10; // ten second timeout
timeout.tv_usec = 0;
unsigned char send_bytes[] = "AT+CMGF=1";
unsigned char send_bytes1[] = "AT+CMGS=\"603*****\"";
unsigned char send_bytes3[] = "TEST";
// puts(send_bytes);
write(fd, send_bytes, 13); //Send data
write(fd, send_bytes1, 13);
write(fd, send_bytes3, 13);
//printf("Wrote the bytes. \n");
// do the select
n = select(fd + 1, &rdfs, NULL, NULL, &timeout);
// check if an error has occured
if(n < 0)
{
perror("select failed\n");
}
else if (n == 0)
{
puts("Timeout!");
}
else
{
printf("\nBytes detected on the port!\n");
}
return 0;
} //query_modem
int main(void)
{
int fd = open_port();
configure_port(fd);
query_modem(fd);
return(0);
} //main
Open the relevant serial port (/dev/ttySx, where x is most likely a number), use write or fwrite to write to the port, close the port, exit program.

linux c++ serial port echoes output

In my program which sends bytes to a serial port, I receive bytes which I send. I don't want to receive bytes which I send, and I don't know how to do this?
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys/ioctl.h>
int fd;
struct termios tio, old_tio;
time_t SubTime_mSec(timeval val1, timeval val2)
{
timeval tv;
if (val1.tv_sec > val2.tv_sec) return (0);
if (val1.tv_sec == val2.tv_sec)
if (val1.tv_usec > val2.tv_usec) return (0);
tv.tv_sec = val2.tv_sec - val1.tv_sec;
if (val1.tv_usec < val2.tv_usec) {
tv.tv_usec = val2.tv_usec - val1.tv_usec;
} else {
tv.tv_sec --;
tv.tv_usec = 1000000 + val2.tv_usec - val1.tv_usec;
}
return(tv.tv_sec*1000 + tv.tv_usec/1000);
}
void RTUOutMessage(int cnt1, int cnt2)
{
unsigned char msg[13] = {0x01, 0x10, 0x00, 0x2F, 0x00, 0x02, 0x04, 0x4B, 0x64, 0x3D, 0xD9, 0x36, 0xC6};
int Len = 13;
int status, i, j;
ioctl(fd, TIOCMGET, &status);
status = status | TIOCM_RTS | TIOCM_DTR;
ioctl(fd, TIOCMSET, &status);
write(fd, msg, Len);
for (j = 0; j < cnt1; j ++)
for (i = 0; i < cnt2; i ++);
ioctl(fd, TIOCMGET, &status);
status &= ~TIOCM_RTS;
status &= ~TIOCM_DTR;
ioctl(fd, TIOCMSET, &status);
timeval start_t, curr_t;
char Buff[80];
int l;
gettimeofday(&start_t, NULL);
curr_t = start_t;
while (SubTime_mSec(start_t, curr_t) < 1000) {
l = read(fd, Buff, 80);
if (l > 0) {
printf("BUFFER=");
for(i = 0; i < l; i++) {
printf(" %x", Buff[i]);
}
//printf("\n");
}
gettimeofday(&curr_t, NULL);
}
}
void InitPort(void)
{
int StopBits = 2;
if ((fd = open("/dev/ttyAM2", O_RDWR | O_NDELAY)) < 0) {
printf("Couldn't open //dev//ttyAM2\n");
}
tcflush(fd, TCIOFLUSH);
int n = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, n & ~O_NDELAY);
tcgetattr(fd, &old_tio);
tcgetattr(fd, &tio);
cfsetospeed(&tio, (speed_t)B9600);
cfsetispeed(&tio, (speed_t)B9600);
tio.c_cflag = (tio.c_cflag & ~CSIZE) | CS8;
tio.c_cflag |= CLOCAL | CREAD ;
tio.c_cflag &= ~OFILL;
//parity
tio.c_cflag &= ~(PARENB | PARODD);
tio.c_cflag &= ~CRTSCTS;
if (StopBits == 2) tio.c_cflag |= CSTOPB;
else tio.c_cflag &= ~CSTOPB;
tio.c_iflag=IGNBRK;
tio.c_iflag &= ~(IXON|IXOFF|IXANY);
tio.c_lflag=0;
tio.c_oflag=0;
tio.c_cc[VTIME]=0;
tio.c_cc[VMIN]=0;
if (tcsetattr(fd, TCSANOW, &tio)!=0) printf("tcsetattr() 1 failed\n");
int mcs=0;
ioctl(fd, TIOCMGET, &mcs);
mcs |= TIOCM_RTS;
ioctl(fd, TIOCMSET, &mcs);
if (tcgetattr(fd, &tio)!=0) printf("tcgetattr() 4 failed\n");
tio.c_cflag &= ~CRTSCTS;
if (tcsetattr(fd, TCSANOW, &tio)!=0) printf("tcsetattr() 2 failed\n");
}
int main(int argc, char **argv)
{
InitPort();
int cnt1, cnt2;
cnt1 = 3;
cnt2 = 20000;
cnt1 = atoi(argv[1]);
cnt2 = atoi(argv[2]);
for(;;) {
RTUOutMessage(cnt1, cnt2);
usleep(1000000);
}
tcsetattr(fd, TCSANOW, &old_tio);
close(fd);
printf("End\n");
return 0;
}
If you are receiving the chars that you sent, then the remote's serial port is apparently echoing its input.
You will either have to disable input echo at the other device, or perform "echo cancellation" in your receive logic. I.E. create an "echo FIFO". Each byte output to the serial port is also written to the "echo FIFO". Set a flag indicating that an echo is expected. As input is received, compare it to the "echo FIFO", and remove chars when it matches, and toss the receive char. If no match, then accept receive char. Clear the echo flag when the "echo FIFO" is empty.
BTW the code appears to set the serial port to raw or non-canonical mode. The preferred method would be to use
cfmakeraw(&tio);
rather than
tio.c_iflag=IGNBRK;
tio.c_iflag &= ~(IXON|IXOFF|IXANY);
tio.c_lflag=0;
tio.c_oflag=0;