Serial Communication read() Error - c

This should be fairly straightforward for someone in the know, but I have been struggling for a bit and would appreciate some thoughts. I am writing an application that reads from a serial comm port.
My Setup:
I have a windows machine with putty open and connected to my comm port of interest.
I have a linux (ubuntu) machine in which I am writing this software (in C).
I am typing into putty on the windows machine and trying to read it with my application on the linux machine.
What I have:
So far, using the code below I can successfully write to the putty display on the windows machine from my application on the linux computer, but I cannot read the buffer on my linux machine when I type on the windows machine.
Code:
#include <stdio.h> // standard input / output functions
#include <stdlib.h>
#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>
int openport()
{
int USB = open( "/dev/ttyUSB0", O_RDWR| O_NOCTTY | O_NONBLOCK );
struct termios tty;
struct termios tty_old;
memset(&tty, 0, sizeof tty);
/* Error Handling */
if ( tcgetattr( USB, &tty ) != 0 )
{
printf("Error 1, or something");
}
/* 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; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
/* Make raw */
cfmakeraw(&tty);
/* Flush Port, then applies attributes */
tcflush( USB, TCIFLUSH );
if ( tcsetattr ( USB, TCSANOW, &tty ) != 0)
{
printf("Error, or something");
}
return USB;
}
int main()
{
int n = 0;
int j = 0;
unsigned char buf[10] = {0,0,0,0,0,0,0,0,0,0};
printf("Hello world!\n");
int USB = openport();
unsigned char cmd[] = "INIT Hey SHanahas \r";
int n_written = 0;
do
{
n_written += write( USB, &cmd[n_written], 1 );
}
while (cmd[n_written-1] != '\r' && n_written > 0);
printf("Here\n\n");
do
{
n = read( USB, &buf, 1 );
printf("%s \n",buf);
printf("%d",n);
}
while( buf != '\r' && n > 0);
printf("Herr2");
return 0;
}
Does anyone have any thoughts on what might be happening? the read() command returns a -1 error.
Thanks!

Related

Linux UART transmitting Problems

I'm trying to communicate with an external IC via UART/tty in C. I'm using a nanoPI neo2 (allwinner h5) and friendlyARM's own Linux OS (which is a modified Ubuntu core).
I'v tried to get it working, but the TX output of the pi is ?logical inverted?. You can see what I mean in the oscilloscope pictures. There you can see if I select the "Polarity Invert"- Mode the data is ok, but in normal mode it isn't working.
In the past, I got around that by setting the invert Bit of the MCU (e.g. PIC MCU), but the IC I'm using now doesn't support this feature.
http://wiki.friendlyarm.com/wiki/index.php/NanoPi_NEO2
oscilloscope picture 1
oscilloscope picture 2
c source
#include <stdio.h>
//#include <errno.h>
//#include <termios.h>
//#include <unistd.h>
#include <string.h>
#include <fcntl.h> /* File Control Definitions */
#include <termios.h>/* POSIX Terminal Control Definitions*/
#include <unistd.h> /* UNIX Standard Definitions */
#include <errno.h> /* ERROR Number Definitions */
#include <unistd.h>
#include <sys/types.h>
#include <sys/signal.h>
/* source : http://stackoverflow.com/a/6947758 */
int fd;
int set_interface_attribs (int fd, int speed, int parity) {
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0) {
perror ("error from tcgetattr");
return -1;
}
cfsetospeed (&tty, speed);
cfsetispeed (&tty, speed);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
// disable IGNBRK for mismatched speed tests; otherwise receive break
// as \000 chars
tty.c_iflag &= ~IGNBRK; // disable break processing
tty.c_lflag = 0; // no signaling chars, no echo,
// no canonical processing
tty.c_oflag = 0; // no remapping, no delays
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
// enable reading
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
tty.c_cflag |= parity;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
if (tcsetattr (fd, TCSANOW, &tty) != 0) {
perror ("error from tcsetattr");
return -1;
}
return 0;
}
void set_blocking (int fd, int should_block) {
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
perror ("error from tggetattr");
return;
}
tty.c_cc[VMIN] = should_block ? 1 : 0;
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
if (tcsetattr (fd, TCSANOW, &tty) != 0)
perror ("error setting term attributes");
}
int main()
{
char *portname = "/dev/ttyS0";
int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0)
{
//perror ("error %d opening %s: %s", errno, portname, strerror (errno));
return;
}
set_interface_attribs (fd, B115200, 0); // set speed to 115,200 bps, 8n1 (no parity)
set_blocking (fd, 0); // set no blocking
write (fd, "hello!\n", 7); // send 7 character greeting
usleep ((7 + 25) * 100); // sleep enough to transmit the 7 plus
// receive 25: approx 100 uS per char transmit
char buf [100];
int n = read (fd, buf, sizeof buf); // read up to 100 characters if ready to read
}
Thanks in advance
Axel
The picture on the scope looks fine - it is an UART signal. The problem here is not programming-related, but failure to understand the difference between UART and RS-232.
You have picked RS-232 encoding on your scope, and RS-232 uses a different, inverted polarity compared to UART.
UART idles high voltage=Vdd, RS-232 idles at negative voltage < -3V.
On UART, a high voltage=Vdd bit means 1 and low voltage=0V means 0.
On RS-232, a high voltage > +3V bit means 0, and negative voltage < -3V means 1.
So when you try to decode a UART signal with RS-232 encoding, it works when you inverse the polarity. Apparently Rigol isn't picky about the actual voltage levels, since it doesn't understand that the signal is not RS-232 at all.

