![]() |
| | #1 |
| Registered User Join Date: Jun 2009
Posts: 34
| Best way to read character input from serial port (Linux)? 61 20 20 20 20 20 ...and so on forever, since the var that holds the input hasn't been reset. The bigger issue is that depending on the timing of the while loop, old characters may get mixed up with new input from the master device, which throws everything off. I need the loop to STOP outputting until it knows for sure that new characters are being sent. Example: Code: int fd_serialport;
struct termios options;
fd_serialport = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
if(fd_serialport == -1){
perror("Unable to open /dev/ttyS0");
}
tcgetattr(fd_serialport, &options);
cfsetispeed(&options, B38400);
cfsetospeed(&options, B38400);
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag |= PARENB;
options.c_cflag |= PARODD;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_iflag |= (INPCK | ISTRIP);
tcsetattr(fd_serialport, TCSANOW, &options);
fcntl(fd_serialport, F_SETFL, FNDELAY);
while(read(fd_serialport, &data_in[0], sizeof(char))){
printf("%s\n",&data_in[0]);
usleep(2000);
}
|
| synthetix is offline | |
| | #2 |
| Registered User Join Date: Jun 2009
Posts: 34
| Ok, I think I partially figured this out. If I automatically set the variable to '\0' after reading one character, and then add an if statement to check this, it seems to work the way I need it. HOWEVER, there are characters sent that actually are 0 (0x00), that I need to see. If I set the var to '\0' after reading, when input is read that actually is 0 (and valid), these characters are ignored: Code: while(read(fd_serialport, &data_in[0], sizeof(char))){
if(data_in[0] != '\0'){
printf("%02x\n",data_in[0]);
}
data_in[0] = '\0'; //reset and wait for next char
}
|
| synthetix is offline | |
| | #3 |
| +++ OK NO CARRIER Join Date: Oct 2001
Posts: 10,258
| Code: while( read( fd_serialport, &data[0], 1 ) != -1 )
{
...do stuff...
}
Quzah.
__________________ Hundreds of thousands of dipshits can't be wrong. Are you up for the suck? |
| quzah is offline | |
| | #4 |
| Registered User Join Date: Jun 2009
Posts: 34
| I think I figured it out. I used select() to determine if new data was available (by checking FD_ISSET), then read(). It seems to be working OK. |
| synthetix is offline | |
| | #5 |
| Registered User Join Date: Oct 2008 Location: TX
Posts: 1,262
| Another way is to setup the read() to block until new characters are available in the serial input buffer: Code: fcntl(fd_serialport, F_SETFL, 0); /* causes read to block until new characters are present */ fcntl(fd_serialport, F_SETFL, FNDELAY); /* remove this call as it causes read to return immediately */ |
| itCbitC is offline | |
| | #6 | |
| Registered User Join Date: Jun 2009
Posts: 34
| Quote:
I've also discovered the following: If using non-blocking I/O, you will need to implement your own checks to confirm the completion of reads/writes. I've found a few ways of doing this. One is the way you just mentioned (which seems to be the simplest), using read() with blocking I/O flags set. Second is using a non-blocking file descriptor with select() to check for completed reads. Yet another is using a non-blocking file descriptor flagged with O_ASYNC along with signal(), checking for SIGIO: Code: fcntl(fd_serialport, F_SETOWN, getpid()); fcntl(fd_serialport, F_SETFL, O_ASYNC); | |
| synthetix is offline | |
| | #7 |
| Senior software engineer Join Date: Mar 2007 Location: Portland, OR
Posts: 5,378
| So you took the good solution (select) and replaced it with a dumb one (non-blocking IO).
__________________ "Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously." -- raftpeople@slashdot |
| brewbuck is offline | |
| | #8 |
| Registered User Join Date: Jun 2009
Posts: 34
| I'm not sure I understand. I don't see the point in using the extra code if using blocking I/O allows me to read the serial port without losing data. If you think I'm overlooking something and making a mistake, please explain. |
| synthetix is offline | |
| | #9 |
| +++ OK NO CARRIER Join Date: Oct 2001
Posts: 10,258
| Using select will allow you to sleep when nothing is waiting to be read. Quzah.
__________________ Hundreds of thousands of dipshits can't be wrong. Are you up for the suck? |
| quzah is offline | |
| | #10 | |
| Senior software engineer Join Date: Mar 2007 Location: Portland, OR
Posts: 5,378
| Quote:
From an engineering standpoint you should find that revolting.
__________________ "Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously." -- raftpeople@slashdot | |
| brewbuck is offline | |
| | #11 | |
| Kernel hacker Join Date: Jul 2007 Location: Farncombe, Surrey, England
Posts: 15,686
| Quote:
If I suggested such a thing on the ~ 300MHz processors that go into our product, I'd be severely told off by whoever reviews the design document (or code if the design document didn't specify it precisely enough). But of course, if the CPU isn't really doing much, and electricity is for free, then sure, go ahead and burn up those cycles for no use. -- Mats
__________________ Compilers can produce warnings - make the compiler programmers happy: Use them! Please don't PM me for help - and no, I don't do help over instant messengers. | |
| matsp is offline | |
| | #12 | |
| Registered User Join Date: Jun 2009
Posts: 34
| Quote:
I ended up going back to select() as the app grew, since using blocking I/O brings everything to a halt as long as the machine is polling the port. Couldn't I could use blocking I/O in a thread without select() and still prevent the main thread from stopping dead in its tracks? | |
| synthetix is offline | |
| | #13 |
| +++ OK NO CARRIER Join Date: Oct 2001
Posts: 10,258
| If you're not sleeping for some length of time, then you are going to be just check check check check check check check check check check ... as fast as it can, burning up 100% of your CPU time. If one thread is sitting there doing nothing, where the other one is going to say "check check check check...", your scheduler should look and say "Hey, that thread's not doing anything, and this one needs an assload of CPU time, let's let it do its thing..." Basically, if nothing is pending on either thread, you want to not really do anything at all (assuming you're not actually trying to do anything while you don't have any data), other than sit and wait for something to happen. Quzah.
__________________ Hundreds of thousands of dipshits can't be wrong. Are you up for the suck? |
| quzah is offline | |
| | #14 |
| Registered User Join Date: Jun 2009
Posts: 34
| The serial port "module" runs in its own thread, using non-blocking I/O (O_NONBLOCK) and select(). I passed a struct to the thread that contains the stuff that the thread needs to update (based on serial input) for the purpose of controlling the main thread: Code: void *do_serial_control(void *args); //prototype for ctrl thread
struct SERIALCTRL {
int device_status;
char timecode[4];
};
struct SERIALCTRL serial_control;
pthread_create(&thread1, NULL, do_serial_control, (void*)&serial_control);
Seems to be working well so far! Thanks for the help! |
| synthetix is offline | |
| | #15 |
| Registered User Join Date: Oct 2008 Location: TX
Posts: 1,262
| Curious if you made it non-blocking by setting a timeout in the struct timeval member?? |
| itCbitC is offline | |
![]() |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| sending data over UDP from serial port | forumguy | Linux Programming | 0 | 04-25-2009 02:10 PM |
| can someone help me with these errors please code included | geekrockergal | C Programming | 7 | 02-10-2009 02:20 PM |
| Problem with string and serial port | collinm | C Programming | 2 | 03-23-2005 10:19 AM |
| Serial Communications in C | ExDigit | Windows Programming | 7 | 01-09-2002 10:52 AM |
| Need help or info about serial port communication | Unregistered | Linux Programming | 1 | 01-08-2002 01:48 PM |