1. 개요
이문서는 RS485통신이나 모뎀 제어시에 사용되는 RTS 제어에 대한 소스의 예를 보여주는 문서입니다.
2. RS485
RS485 통신은 전송 라인을 2 선만을 사용하는 방식이고 2선식의 특성상 송신과 수신이 동시에 이루어질 수 없습니다.
송신시에는 수신이 불가능하고 수신시에는 송신이 불가능하므로 통신상에서는 마스터와 슬레이브 개념을 사용하여
마스터가 송신을 하고 이에 대한 수신을 처리하는 방식으로 프로그램을 하고있습니다.
하드웨어는 송신시에 송신 드라이버를 열고 그외에는 송신 드라이버를 닫습니다.
또한 송신 드라이버를 열었을때는 수신 드라이버를 닫으며 수신 드라이버를 열때는 송신 드라이버를 닫습니다.
송신 드라이버와 수신 드라이버가 동시에 열릴수 없는 구조가 되는 것입니다.
이렇게 송신 드라이버와 수신 드라이버의 열고 닫음을 하드웨어적으로 구현할 때 RTS 신호를 이용하게 설계합니다.
그러므로 RS485 통신을 리눅스 프로그램상에서 하려면 이에 대한 제어를 해야하는데 의외로 이에 대한 자료가 부족한
형편입니다. 물론 시리얼 디바이스의 소스를 수정하여 이에 대한 제어를 할수도 있지만 그리 쉬운 작업이 아니지요.
이 강좌에서는 어플리케이션 단에서 이를 어떻게 처리하는지에 대한 간단한 샘플 소스를 정리한 것입니다.
3. 조건
이 소스는 이지보드의 시리얼 확장보드를 사용한 예입니다.
4. 소스
#include #include #include #include #include #include #include
#include #include
#include #include #include
nt main( int argc, char **argv ) {
int fd,c, res; struct termios oldtio,newtio; char buf[255];
int modemctlline; int txemptystate;
// 시리얼 장치를 연다. fd = open( "/dev/ttySS0", O_RDWR | O_NOCTTY ); if (fd <0) { // 화일 열기 실패 printf( "Device OPEN FAIL\n"); return -1; }
// 통신 환경를 설정한다. tcgetattr(fd,&oldtio); // 현재 설정을 oldtio에 저장
memset(&newtio, 0, sizeof(newtio)); newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD ; newtio.c_iflag = IGNPAR; newtio.c_oflag = 0;
// set input mode (non-canonical, no echo,...) newtio.c_lflag = 0;
// 다음 두라인은 통신 방식에 따라서 다르게 설정하여야 한다. newtio.c_cc[VTIME] = 0; // 문자 사이의 timer를 disable newtio.c_cc[VMIN] = 5; // 최소 5 문자 받을 때까진 blocking tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio);
// 현재 설정된 모뎀 제어 레지스터를 읽는다. ioctl( fd, TIOCMBIS, &modemctlline);
// RTS를 HIGH로 만든다. modemctlline = TIOCM_RTS; ioctl( fd, TIOCMBIS, &modemctlline );
// 데이타를 출력한다. memset( buf, c, 32 ); buf[32]=0; write( fd, buf, 32 ); printf( "DATA : [ %s ]\n", buf);
// 모든 데이타가 전송되어 완전하게 버퍼가 // 비워질때까지 대기한다. while( 1 ) { ioctl( fd, TIOCSERGETLSR, &txemptystate); if( txemptystate ) break; }
// RTS를 LOW로 만든다. modemctlline = TIOCM_RTS; ioctl( fd, TIOCMBIC, &modemctlline );
// 잠시 대기한다. sleep(1);
// 데이타를 읽는다. res = read(fd,buf,255); buf[res]=0; printf("%s:%d\n", buf, res);
// 통신상태를 원 위치한다. tcsetattr(fd,TCSANOW,&oldtio);
close( fd ); return 0; }
출처 : http://www.falinux.com/win/study/09/rs485.html
|
port 기반의 Inernet Domain Socket에 비해서 로컬 시스템의 파일시스템을
이용해서 내부프로세스간의 통신을 위해 사용한다는 점이 다르다고 할수 있다.
ls 를 이용해서 통신을 위해서 만들어진 파일을 보면 다음과 같은 모습을
보인다.
[yundream@localhost tmp]$ ls -al |
보면 파일타입에 "s" 가 붙어 있는걸 알수 있으며, 파일사이즈가 0으로 되어 있는
걸 알수 있다. 왜냐하면 FIFO와 마찬가지로 메시지가 파일로 쌓이지 않고
커널로 전달되어서 커널에서 처리하기 때문이다.
파일을 통해서 통신을 하며, 커널내부에서 메시지를 관리한다는 점에서
FIFO와 매우 유사한면을 보여주지만, FIFO와는 달리 양방향 통신이 가능하다는
특징을 가지고 있다. 그러므로 다중의 클라이언트를 받아들이는 서버/클라이언트
모델을 만들기가 매우 쉽다.
또한 Inet 소켓을 통한 외부통신에 비해서 2배 이상의 효율을 보여준다라는
장점을 가지고 있다.
많은 경우 약간 복잡한 내부프로세스간 통신을 해야된다고 했을때 UDS을 많이
사용한다. INET 계층에서의 통신이 TCP/IP 4계층을 모두 거치는것과는
다르게, UDS 은 어플리케이션 계층에서 TCP 계층까지만 메시지가 전달되고,
다시 곧바로 어플리케이션 계층으로 메시지가 올라가게 된다. TCP/IP 계층에 대한
자세한 내용은 TCP/IP 개요(2)를 참고 하기 바란다.
위에서 INET 소켓보다 2배이상의 효율을 가진다고 했는데,
4계층의 레이어를 모두 거쳐야하는 INET 소켓에 비해서 단지 2개의 레이어만
사용한다는 점도 그 이유중 하나로 작용한다.
쏘쓰 코드는 다중연결서버 만들기(1)의 zipcode_multi.c 와
셈플로 알아보는 소켓프로그래밍(1)의 zipcode_cli.c 를 사용하도록할것이다.
예제: zipcode_local.c
#include |
다음은 클라이언트 프로그램이다.
예제: zipcode_cli_local.c
#include |
기존의 INET 버젼의 프로그램과 비교해 보면 고작 3줄 정도만 수정되었음을
알수 있을것이다. 단지 소켓 구조체가 sockaddr_un 으로 바뀌고,
AF_INET 대신 AF_UNIX 를 그리고 port 번호대신에 파일명을 사용했음을
알수 있다.
나머지의 모든 코드는 INET 코드와 완전히 같다. 그러므로
Unix Domain Socket 를 사용하면 Inet Domain Socket 와 코드 일관성을
유지할수 있으며, 동일한 기술을 사용해서 프로그래밍을 할수 있다.
또한 다른 대부분의 IPC 설비들이, 범용적으로 사용하기에는 부족한 여러가지
단점들을 가진반면(단방향 이거나, 읽기만 가능하다거나, 제어하기가 어려운)
UDS는 매우 범용적인 IPC 로써 사용가능하다라는 장점을 가지고 있다.
실제로 X 서버 같은경우에 외부에서의 접근시에는 INET 연결을 내부에서의
연결을 위해서는 UDS 를 사용한다. 이밖에도 mysql, pgsql, KDE, Gnome 과 같은
대부분의 서버프로그램이 내부통신을 위해서 UDS 를 사용한다.
이 글과 관련있는 글을 자동검색한 결과입니다 [?]

Add New Comment