read from serial port fails when called twice

Resolved Bellow: Wrong number of characters in read/write
I am attempting to read and write to a serial port, and I don't have much experience in C/C++.
My port is connected to a motion controller/driver that requires the following settings:
Baudrate: 57600
Data bits: 8
Parity: None
Stop bits: 1
Flow control: Xon/Xoff
Terminator CRLF
Problem: The code will write and read my first command,but it hangs on the second read call. I am currently blocking until I receive at least one character, but each written command should generate a return.
Additional information: I can only run the first write/read if I first unplug the remote and plug it back in. Alternatively, I can open a cool term window, setup my serial port and run a few commands. When I close the cool term window I will be able to write/read once.
Current Code:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <time.h>
#include <iostream>
using namespace std;
int open_port(void)
{
int fd;
// open file descriptor
fd = open("/dev/cu.USA19H41P1.1", O_RDWR | O_NOCTTY);
// if unsucessful
if (fd == -1)
{
printf("open_port: unable to open port. \n");
}
else
{
// remains open across executables
fcntl(fd, F_SETFL, 0);
printf("port is open. \n");
}
return (fd);
}
int configure_port(int fd)
{
// store terminal port settings
struct termios port_settings;
memset(&port_settings, 0, sizeof port_settings);
if(tcgetattr(fd, &port_settings) !=0)
{
printf("error tcgetattr \n");
cout << errno;
}
port_settings.c_iflag = 0;
port_settings.c_oflag = 0;
port_settings.c_lflag = 0;
port_settings.c_cflag = 0;
// flush
tcflush(fd, TCIOFLUSH);
// set baud rate
cfsetispeed(&port_settings, B57600);
cfsetospeed(&port_settings, B57600);
// xon/xoff requirment
port_settings.c_iflag |= IXON;
port_settings.c_iflag |= IXOFF;
// no parity requirement
port_settings.c_cflag &= ~PARENB;
// one stop bin requirement
port_settings.c_cflag &= ~CSTOPB;
// turn on read
port_settings.c_cflag |= CREAD;
port_settings.c_cflag |= CLOCAL;
// no character processing and 8 bit input
port_settings.c_cflag &= ~CSIZE;
port_settings.c_cflag |= CS8;
// one character blocking
port_settings.c_cc[VMIN] = 1;
port_settings.c_cc[VTIME] = 5;
// apply above settings
if(tcsetattr(fd,TCSANOW, &port_settings) != 0)
{
printf("error tcsetattr \n");
cout << errno;
}
// flush buffers one more time
tcflush(fd, TCIOFLUSH);
return(fd);
}
int read_write(int fd)
{
// write to serial port
ssize_t size=write(fd, "1va?\r\n", 8);
// wait until output is transmitted
tcdrain(fd);
// read from serial port
char buf[100];
memset(buf, '\0', sizeof buf);
ssize_t size2=read(fd, &buf, sizeof(buf));
cout << buf << endl;
return(fd);
}
int main(void)
{
// open port
int fd = open_port();
// store old settings
struct termios old_settings;
memset(&old_settings, 0, sizeof old_settings);
tcgetattr(fd,&old_settings);
// configure port
configure_port(fd);
// write/read first command ("1va?\r\n")
read_write(fd);
// write read second command ("1pa?\r\n")
ssize_t size=write(fd, "1pa?\r\n", 8);
tcdrain(fd);
char buf[100];
memset(buf, '\0', sizeof buf);
ssize_t size3=read(fd, &buf, sizeof(buf));
cout << buf;
//close serial port
close(fd);
tcsetattr(fd, TCSANOW, &old_settings);
return 0;
}
Here is some example code on working with Serial ports setting the correct flags and the baud rate:
Provide your code and and more thorough explanation for us to resolve your issue. What do you mean by write and read my first command? Is your device still responsive after this command? Isn't the second command sent?

