티스토리 뷰
목차
반응형
리눅스 Linux 간단한 시리얼 통신 프로그램 예제 소스
윗분이 알려주신 사이트로 이동해 봅시다. 정말 작고 간단한 Linux 시리얼 통신 프로그램 사이트가 보입니다.
바로 가기 - Tiny serial terminal [링크]
이동하면 아래와 같은 글이 보입니다.
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]
간단한 사용 방법에 대한... 즉, 시리얼 통신 프로그램 메뉴얼에 해당합니다.
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}, {NULL, 0} }; 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, NULL, NULL, NULL); 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 간단한 시리얼 통신 프로그램 예제 소스
반응형