What is the best and easiest operating system to program in C in especially if I’m programming a serial port? Windows, Linux, or just DOS?
What is the best and easiest operating system to program in C in especially if I’m programming a serial port? Windows, Linux, or just DOS?
Is that it, or were you planning to do something else as well?
Driving the solution from looking at just one aspect of the problem isn't the way to go.
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
If at first you don't succeed, try writing your phone number on the exam paper.
This is a robotics project. I'm using a R232 serial port to control a microcontroller board. So the computer will be doing calculations and decisions, but input and output will be through the serial port. I’ve been working in a Linux environment with GCC, yet reading and writing through the port seems very complicated. I finally can send numbers out (every other time I run the program), but I get a segmentation error-core dumped when I try to read from the port. I wonder if plain DOS would have fewer “hoops” to jump through to send and receive numbers through the port.
Serial ports in Linux is far less complicated than doing it in DOS - for one thing, the OS will actually help you with the collection of data, and (almost) guarantee that you never miss a reply from the sending side.
Windows has the same advantage.
A segmentation fault is nothing to do with accessing the serial port (or at least, it's highly unlikely), but rather with how you deal with data to or from the serial port. Segmentation errors are caused by accessing memory that is not available - usually caused by errant pointers.
--
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.
> but I get a segmentation error-core dumped when I try to read from the port.
Post your code, then we can fix it.
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
If at first you don't succeed, try writing your phone number on the exam paper.
Here is my code for recieving bytes from a device through the serial port:
When certain numbers are sent to this device it is programmed to return all data from its sensors which is 26 bytes, but instead I get a segmentation error-core dumped message.Code:#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/io.h> #include <fcntl.h> #include <termios.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/time.h> #define SERIAL "/dev/ttyS0" #define BAUDRATE B57600 #define _POSIX_SOURCE 1 #define FALSE 0 #define TRUE 1 volatile int STOP=FALSE; void get_data(void); void request_data(void); int sensor[26]; int n, fd; struct termios oldtio,newtio; int main(void)/*------------------------MAIN PROGRAM*/ { request_data(); /* Asks for data from Roomba*/ get_data(); /*Reads input from Roomba*/ /* restore the old port settings */ tcsetattr(fd,TCSANOW,&oldtio); return 0; } void request_data()/*..................................Asks for input from Roomba*/ { fd = open(SERIAL, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd<0) {perror(SERIAL); exit(-1);} tcgetattr(fd,&oldtio); // save current port settings // set new port settings for canonical input processing newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD; newtio.c_iflag = IGNPAR | ICRNL; newtio.c_oflag = 0; newtio.c_lflag = 0; //ICANON; newtio.c_cc[VMIN]=1; newtio.c_cc[VTIME]=0; tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio); /*Roomba Control*/ int begin[1]; begin[0] = 128; n=write(fd, begin, 1); /*Prepares Roomba to receive orders*/ if (n < 0) printf("Error @ begin!\n"); begin[0] = 130; n=write(fd, begin, 1); /* Roomba Ready!*/ begin[0] = 142; /* Get Data*/ n=write(fd, begin, 1); begin[0] = 0; /* Return all 26 bytes*/ n=write(fd, begin, 1); close (fd); /*Closes the port?*/ } void get_data() /* =========================Read data that Roomba sent*/ { int ch, i; char a; fd = open(SERIAL, O_RDWR | O_NOCTTY); if (fd<0) {perror(SERIAL); exit(-1);} tcgetattr(fd,&oldtio); /* save current port settings */ bzero(&newtio, sizeof(newtio)); newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD; newtio.c_iflag = IGNPAR; newtio.c_oflag = 0; /* set input mode (non-canonical, no echo,...) */ newtio.c_lflag = 0; newtio.c_cc[VTIME] = 0; /* inter-character timer unused */ newtio.c_cc[VMIN] = 26; /* blocking read until 26 chars received */ tcsetattr(fd,TCSANOW,&newtio); n=read(fd, sensor, 255); /* returns after 26 chars have been input */ printf("%d\n",sensor[0]); printf("%d\n",sensor[1]); printf("%d\n",sensor[2]); printf("%d\n",sensor[3]); close (fd); /*Closes the port?*/ }
Thanks for any help with the code, but first a question. I have a degree in mechanical engineering, and I want to build a robot that is sophisticated enough to count as experience in robotics to help me get a job in robotics. Is C the best language for this, and would robot “experts” be pleased with experience in programming in Linux or another system?
Why are you using int arrays for all your byte streams ?
Why do you open/close the connection in both functions? Open it once at the start of the program, then close it again when you're done.
> n=read(fd, sensor, 255); /* returns after 26 chars have been input */
So say 26 then, not 255. That's just a big invitation to a buffer overflow.
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
If at first you don't succeed, try writing your phone number on the exam paper.
I learning from tutorials that use arrays for reading and writing to the port.
Now it doesn't seem to respond to reading or writing.
Here is code that I wrote that sends numbers to the device to get it to move, and then when a key is hit 4 zeros are sent to tell it to stop.
It used to work every other time, but now it doesn't do anything.Code:#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/io.h> #include <fcntl.h> #include <termios.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/time.h> #define SERIAL "/dev/ttyS0" #define PORT1 0x3F8 #define BAUDRATE B57600 #define _POSIX_SOURCE 1 void changemode(int); / int kbhit(void); int main(void) { int n, fd, ch; char a; struct termios oldtio,newtio; fd = open(SERIAL, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd<0) {perror(SERIAL); exit(-1);} tcgetattr(fd,&oldtio); // save current port settings // set new port settings for canonical input processing newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD; newtio.c_iflag = IGNPAR | ICRNL; newtio.c_oflag = 0; newtio.c_lflag = 0; //ICANON; newtio.c_cc[VMIN]=1; newtio.c_cc[VTIME]=0; tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio); /*Roomba Control*/ int begin[1]; begin[0] = 128; n=write(fd, begin, 1); /*Prepares Roomba to receive orders*/ if (n < 0) printf("Error @ begin!\n"); begin[0] = 130; n=write(fd, begin, 1); if (n < 0) begin[0] = 132; n=write(fd, begin, 1); /* Roomba Ready!*/ begin[0] = 137; /* Forward*/ n=write(fd, begin, 1); begin[0] = 255; n=write(fd, begin, 1); begin[0] = 56; n=write(fd, begin, 1); if (n < 0) printf("Error @ begin!\n"); begin[0] = 128; n=write(fd, begin, 1); if (n < 0) printf("Error @ begin!\n"); begin[0] = 0; n=write(fd, begin, 1); if (n < 0) printf("Error @ begin!\n"); changemode(1); while ( !kbhit() ) { putchar('.'); } begin[0] = 137; n=write(fd, begin, 1); if (n < 0) printf("Error @ begin!\n"); /*Orders Roomba to stop*/ begin[0] = 0; n=write(fd, begin, 1); n=write(fd, begin, 1); n=write(fd, begin, 1); n=write(fd, begin, 1); /* restore the old port settings */ tcsetattr(fd,TCSANOW,&oldtio); changemode(0); return 0; } void changemode(int dir) { static struct termios oldt, newt; if ( dir == 1 ) { tcgetattr( STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~( ICANON | ECHO ); tcsetattr( STDIN_FILENO, TCSANOW, &newt); } else tcsetattr( STDIN_FILENO, TCSANOW, &oldt); } int kbhit (void) { struct timeval tv; fd_set rdfs; tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&rdfs); FD_SET (STDIN_FILENO, &rdfs); select(STDIN_FILENO+1, &rdfs, NULL, NULL, &tv); return FD_ISSET(STDIN_FILENO, &rdfs); }
Is there a way to check if the computer did send bytes out of the port?
What are the books on serial port programming in Linux?
> void changemode(int); /
Does it compile with that trailing / ?
> It used to work every other time, but now it doesn't do anything.
Learn about CVS
At the very least, make regular backups of what used to work so that you can always get back to something which works, and maybe do a "diff" to find out what changed in the meantime to break it.
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
If at first you don't succeed, try writing your phone number on the exam paper.
That is the program that use to work every other time. That's what doesn't make sense. I copied the code you see from the program that was saved for backup. How does a program work every other time and then not at all without any changes in the code?
Also how different is inputing and outputing with microcontroller boards as apposed to PC's if the I/O is digital?
Like Salem, I doubt this would actually compile - I haven't got a Linux machine at the moment to test it on, but I'm pretty sure it's not compiling.
One reason that you can't communicate on the serial port may be that the /dev/ttyS0 is being used by some other process, for example the /etc/inittab has a getty on ttyS0 (remove that line if that's the case).
--
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.
I don't see /etc/inittab or getty in the code. Is that somewhere in the Linux system? I'm still learning C and Linux.
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.