IT_Programming/System Programming

[펌] 리눅스에서 시리얼 제어 하기

JJun ™ 2009. 9. 30. 20:12

/* 리눅스에서 시리얼 제어 하기 (출처 : http://2mr.mju.ac.kr/zbxe/) */
  
#include <termios.h>   // 터미널 제어 해더파일
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <sys/types.h>

 

#define BAUDRATE B38400   // 38400 baudrate
#define MODEMDEVICE "/dev/ttyS0" // 시리얼 포트 정의 (ttyS0 : com1, ttyS1 : com2)

#define TRUE 1
#define FALSE 0

 

main()
{
    int fd,i,stop;
    int res;
    struct termios oldtio, newtio;  

    unsigned char buf[255];
    unsigned char recieve;
 
    /* 시리얼 장치 open */
    fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NDELAY);

    if(fd<0)
    { 
        perror(MODEMDEVICE);
        exit(-1);
    }
 
    /* file descriptor를 비동기로 만든다 */
    fcntl(fd, F_SETFL, FASYNC);
 
    /* 현재 포트 플래그를 oldtio에 저장 */
    tcgetattr(fd, &oldtio);
 
    /* 포트 플래그를 세팅 */
    /*

        c_cflag(제어 모드 플래그)
        BAUDRATE : 전송 속도
        CRTSCTS  : 하드웨어 흐름 제어 (시리얼 케이블이 모든 핀에 연결되어 있을 경우 사용
        HUPCL    : 마지막 프로세스가 장치를 닫은 후에 접속을 닫음
        CS8      : 8bit data (no parity, 1 stopbit)
        CLOCAL   : Local connectio. 모뎀 제어를 안함
        CREAD    : 수신을 가능하게 함
    */ 
    newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD; 

    /*

        c_iflag(입력 모드 플래그)
        IGNBRK   : 입력에서 break 조건을 무시
        BRKINT   : IGNBRK가 설정되면 break에서 SIGINT를 생성
        INLCR    : 입력에서 NL을 CR로 변환
        IGNCR    : 입력에서 CR을 무시
        ICRNL    : IGNCR이 설정되지 않으면 입력에서 CR을 NL로 변환
    */
    newtio.c_iflag = IGNPAR | ICRNL;
  

    /*

        c_oflag(출력 모드 플래그)
        onLCR    : 출력에서 NL을 CR-NL로 맵핑
        OCRNL    : 출력에서 CR을 NL로 맵핑
        ONLRET   : CR을 출력하지 않음
    */
    ne
wtio.c_oflag = 0;

    /*

        c_lflag(지역 모드 플래그)
        ISIG     : INTR, QUIT, SUSP 문자가 수신될 때 각각 SIGINT, SIGQUIT, SIGSTP을 생성
        ICANON   : 정규 모드를 사용
        ECHO     : 입력 문자를 출력으로 반향
        ECHONL   : ECHO가 설정되지 않더라도 정규 모드에서 NL문자를 반향
    */
    newtio.c_lflag = 0;

    /*

        c_cc[](제어 문자)
        밑의 설정 빼고는 default로 설정되어 있음(참고파일 : sys/ttydefaults.h)
    */
    newtio.c_cc[VMIN] = 1;   // 1 문자 받을때까지 blocking
    newtio.c_cc[VTIME] = 0;  // 문자 사이의 delay 0

 

    /* 포트를 초기화 */ 
    tcflush(fd, TCIFLUSH);
   

    /* 포트를 세팅 */
    tcsetattr(fd, TCSANOW, &newtio);

   

    for(i=0;i<255;i++)
        buf[i] = 0;

 

    stop = FALSE; 

 

    while(1)
    {
        res = read(fd, &recieve, 1); // 읽기 시작. recieve변수에 데이터가 들어옴.

                                             // 데이터 갯수를 res변수로 리턴
        if(res < 1)
            printf("read error!\n");
  
        switch(recieve)
        {
            case 0:
                buf[0] = 0x11;
                if(write(fd, buf, 1) < 1)     // 쓰기 시작. buf배열의 데이터가 출력.

                    printf("write error!\n"); // 출력된 데이터의 갯수가 리턴됨

                break;

 

           case 1:
                buf[0] = 0x22;
                if(write(fd, buf, 1) < 1)
                    printf("write error!\n");
                break;

 

           case 2:
                buf[0] = 0x33;
                if(write(fd, buf, 1) < 1)
                   printf("write error!\n");
                break;
  
           case 3:
                buf[0] = 0xff;
                if(write(fd, buf, 1) < 1)
                    printf("write error!\n");
    
                stop = TRUE;
                break;

 

          default:
                break;
        }

 

        if(stop == TRUE)
            break;
    }
    tcsetattr(fd, TCSANOW, &oldtio); //처음 설정으로 다시 세팅
    close(fd); //시리얼 포트를 닫음 
}

serial(Linux).c
0.0MB