본문 바로가기

Enginius/Linux

Using serial comm in Linux environment

1. inclde stuffs, we assume basic headers are already included


#include <termios.h>
#include <string.h>
#include <unistd.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>


2. define some variables and functions


typedef struct {char *name; int flag; } speed_spec;

int transfer_byte(int from, int to, int is_control);
void print_status(int fd);

void print_status(int fd) {
    int status;
    unsigned int arg;
    status = ioctl(fd, TIOCMGET, &arg);
    fprintf(stderr, "[STATUS]: ");
    if(arg & TIOCM_RTS) fprintf(stderr, "RTS ");
    if(arg & TIOCM_CTS) fprintf(stderr, "CTS ");
    if(arg & TIOCM_DSR) fprintf(stderr, "DSR ");
    if(arg & TIOCM_CAR) fprintf(stderr, "DCD ");
    if(arg & TIOCM_DTR) fprintf(stderr, "DTR ");
    if(arg & TIOCM_RNG) fprintf(stderr, "RI ");
    fprintf(stderr, "\r\n");
}

int transfer_byte(int from, int to, int is_control) {
    char c;
    int ret;
    do
    {
        ret = read(from, &c, 1);
    }
    while (ret < 0 && errno == EINTR);
    if(ret == 1)
    {
        if(is_control)
        {
            if(c == '\x01')
            { // C-a
                return -1;
            } else if(c == '\x18')
            { // C-x
                print_status(to);
                return 0;
            }
        }
        while(write(to, &c, 1) == -1) {
            if(errno!=EAGAIN && errno!=EINTR) { perror("write failed"); break; }
        }
    }
    else
    {
        fprintf(stderr, "\nnothing to read. probably port disconnected.\n");
        return -2;
    }
    return 0;
}


3. Usage


int main(int argc, char** argv)

{

    printf("Hello, CPS - let's start serial communication \r\n");
    int comfd;
    struct termios oldtio, newtio;       //place for old and new port settings for serial port
    struct termios oldkey, newkey;       //place tor old and new port settings for keyboard teletype
    char* devicename = "/dev/ttyUSB0";
    int speed = B9600;

    comfd = open(devicename, O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (comfd < 0)
    {
        perror(devicename);
        exit(-1);
    }

    tcgetattr(STDIN_FILENO,&oldkey);
    newkey.c_cflag = B9600 | CRTSCTS | CS8 | CLOCAL | CREAD;
    newkey.c_iflag = IGNPAR;
    newkey.c_oflag = 0;
    newkey.c_lflag = 0;
    newkey.c_cc[VMIN]=1;
    newkey.c_cc[VTIME]=0;
    tcflush(STDIN_FILENO, TCIFLUSH);
    tcsetattr(STDIN_FILENO,TCSANOW,&newkey);

    tcgetattr(comfd,&oldtio); // save current port settings
    newtio.c_cflag = speed | CS8 | CLOCAL | CREAD;
    newtio.c_iflag = IGNPAR;
    newtio.c_oflag = 0;
    newtio.c_lflag = 0;
    newtio.c_cc[VMIN]=1;
    newtio.c_cc[VTIME]=0;
    tcflush(comfd, TCIFLUSH);
    tcsetattr(comfd,TCSANOW,&newtio);

    // Do TX
    char c;
    c = 'a';
    write(comfd, &c, 1);
    sleep(1);

    c = 'b';
    write(comfd, &c, 1);
    sleep(1);

    c = '1';
    write(comfd, &c, 1);
    sleep(1);
    c = 'b';
    write(comfd, &c, 1);
    sleep(1);

    c = '2';
    write(comfd, &c, 1);
    sleep(1);
    c = 'b';
    write(comfd, &c, 1);
    sleep(1);

    c = '3';
    write(comfd, &c, 1);
    sleep(1);
    c = 'b';
    write(comfd, &c, 1);
    sleep(1);

    c = '4';
    write(comfd, &c, 1);
    sleep(1);
    c = 'b';
    write(comfd, &c, 1);
    sleep(1);

    // close comm port
    printf("Close port \r\n");
    tcsetattr(comfd,TCSANOW,&oldtio);
    tcsetattr(STDIN_FILENO,TCSANOW,&oldkey);
    close(comfd);

    return 0;

}