cary
Posts: 6
Joined: Thu Mar 21, 2013 2:37 pm

Why i can only get one character each time from UTRA

Thu Mar 28, 2013 9:38 am

I use same code on my raspberry and pc, the utra mode is set to raw mode. The only different is pc open dev '/dev/ttyUSB0' and raspberry open dev '/dev/ttyAMA0'. Then i try to send character from each other.
I can get many character on my raspberry from pc one time, but can only get one character on pc from my raspberry one time.

That bother my a lot. Does any meet the same problem?

User avatar
joan
Posts: 15469
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Why i can only get one character each time from UTRA

Thu Mar 28, 2013 9:40 am

It's probably a mistake in your code.

Could you post the PC and Pi code?

cary
Posts: 6
Joined: Thu Mar 21, 2013 2:37 pm

Re: Why i can only get one character each time from UTRA

Fri Mar 29, 2013 2:04 pm

This is the code on pc

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>

void writeBytes(int descriptor, int count);
void readBytes(int descriptor, int count);
void displaySoftwareValue(int fd);
int getRangeCM(int fd);

char serialBuffer[10];									

int main(int argc, char **argv)
{
	int fd;												
	char *portName = "/dev/ttyUSB0";					
	struct termios options;								

	fd = open(portName, O_RDWR | O_NOCTTY);				
	if (fd == -1)
	{
		perror("openPort: Unable to open port ");		
	}
	tcgetattr(fd, &options);
	cfsetispeed(&options, B9600);						
	cfsetospeed(&options, B9600);

	cfmakeraw(&options);

	tcflush(fd, TCIFLUSH);
	tcsetattr(fd, TCSANOW, &options);

	usleep(10000);	
									
	serialBuffer[0] = 0x01;										
	serialBuffer[1] = 0x5D;
	serialBuffer[2] = 0x4;


	writeBytes(fd, 3);
	readBytes(fd, 3);

	printf("SRTF01 Software v: %d,%d \n",serialBuffer[0],serialBuffer[1]);									

	fflush(stdout);

	close(fd);											

	return 0;
}

void writeBytes(int descriptor, int count) {
	if ((write(descriptor, serialBuffer, count)) == -1) {			
		perror("Error writing");
		close(descriptor);											
		exit(1);
	}
}

void readBytes(int descriptor, int count) {
	tcflush(descriptor, TCIFLUSH);								
	if (read(descriptor, serialBuffer, count) == -1) {				
		perror("Error reading ");
		close(descriptor);											
		exit(1);
	}
}
This the code on my raspberry

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>

void writeBytes(int descriptor, int count);
void readBytes(int descriptor, int count);
void displaySoftwareValue(int fd);
int getRangeCM(int fd);

char serialBuffer[10];									

int main(int argc, char **argv)
{
	int fd;												
	char *portName = "/dev/ttyAMA0";					
	struct termios options;								

	fd = open(portName, O_RDWR | O_NOCTTY);				
	if (fd == -1)
	{
		perror("openPort: Unable to open port ");		
	}
	tcgetattr(fd, &options);
	cfsetispeed(&options, B9600);						
	cfsetospeed(&options, B9600);

	cfmakeraw(&options);

	tcflush(fd, TCIFLUSH);
	tcsetattr(fd, TCSANOW, &options);

	usleep(10000);	

	readBytes(fd, 3);

	printf("SRTF01 Software v: %d,%d \n",serialBuffer[0],serialBuffer[1]);										
	serialBuffer[0] = 0x04;										
	serialBuffer[1] = 0x31;
	serialBuffer[2] = 0x22;

	writeBytes(fd, 3);						

	fflush(stdout);

	close(fd);											

	return 0;
}

void writeBytes(int descriptor, int count) {
	if ((write(descriptor, serialBuffer, count)) == -1) {			
		perror("Error writing");
		close(descriptor);											
		exit(1);
	}
}

void readBytes(int descriptor, int count) {
	tcflush(descriptor, TCIFLUSH);								
	if (read(descriptor, serialBuffer, count) == -1) {				
		perror("Error reading ");
		close(descriptor);											
		exit(1);
	}
}
I use this code to communicate each other, and i can get the three character 0x01, 0x5D, 0x04 sent from pc on my raspberry, but only can get 0x04, 0x01 sent from my raspberry on pc. Especially the 0x01 is so weird, it the character pc just send.
So does any one know why? I really confused.

User avatar
jojopi
Posts: 3426
Joined: Tue Oct 11, 2011 8:38 pm

Re: Why i can only get one character each time from UTRA

Fri Mar 29, 2013 4:07 pm

One of the things that cfmakeraw() requests is "noncanonical input mode". In this mode, control characters have no special meaning, and input is not line buffered. Instead, it is returned according to the VMIN and VTIME settings. You have not set those explicitly so you get the default values of:

Code: Select all

   options.c_cc[VMIN] = 1;
   options.c_cc[VTIME] = 0;
This means that read() returns as soon as there is at least one character available, otherwise it waits forever. Because the PC is fast is the baud rate is low, your first call to read() starts before any characters have been received, and it need only wait for the first one.

You could change the termios settings to:

Code: Select all

   options.c_cc[VMIN] = 3;
   options.c_cc[VTIME] = 10;
Then read() will wait until either there are three characters available, or it has been ten tenths of a second since the last one arrived.

More typically, though, you would include extra logic in readBytes() to detect when read() returns fewer bytes than requested, and decide whether to return them straight away, or keep calling read() until there are enough.

Return to “C/C++”