Error : Resource temporarily unavailable Unable to receive serial data

My C code is sending data to Uart perfectly but while receiving it gives error.
Here is my code
#include <stdio.h> // standard input / output functions
#include <stdlib.h>
#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>
void main()
{
int USB = open( "/dev/ttyUSB0", O_RDWR| O_NONBLOCK | O_NDELAY );
struct termios tty;
struct termios tty_old;
memset (&tty, 0, sizeof tty);
/* Error Handling */
if ( USB < 0 )
{
printf( "Error %d form tcgetattr : %s /n", errno, strerror( errno ) );
}
/* 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; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
/* Make raw */
cfmakeraw(&tty);
/* Flush Port, then applies attributes */
tcflush( USB, TCIFLUSH );
if ( tcsetattr ( USB, TCSANOW, &tty ) != 0)
{
printf("Error %d from tcsetattr /n",errno);
// std::cout << "Error " << errno << " from tcsetattr" << std::endl;
}
/* WRITE */
unsigned char cmd[] = "YES this program is writing \r";
int n_written = 0,spot = 0;
do {
n_written = write( USB, &cmd[spot], 1 );
spot += n_written;
} while (cmd[spot-1] != '\r' && n_written > 0);
/* READ */
int n = 0,spot_r =0;
char buf = '\0';
/* Whole response*/
char response[1024];
memset(response, '\0', sizeof response);
do {
n = read( USB, &buf, 1 );
sprintf( &response[spot_r], "%c", buf );
spot_r += n;
} while( buf != '\r' && n > 0);
if (n < 0) {
printf("Error reading %s",strerror(errno));
}
else if (n==0) {
printf("read nothing");
}
else {
printf("Response %s",response);
}
}
Error Message
Error reading Resource temporarily unavailable
It is sending data to UART perfectly.
But at reception side it gives error of resource temporary unavailable.
Should i put delay in-between?
Or any other function that could help me out.
Thank you.
Abhi

send and receive data using usb to rs232 interface in Linux C

I am writing c code to send and receive characters to and from an Ergometer using FTDI USB to RS232 Cable in Linux. The write function is working properly but the read function has failed. I am not getting any data back from the Ergometer. I have posted my code here:
#include <stdio.h> // standard input / output functions
#include <stdlib.h>
#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 definitions
#include <stdbool.h>
#define SOH 0x01 // Start of Header
#define ETB 0x17 // End of transmission block
#define ACK 0x06 // Acknowledged
#define NAK 0x15 // Not Acknowledged
#define GS 0x1D // Group separator
#define FP_WATT1_PROG 0x13
#define FP_CARDIO 0x2F
int main(){
/* Open File Descriptor */
int USB = open( "/dev/ttyUSB0", O_RDWR| O_NONBLOCK | O_NDELAY );
/* Error Handling */
if ( USB < 0 )
{
printf("Error beim oeffnen");
}
// Configure Port
struct termios tty;
struct termios tty_old;
memset (&tty, 0, sizeof tty);
// Error Handling
if ( tcgetattr ( USB, &tty ) != 0 ) {
printf("error beim tcgetattr");
}
// Save old tty parameters
tty_old = tty;
// Set Baud Rate of 9600 Bps
cfsetospeed (&tty, (speed_t)B9600);
cfsetispeed (&tty, (speed_t)B9600);
// 8 Bits, No Parity and 1 Stop bit settings
tty.c_cflag &= ~PARENB; // No Parity
tty.c_cflag &= ~CSTOPB; // 1 Stop Bit
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8; // 8 Bits
tty.c_cflag &= ~CRTSCTS; // no flow control
tty.c_cc[VMIN] = 1; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_cflag |= (CLOCAL | CREAD ); // turn on READ & ignore ctrl lines
// Make raw
cfmakeraw(&tty);
// Flush Port, then apply attributes
tcflush( USB, TCIFLUSH );
if ( tcsetattr ( USB, TCSANOW, &tty ) != 0)
{
printf("from tcsetattr");
}
// WRITE
// Set the Ergometer language.
char cmd[255] = {0x60,0x01}; // Ergometer Cockpit Adresse
int n_written = write( USB, cmd, sizeof(cmd));
printf("%s\n",cmd);
// Allocate memory for read buffer
int bb = 0;
int i,x = 0;
bool cmdOK=false;
char marr[10];
do
{
if((bb = read(USB, &marr[x], sizeof( marr )-x )) > 0)
{
for (i=x;i<x+bb;i++)
{
//printf("0x%02x",marr[i]);
if ((marr[i]==ACK)||(marr[i]==NAK)) cmdOK=true;
}
x+=bb;
//printf("\n");
//printf("x=%d\n",x);
}
}while(!cmdOK);
printf("-Ausgabe---------------------\n");
for (i=0; i<x; i++)
{
printf("0x%02x",marr[i]);
}
close(USB);
// ttyUSB0 auf alten Wert setzen
tcflush(USB,TCIFLUSH);
if (tcsetattr(USB, TCSANOW, &tty) != 0) return(-1);
exit(0);
return 0;
}

