How to read from serial in c ? (under linux)

Like title says...my arduino board periodically sends some integers througth serial board.
I have a controller thread written in C and I need to read these integers. I'm programming under linux so "everything's a file", so I guess I just have to open serial for reading...but how to know if I'm reading the same integer or a new one?

When you're reading a line of text, how do you know it's a new word, and not the same one?

https://www.google.com/search?q=linux+c+read+serial+port

Does this work in kernel mode too? I'm writing a kernel module which has to interact with arduino board..

Phate867:
Does this work in kernel mode too? I'm writing a kernel module which has to interact with arduino board..

Why don't you try it? Just

FILE* ardport = fopen("/dev/ttyACM0", "r+");
FILE* output = fopen("/tmp/ardoutput", "a");

int c;
while ((c = fgetc(ardport)) != EOF) {
  fputc(output, c);
}
fclose(ardport);
flose(output);

Phate867:
how to know if I'm reading the same integer or a new one?

You wrote the program that is sending them, so send them in a way that lets your receiving code detect the boundary between numbers. For example, if you're sending the numbers as an ASCII sequence of decimal digits, you could use any non-digit character(s) as a separator. Comma and/or a line feed would be obvious candidates.

If you are sending integers only, it may be easiest to send them as binary data, though there are still some quirks you have to take care of:

  • Check if the Arduino and your Linux computer share the same byte order (little endian vs. big endian). If not, you need to convert to/from the network byte order when sending/receiving the integers. (Check htons/ntohs man pages on Linux).
  • "int" is 16 bits on the Arduino and probably 32 bits on your Linux computer. Use "short" on Linux instead.

Thanks guys I think I figured out the way! :slight_smile:

Now I have a bigger problem anyway...in my kernel module the open() function is not recognized, it gives me "implicit declaration"!
My include part is:

#include <linux/module.h>
#include <linux/unistd.h>
#include <asm/io.h>
#include <asm/fcntl.h>
#define SERIAL_PORT "/dev/ttyACM0"

while the error is in this line:

void myfun(void){
  int fd = open(SERIAL_PORT,O_RDONLY | O_NOCTTY);
  ..reading...

can you help me to solve this?

it gives me "implicit declaration"!

I'm nearly certain there was more to the message than that.

Does this work in kernel mode too? I'm writing a kernel module which has to interact with arduino board..

You don't know how to access a serial interface in Linux but you wanna write a kernel module?

Start with a smaller project, build a simple kernel module. Extend it to read files. Extend it to access simple character devices (like /dev/random). If that all works try accessing a complex tty device like the serial interface.
You cannot use functionality of the GNU C library withing the kernel (fopen, fclose and the like), don't use any library at all, use the kernel calls directly. This is really different from userland programming.

I've done it..normal kernel module works and I know I cannot use gnu c library, if you look at the code I'm not using it at all.

Tried with a normal user space program and still does not work: a lot of strange characters come out.
I see a problem in your code too: you do not set baud rate at all, I think this has to be a problem...

Phate867:
Tried with a normal user space program and still does not work: a lot of strange characters come out.
I see a problem in your code too: you do not set baud rate at all, I think this has to be a problem...

Yes, you obviously have to set the baud rate and possibly other tty parameters. You can use stty from the command line before running the program or cfsetspeed function in your program.

I'm trying this way but still no success:

        struct termios options;
	int nBytesRead = 0;
	char buffer[20];

	int fd = open(SERIAL_PORT,O_RDONLY | O_NOCTTY);

	if(fd == -1){
		perror("unable to open serial port");
		return -1;	
	}

       //setting baud rate
	tcgetattr(fd, &options);
	cfsetispeed(&options,B9600);
	cfsetospeed(&options,B9600);	
	options.c_cflag |= (CLOCAL | CREAD);
	tcsetattr(fd,TCSANOW,&options);
	fcntl(fd,F_SETFL,0); //setting blocking read
	
	nBytesRead = read(fd,buffer,20);

now it just immediately returns from read with 0 bytes read...but read() should be blocking.

You haven't told the tty after how many characters it should return from a blocking call:

options.c_cc[VMIN] = 20; // block until 20 characters are read

This topic gets very Linux specific, don't you think you should ask your questions on a Linux forum? Your questions have nothing to do with the Arduino platform.