msmithy12
Posts: 94
Joined: Fri Aug 10, 2012 8:57 am

Serial Comms In C

Thu Feb 07, 2013 11:17 am

Ok, so i have been bouncing from forum to forum via Google and Bing looking for serial port comms in c.


I have found a few examples and have wrote a program that outputs a message on the serial port waits for a response and then outputs the response to the terminal.

Code: Select all


#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>

main()
	int fd = open("/dev/ttyAMA0", O_WRONLY | O_NOCTTY | O_NDELAY);
	if (fd == -1)

	{
	//Could not open Port

	perror("open_port: Unable to Open /dev/ttyAMA0 -");
	gtk_statusbar_push(GTK_STATUSBAR (statusbar), 0, "Serious Error");
	}

	int z = write(fd, "Enter Message\n", 14);
	if(z<0)
		fputs("write fail\n", stderr);

	fd = open("/dev/ttyAMA0", O_RDONLY | O_NOCTTY);
	if (fd == -1)

	{
	//Could not open Port

	perror("open_port: Unable to Open /dev/ttyAMA0 -");
	gtk_statusbar_push(GTK_STATUSBAR (statusbar), 0, "Serious Error");
	}

	char a[32];
	int n = read(fd, a, sizeof(a));

	if (n < 0)
		fputs("read failed!\n", stderr);

printf("You entered:- %s", a);

}
Im not saying its pretty, im not saying its optimised for performance. Im saying its what i wanted to achieve and i guess someone else in the pi world is wanting the same.

I saw on a forum that a guy was asking for a similar piece of code, and the top response was a second guy offering to quote the job and charge the first guy for help.

also remember that to connect the serial on the pi to a pc serial you need a max232c and 4 caps. Info on the MAX232c is on the datasheet on the RS website (other component suppliers are available)

In real life i have that routine in a gtk_signal_connect.

I hope this helps someone
I assume I know what I`m talking about... I probably don`t

Home: 256mb Made in UK, Rasbmc, 40" Sony Bravia KDL-40v3000
Work: 2b+, Rasbian, 6" Lilliput touchscreen

User avatar
rurwin
Forum Moderator
Forum Moderator
Posts: 4257
Joined: Mon Jan 09, 2012 3:16 pm
Contact: Website

Re: Serial Comms In C

Thu Feb 07, 2013 11:56 am

That code is better than the other example I've seen, which uses the O_NDELAY flag for the read, but it suffers from another problem arising from that.

If the serial port is opened with the O_NDELAY flag then all read() calls will return immediately. If there is no data already received by the port then it will report an error. That has confused more than one poster here.

However if the O_NDELAY flag is not given, then the read() call will wait until enough characters have been received to fill its buffer. In this case that is 32 characters. That is never going to be a correct solution in the real world. There are two usable alternatives:

You could specify O_NDELAY and loop around the read() call until all the data that is required to be read has been read. Detecting that condition would depend on the situation, but in this case reception of the '\n' is probably what you want. You would have to expect the data to come in short pieces, maybe only one byte each, and the program would have to append those to the incoming message. That would be rather inefficient, since 99%+ of calls to read() would read no data.

Given that this program has no timeout detection, a better solution is probably to not specify the O_NDELAY flag and then repeatedly call read() with a size of 1 until you receive the '\n'.

In the real world you'd probably want to use O_NDELAY and then call select() with a timeout, but that would complicate this simple example.

msmithy12
Posts: 94
Joined: Fri Aug 10, 2012 8:57 am

Re: Serial Comms In C

Thu Feb 07, 2013 12:18 pm

i pieced that example through trial and error using some forum posts i came across. Any extra info/mods are great and i will be trying these suggestions in my code.

I aimed to give everyone a starting platform to build their code from and helpful/experienced coders like rurwin will give better information than i can.

Also im going to forget the O_NDELAY flag and set the buffer to the size of data i expect and see how that goes.
I assume I know what I`m talking about... I probably don`t

Home: 256mb Made in UK, Rasbmc, 40" Sony Bravia KDL-40v3000
Work: 2b+, Rasbian, 6" Lilliput touchscreen

User avatar
gordon@drogon.net
Posts: 2023
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website Twitter

Re: Serial Comms In C

Thu Feb 07, 2013 2:23 pm

There's always going to be that issue on serial port reads (O_NDELAY or not), and a lot will really depend on your application - when I did the wiringSerial stuff, I did it based on code I've been using under Linux for a very long time and that uses O_NDELAY, but then sets a time-out (of 10 seconds) on reads too.

Most of my stuff is to communicate with remote devices which are usually well behaved, but you never know, so at least that gives an option (and is trivial to change anyway)

Another stategy is to simply open it blocking and use the FIONREAD ioctl() call to see if there is data avalable - unless blocking on a read is OK with your program.

-Gordon
--
Gordons projects: https://projects.drogon.net/

Return to “C/C++”