Reading from serial port on Linux and OSX

I am writing simple CLI application for reading data from serial port. I have USB to serial converter with CP2102 and every few seconds, I am receiving 200 B long string.
Edit: I made a mistake. It is not a CP2102, but Profilic PL2303. I also found strange behavior when I use stty -- I cannot change baud rate and it's randomly changing:
$ stty -F /dev/ttyUSB5 57600 # Set baudrate
$ stty -F /dev/ttyUSB5 # Read configuration
speed 1200 baud;
.....
$$ stty -F /dev/ttyUSB5 # Read configuration
speed 9600 baud;
.....
End-of-edit
When I compile my application under Mac OS X, it works without any problem. But when I compile this code for Linux (cheap Android tablet with ARM CPU, I use Android NDK for compilation) I receive some data, then garbage:
~|?>?lq?43??d??2~??O?$?$??c??Hello World, good data.
???5??l??!???????x?????????????fx???~????????????x??????`???????~???f?x???~????`f??f???~?????x??????#ף???????x?????????????fx???~????????????x??????`???????~???f?x???~????`f??f???~??3?
It looks like I set wrong baud rate, but I am 100% sure the baud rate is 57600 bauds.
Is the problem in my code (differences in POSIX, Unix, Linux, etc.) or should I look for problems in hardware (CP2102, etc)?
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // string function definitions
#include <errno.h> // Error number definitions
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <termios.h> // POSIX terminal control definitions
int main(int argc, char *argv[]) {
printf("Opening device... ");
int USB = open("/dev/ttyUSB5", O_RDONLY | O_NOCTTY | O_NONBLOCK);
printf("opened.\n");
struct termios tty;
struct termios tty_old;
memset (&tty, 0, sizeof tty);
/* Error Handling */
if (tcgetattr(USB, &tty) != 0) {
printf("Error %d from tcgetattr: %s!\n", errno, strerror(errno));
}
/* Save old tty parameters */
tty_old = tty;
/* Set Baud Rate */
cfsetospeed (&tty, (speed_t)B57600);
cfsetispeed (&tty, (speed_t)B57600);
/* 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;
tty.c_cc[VTIME] = 5;
tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
/* Make raw */
cfmakeraw(&tty);
/* Flush Port, then applies attributes */
tcflush(USB, TCIFLUSH);
if ( tcsetattr ( USB, TCSANOW, &tty ) != 0) {
printf("Error %d from tcgetattr: %s!\n", errno, strerror(errno));
}
int n = 0;
char buf [256];
printf("Starting to read data...\n");
do {
n = read( USB, &buf, sizeof buf);
if (n > 0) {
printf("%s", buf);
memset(&buf, '\0', sizeof buf);
}
usleep(100000); /* sleep for 100 milliSeconds */
} while(1);
}

Resources