Skip to content

Instantly share code, notes, and snippets.

@armadsen
Created October 12, 2015 17:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save armadsen/31d311120d58a739fbfe to your computer and use it in GitHub Desktop.
Save armadsen/31d311120d58a739fbfe to your computer and use it in GitHub Desktop.
Simple demo of opening and reading data from a serial port in pure C in OS X.
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <dispatch/dispatch.h>
int main(int argc, char *argv[]) {
int fd = open("/dev/cu.usbmodem1421", O_RDWR | O_NOCTTY | O_EXLOCK | O_NONBLOCK);
if (fd < 1) { return printf("Error opening port: %i\n", errno); }
struct termios originalPortAttributes;
tcgetattr(fd, &originalPortAttributes); // Get original options so they can be reset later
fcntl(fd, F_SETFL, 0);
struct termios options;
tcgetattr(fd, &options);
cfmakeraw(&options);
options.c_cc[VMIN] = 1; // Wait for at least 1 character before returning
options.c_cc[VTIME] = 2; // Wait 200 milliseconds between bytes before returning from read
// Set 8 data bits
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_cflag &= ~PARENB; // Set no parity
options.c_cflag &= ~CSTOPB; // 1 stop bit
options.c_lflag &= ~ECHO; // no echo
options.c_cflag &= ~CRTSCTS; // no RTS/CTS Flow Control
options.c_cflag &= ~(CDTR_IFLOW | CDSR_OFLOW); // no DTR/DSR Flow Control
options.c_cflag &= ~CCAR_OFLOW; // no DCD Flow Control
options.c_cflag |= HUPCL; // Turn on hangup on close
options.c_cflag |= CLOCAL; // Set local mode on
options.c_cflag |= CREAD; // Enable receiver
options.c_lflag &= ~(ICANON /*| ECHO*/ | ISIG); // Turn off canonical mode and signals
// Set baud rate
cfsetspeed(&options, B57600);
if (tcsetattr(fd, TCSANOW, &options)) { return printf("Error setting options on port: %i\n", errno); }
// Start a read dispatch source in the background
dispatch_source_t readPollSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, dispatch_get_main_queue());
dispatch_source_set_event_handler(readPollSource, ^{
// Data is available
char buf[1024] = {0};
long lengthRead = read(fd, buf, sizeof(buf));
if (lengthRead > 0) printf("received: %s\n", buf);
});
dispatch_source_set_cancel_handler(readPollSource, ^{
// Set port back the way it was before we used it
tcsetattr(fd, TCSADRAIN, &originalPortAttributes);
printf("Closing port.\n");
if (close(fd)) { printf("error closing port: %i", errno); return;}
printf("Quitting.\n");
exit(EXIT_SUCCESS);
});
dispatch_resume(readPollSource);
dispatch_source_t stdinReadSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, STDIN_FILENO, 0, dispatch_get_main_queue());
dispatch_source_set_event_handler(stdinReadSource, ^(void) {
printf("got input\n");
char buf[10] = {0};
long lengthRead = read(STDIN_FILENO, buf, sizeof(buf));
if (buf[0] == 'q') { dispatch_cancel(readPollSource); }
});
dispatch_resume(stdinReadSource);
dispatch_main();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment