코드만 한번 봐주세요..
이 코드는
/dev/ttyS0에서 쓴 데이터를 /dev/ttyS1에서 읽어 파일에 쓰는
코드입니다.
한번 보시고 문제될 만한 부분이 있는지 봐주세요..
먼저, ttyS0에 쓰는 코드는 다음과 같습니다.
buff에는 '0', '1', '3', '4', ... '9', 'CR', 'LF' 이렇게 해서 데이터를 넣었습니다.
/****************************** * "/dev/ttyS0" * RS232 interface write Data. ******************************/ #include <stdio.h> #include <unistd.h> #include <termios.h> #include <fcntl.h> #include <errno.h> #include "serial.h" #include "buf.h" int serial_open(const char *device, int baud, int flow) { int fd; static long baudrate; struct termios tio; fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK , 0644); if(fd < 0) { dbg("Can't open device %s\n", device); return -1; } else { dbg("Open %s Device, fd %d : \n", device, fd); bzero(&tio, sizeof(tio)); switch(baud) { case 9600: baudrate = B9600; break; case 115200: baudrate = B115200; break; case 19200: baudrate = B19200; break; default : dbg("Can't define %d\n", baud); close(fd); exit(0); } /* end switch */ tio.c_cflag &= ~CSIZE; tio.c_cflag |= CS8; /* 8 data bit */ tio.c_cflag &= ~CSTOPB; /* 1 stop bit */ tio.c_cflag &= ~(PARENB | PARODD); /* no parity bit */ if(flow){ tio.c_cflag |= CRTSCTS; /* h/w flow control */ } else{ tio.c_cflag &= ~CRTSCTS; /* no flow control */ } if((cfsetispeed(&tio, baudrate) < 0 || cfsetospeed(&tio, baudrate) < 0)){ /* baudrate set */ dbg("Can't set baudrate\n"); close(fd); return -1; } else { if(tcsetattr(fd, TCSANOW, &tio) < 0){ /* termios set */ dbg("Can't set Termios struct\n"); close(fd); return -1; } else { if(tcflush(fd, TCIOFLUSH) < 0){ close(fd); return -1; } } } } return fd; } int serial_write(int fd, char *buf, int size) { int t = 0; int ones; int writesize; writesize = size; while(writesize > 0) { ones = write(fd, buf, writesize); if(ones <= 0) { if(!(errno == EINTR || errno == EAGAIN)){ dbg("Error write serail : %d\n", errno); break; } } else { buf += ones; writesize -= ones; t += ones; } } return t; } int usage(const char *device) { printf("serial_write - RS232 write Data. copyright(c)2003 by leolo\n"); printf("description : RS232(%s) write data\n", device); printf("serial_write baudrate <flow/none> byte count time\n"); exit(0); } int main(int argc, char *argv[]) { int baud; int flow; int fd; int n; const char *device = "/dev/ttyS0"; int size; int tdata = 0; int cnt; int time; if(argc != 6) usage(device); baud = atoi(argv[1]); if(strncmp(argv[2], "flow", 4) == 0) flow = 1; /* h/w flow control */ else flow = 0; /* no flow control */ size = atoi(argv[3]); cnt = atoi(argv[4]); time = atoi(argv[5]); fd = serial_open(device, baud, flow); while(cnt){ usleep(time*1000); n = serial_write(fd, buf, size); tdata += n; dbg("Send data total %d\n", tdata); cnt--; } close(fd); return 0; }
읽고 파일에 쓰는 코드는 다음과 같습니다.
/****************************** * "/dev/ttyS1" * RS232 interface read Data. ******************************/ #include <stdio.h> #include <unistd.h> #include <termios.h> #include <fcntl.h> #include <errno.h> #include "serial.h" int serial_open(const char *device, int baud, int flow) { int fd; static long baudrate; struct termios tio; fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK , 0644); if(fd < 0) { dbg("Can't open device %s\n", device); return -1; } else { dbg("Open %s Device, fd %d : \n", device, fd); bzero(&tio, sizeof(tio)); switch(baud) { case 9600: baudrate = B9600; break; case 115200: baudrate = B115200; break; case 19200: baudrate = B19200; break; default : dbg("Can't define %d\n", baud); close(fd); exit(0); } /* end switch */ tio.c_cflag &= ~CSIZE; tio.c_cflag |= CS8; /* 8 data bit */ tio.c_cflag &= ~CSTOPB; /* 1 stop bit */ tio.c_cflag &= ~(PARENB | PARODD); /* no parity bit */ tio.c_cflag |= CREAD; if(flow){ tio.c_cflag |= CRTSCTS; /* h/w flow control */ } else{ tio.c_cflag &= ~CRTSCTS; /* no flow control */ } if((cfsetispeed(&tio, baudrate) < 0 || cfsetospeed(&tio, baudrate) < 0)){ /* baudrate set */ dbg("Can't set baudrate\n"); close(fd); return -1; } else { if(tcsetattr(fd, TCSANOW, &tio) < 0){ /* termios set */ dbg("Can't set Termios struct\n"); close(fd); return -1; } else { if(tcflush(fd, TCIOFLUSH) < 0){ close(fd); return -1; } } } } return fd; } int serial_write(int fd, char *buf, int size) { int t = 0; int ones; int writesize; writesize = size; while(writesize > 0) { ones = write(fd, buf, writesize); if(ones <= 0) { if(errno == EINTR || errno == EAGAIN){ dbg("Error write serail : %d\n", errno); exit(0); } } else { buf += ones; writesize -= ones; t += ones; } } return t; } int serial_read(int fd, char *buff, int size) { fd_set rfds; int filefd; int result, isread, readsize; char buffer[2048]; filefd = open("./serial.out", O_RDWR | O_CREAT | O_TRUNC, 0644); while(1){ FD_ZERO(&rfds); FD_SET(fd, &rfds); printf("select pending\n"); result = select(fd + 1, &rfds, (fd_set *)0, (fd_set *)0, NULL); if(result <= 0){ dbg("select error\n"); exit(0); } isread = FD_ISSET(fd, &rfds); if(result > 0 && isread != 0){ memset(buffer, '\0', sizeof(buffer)); readsize = read(fd, buffer, size); if(readsize > 0) { printf("read data %d byte -> %s\n", readsize, buffer); write(filefd, buffer, readsize); } else { if(readsize <= 0){ dbg("Can't read\n"); exit(0); } break; } } else { close(filefd); break; } } return -1; } int main(int argc, char *argv[]) { int baud; int flow; int fd; int n; char *buf; const char *device = "/dev/ttyS1"; int size = 2048; bzero(buf, sizeof(buf)); flow = 0; /* h/w flow control */ baud = 9600; /* baud rate */ fd = serial_open(device, baud, flow); n = serial_read(fd, buf, size); close(fd); return 0; }
/dev/ttyS0에 쓰는 코드를 보시면,
일정한 간격으로 usleep하면서 쓰고 있습니다.
이렇게 하면 일정한 간격으로 데이타가 써지는지 알고 싶습니다.
다음으로 읽고 파일(serial.out)에 쓰는 코드가 정확한지 알고 싶습니다.
위와 같이 코드를 짜고 돌리면.. 잘 돌아갑니다.
아무 문제 없이.. 그런데.. 한가지 의문이 있습니다.
baud rate를 9600으로 한 것과 115200으로 한 것이 차이가 납니다.
물론, 당연히 나겠죠..
./serial_write 9600 none 20000 10 1000 으로 실행하면, 즉, 9600, none flow control, 2000byte, 10번, 1000(1초) 간격으로 쓰는거와.
115200으로 쓰는 것의 차이가 좀 이상합니다.
9600은 중간에 데이터가 손실 되는데.. 115200은 중간에 데이터 손실이 없습니다. 참고로, 저는 이것을 무선 통신을 통해 데이터를 전송했습니다.
baud rate가 정확히 어떻게 동작하는지.. 알고 싶습니다.
한가지 더 질문 드립니다.
struct termios tio;
static long baudrate;
bzero(&tio, sizeof(tio));
.....
tio.c_cflag |= B115200;
....
이렇게 세팅하고..
올바른지 확인하기 위해..
printf("%d\n", cfgetispeed(&tio))
이렇게 하고 찍어보니까? 4098이 나오네요..
원래 이런건가요.. 제대로 된건지.. 통.. 모르겠네요..
실력이 있으면 삶이 편하다... 영차 영차...
Re: 코드만 한번 봐주세요..
다음 2가지가를 고려해봅니다.
1) 9600bps에서 최대 CPS(초당 전송 문자수)를 고려보셨나요? DTE수준에서 압축프로토콜등을 지원한다면 모르지만, 2000바이트라......
2) 읽을때는 select()를 사용하여 이벤트에 기반해서 프로그램했는데, 쓸때도 해보심이 좋을 듯 합니다..
------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.
댓글 달기