티스토리 뷰

목차

    반응형

    리눅스 Linux 간단한 시리얼 통신 프로그램 예제 소스



    윗분이 알려주신 사이트로 이동해 봅시다. 정말 작고 간단한 Linux 시리얼 통신 프로그램 사이트가 보입니다.



    이동하면 아래와 같은 글이 보입니다.


    Download : com.c [링크]

    Building : cc -o com com.c

    Usage   : ./com /dev/device [speed]

    Example : ./com /dev/ttyS0 [115200]

    Keys    : Ctrl-A - exit, Ctrl-X - display control lines status


    Tiny serial terminal - 실행 화면[Tiny serial terminal - 실행 화면]


    Tiny serial terminal[Tiny serial terminal]

    간단한 사용 방법에 대한... 즉, 시리얼 통신 프로그램 메뉴얼에 해당합니다. 

    Linux 전용 소스 전문을 살펴봅시다.


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    #include <termios.h>
    #include <stdio.h>
    #include <stdlib.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>
     
    int transfer_byte(int from, int to, int is_control);
     
    typedef struct {char *name; int flag; } speed_spec;
     
     
    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 main(int argc, char *argv[])
    {
        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 = argv[1];
        int need_exit = 0;
        speed_spec speeds[] =
        {
            {"1200", B1200},
            {"2400", B2400},
            {"4800", B4800},
            {"9600", B9600},
            {"19200", B19200},
            {"38400", B38400},
            {"57600", B57600},
            {"115200", B115200},
            {NULL0}
        };
        int speed = B9600;
     
        if(argc < 2) {
            fprintf(stderr, "example: %s /dev/ttyS0 [115200]\n", argv[0]);
            exit(1);
        }
     
        comfd = open(devicename, O_RDWR | O_NOCTTY | O_NONBLOCK);
        if (comfd < 0)
        {
            perror(devicename);
            exit(-1);
        }
     
        if(argc > 2) {    
            speed_spec *s;
            for(s = speeds; s->name; s++) {
                if(strcmp(s->name, argv[2]) == 0) {
                    speed = s->flag;
                    fprintf(stderr, "setting speed %s\n", s->name);
                    break;
                }
            }
        }
     
        fprintf(stderr, "C-a exit, C-x modem lines status\n");
     
        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);
     
        print_status(comfd);
     
        while(!need_exit) {
            fd_set fds;
            int ret;
            
            FD_ZERO(&fds);
            FD_SET(STDIN_FILENO, &fds);
            FD_SET(comfd, &fds);
     
     
            ret = select(comfd+1&fds, NULLNULLNULL);
            if(ret == -1) {
                perror("select");
            } else if (ret > 0) {
                if(FD_ISSET(STDIN_FILENO, &fds)) {
                    need_exit = transfer_byte(STDIN_FILENO, comfd, 1);
                }
                if(FD_ISSET(comfd, &fds)) {
                    need_exit = transfer_byte(comfd, STDIN_FILENO, 0);
                }
            }
        }
     
        tcsetattr(comfd,TCSANOW,&oldtio);
        tcsetattr(STDIN_FILENO,TCSANOW,&oldkey);
        close(comfd);
     
        return 0;
    }
     
     
    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;
    }
    cs


    다시 정리하면, 


    1
    2
    3
    $ gcc -o com com.c (컴파일)
     
    $ ./com /dev/ttyUSB0 115200 (실행)
    cs


    일반적인 리눅스 gcc를 이용하면 됩니다.

    시리얼 통신 프로그램을 실행할 땐, Baudrate를 인자로 넘겨주면 됩니다. 그렇지만 하나 아쉬운 게 있는데요. Linux 환경에선 캡쳐가 안 되기에 원래 글을 쓰셨던 분은 아래처럼 수정하셨습니다.


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    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;
                }
            }
     
            /*
             * send also to stdout.
             */
            if(to == STDIN_FILENO)
            {
                while (write(STDOUT_FILENO, &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;
    cs


    이정도로 간단한 Serial 통신 프로그램 소개합니다. 짧은 소스지만 핵심 부분은 모두 들어가서 간단한 테스트 용도로는 모자람이 없습니다.


    리눅스 Linux 간단한 시리얼 통신 프로그램 예제 소스

    반응형