diff options
Diffstat (limited to 'arduino-serial.c')
-rw-r--r-- | arduino-serial.c | 201 |
1 files changed, 67 insertions, 134 deletions
diff --git a/arduino-serial.c b/arduino-serial.c index 0646f23..3f3f35f 100644 --- a/arduino-serial.c +++ b/arduino-serial.c @@ -1,5 +1,5 @@ /* - * Arduino-serial + * arduino-serial * -------------- * * A simple command-line example program showing how a computer can @@ -7,9 +7,14 @@ * * * Compile with something like: - * gcc -o arduino-serial arduino-serial.c + * gcc -o arduino-serial arduino-serial-lib.c arduino-serial.c + * or use the included Makefile * - * Created 5 December 2006 + * Mac: make sure you have Xcode installed + * Windows: try MinGW to get GCC + * + * + * Originally created 5 December 2006 * Copyleft (c) 2006, Tod E. Kurt, tod@todbot.com * http://todbot.com/blog/ * @@ -27,54 +32,64 @@ * Update 31 August 2008: * Added patch to clean up odd baudrates from Andy at hexapodia.org * + * Update 6 April 2012: + * Split into a library and app parts + * */ -#include <stdio.h> /* Standard input/output definitions */ +#include <stdio.h> // Standard input/output definitions #include <stdlib.h> -#include <stdint.h> /* Standard types */ -#include <string.h> /* String function definitions */ -#include <unistd.h> /* UNIX standard function definitions */ -#include <fcntl.h> /* File control definitions */ -#include <errno.h> /* Error number definitions */ -#include <termios.h> /* POSIX terminal control definitions */ -#include <sys/ioctl.h> +#include <stdint.h> +#include <string.h> // String function definitions #include <getopt.h> -void usage(void); -int serialport_init(const char* serialport, int baud); -int serialport_writebyte(int fd, uint8_t b); -int serialport_write(int fd, const char* str); -int serialport_read_until(int fd, char* buf, char until); +#include "arduino-serial-lib.h" + + +const int buf_max = 256; -void usage(void) { +// +void usage(void) +{ printf("Usage: arduino-serial -p <serialport> [OPTIONS]\n" "\n" "Options:\n" " -h, --help Print this help message\n" " -p, --port=serialport Serial port Arduino is on\n" " -b, --baud=baudrate Baudrate (bps) of Arduino\n" - " -s, --send=data Send data to Arduino\n" - " -r, --receive Receive data from Arduino & print it out\n" + " -s, --send=string Send string to Arduino\n" + " -S, --sendline=string Send string with newline to Arduino\n" + " -r, --receive Receive string from Arduino & print it out\n" " -n --num=num Send a number as a single byte\n" + " -F --flush Flush the serial port buffers for fresh reading\n" " -d --delay=millis Delay for specified milliseconds\n" + " -q --quiet Don't print out as much info\n" "\n" "Note: Order is important. Set '-b' before doing '-p'. \n" " Used to make series of actions: '-d 2000 -s hello -d 100 -r' \n" " means 'wait 2secs, send 'hello', wait 100msec, get reply'\n" "\n"); + exit(EXIT_SUCCESS); +} + +// +void error(char* msg) +{ + fprintf(stderr, "%s\n",msg); + exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { - int fd = 0; - char serialport[256]; - int baudrate = B9600; // default - char buf[256]; + int fd = -1; + char serialport[buf_max]; + int baudrate = 9600; // default + char buf[buf_max]; int rc,n; + char quiet=0; if (argc==1) { usage(); - exit(EXIT_SUCCESS); } /* parse options */ @@ -84,20 +99,27 @@ int main(int argc, char *argv[]) {"port", required_argument, 0, 'p'}, {"baud", required_argument, 0, 'b'}, {"send", required_argument, 0, 's'}, + {"sendline", required_argument, 0, 'S'}, {"receive", no_argument, 0, 'r'}, + {"flush", no_argument, 0, 'F'}, {"num", required_argument, 0, 'n'}, {"delay", required_argument, 0, 'd'}, + {"quiet", no_argument, 0, 'q'}, {NULL, 0, 0, 0} }; while(1) { - opt = getopt_long (argc, argv, "hp:b:s:rn:d:", + opt = getopt_long (argc, argv, "hp:b:s:S:rFn:d:q", loptions, &option_index); if (opt==-1) break; switch (opt) { case '0': break; + case 'q': + quiet = 1; + break; case 'd': n = strtol(optarg,NULL,10); + if( !quiet ) printf("sleep %d millisecs\n",n); usleep(n * 1000 ); // sleep milliseconds break; case 'h': @@ -109,128 +131,39 @@ int main(int argc, char *argv[]) case 'p': strcpy(serialport,optarg); fd = serialport_init(optarg, baudrate); - if(fd==-1) return -1; + if( fd==-1 ) error("couldn't open port"); + serialport_flush(fd); break; case 'n': + if( fd == -1 ) error("serial port not opened"); n = strtol(optarg, NULL, 10); // convert string to number rc = serialport_writebyte(fd, (uint8_t)n); - if(rc==-1) return -1; + if(rc==-1) error("error writing"); break; + case 'S': case 's': - strcpy(buf,optarg); - printf("read string '%s'\n", buf); + if( fd == -1 ) error("serial port not opened"); + sprintf(buf, (opt=='S' ? "%s\n" : "%s"), optarg); + + if( !quiet ) printf("send string:%s\n", buf); rc = serialport_write(fd, buf); - if(rc==-1) return -1; + if(rc==-1) error("error writing"); break; case 'r': - serialport_read_until(fd, buf, '\n'); - printf("read: %s\n",buf); + if( fd == -1 ) error("serial port not opened"); + memset(buf,0,buf_max); // + serialport_read_until(fd, buf, '\n', buf_max); + if( !quiet ) printf("read string:"); + printf("%s\n", buf); + break; + case 'F': + if( fd == -1 ) error("serial port not opened"); + serialport_flush(fd); break; + } } exit(EXIT_SUCCESS); } // end main -int serialport_writebyte( int fd, uint8_t b) -{ - int n = write(fd,&b,1); - if( n!=1) - return -1; - return 0; -} - -int serialport_write(int fd, const char* str) -{ - int len = strlen(str); - int n = write(fd, str, len); - if( n!=len ) { - printf("couldn't write whole string\n"); - return -1; - } - return 0; -} - -int serialport_read_until(int fd, char* buf, char until) -{ - char b[1]; - int i=0; - do { - int n = read(fd, b, 1); // read a char at a time - if( n==-1) return -1; // couldn't read - if( n==0 ) { - usleep( 10 * 1000 ); // wait 10 msec try again - continue; - } - buf[i] = b[0]; i++; - } while( b[0] != until ); - - buf[i] = 0; // null terminate the string - return 0; -} - -// takes the string name of the serial port (e.g. "/dev/tty.usbserial","COM1") -// and a baud rate (bps) and connects to that port at that speed and 8N1. -// opens the port in fully raw mode so you can send binary data. -// returns valid fd, or -1 on error -int serialport_init(const char* serialport, int baud) -{ - struct termios toptions; - int fd; - - //fprintf(stderr,"init_serialport: opening port %s @ %d bps\n", - // serialport,baud); - - fd = open(serialport, O_RDWR | O_NOCTTY | O_NDELAY); - if (fd == -1) { - perror("init_serialport: Unable to open port "); - return -1; - } - - if (tcgetattr(fd, &toptions) < 0) { - perror("init_serialport: Couldn't get term attributes"); - return -1; - } - speed_t brate = baud; // let you override switch below if needed - switch(baud) { - case 4800: brate=B4800; break; - case 9600: brate=B9600; break; -#ifdef B14400 - case 14400: brate=B14400; break; -#endif - case 19200: brate=B19200; break; -#ifdef B28800 - case 28800: brate=B28800; break; -#endif - case 38400: brate=B38400; break; - case 57600: brate=B57600; break; - case 115200: brate=B115200; break; - } - cfsetispeed(&toptions, brate); - cfsetospeed(&toptions, brate); - - // 8N1 - toptions.c_cflag &= ~PARENB; - toptions.c_cflag &= ~CSTOPB; - toptions.c_cflag &= ~CSIZE; - toptions.c_cflag |= CS8; - // no flow control - toptions.c_cflag &= ~CRTSCTS; - - toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines - toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl - - toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw - toptions.c_oflag &= ~OPOST; // make raw - - // see: http://unixwiz.net/techtips/termios-vmin-vtime.html - toptions.c_cc[VMIN] = 0; - toptions.c_cc[VTIME] = 20; - - if( tcsetattr(fd, TCSANOW, &toptions) < 0) { - perror("init_serialport: Couldn't set term attributes"); - return -1; - } - - return fd; -} |