본문 바로가기
코스웨어/11년 내장형하드웨어

[내장형]박춘우_2011년 10월 17일 월요일 DailyReport

by 알 수 없는 사용자 2011. 10. 17.
728x90
반응형
Linux Serial Port Programming

Serial 은 1 bit 씩 데이터 송수신하는 통식 방식이다. 전송 속도가 느리지만 케이블이 단순하여 구현하기 쉽고 가격이 저렴하다. 이러한 Serial 통신을 리눅스에서 접근하여 통신을 해보자. 사용환경은 VMplayer 을 이용하여 리눅스를 사용하고 있으며, 윈도우의 가상 포트를 생성하여 연결하도록 한다. 가상 포트를 생성하는 방법은 추후에 다루기로 하고 우선 리눅스에서 Serial 을 접근하는 방법에 대해 알아보자.

리눅스는 장치들을 파일로 취급하며, 보통 파일 함수 (ex> open 함수) 들을 통해 읽거나 쓴다. 이러한 장치들은 /dev 디렉토리에 저장되어 있으며 Serial 의 장치 역시 /dev 저장되어 있다. Serial 포트 번호와 장치명을 살펴보면 다음과 같다.

COM1 -> /dev/ttyS0
COM2 -> /dev/ttyS1
COM3 -> /dev/ttyS2
          ...

포트번호와 장치명의 뒤의 번호가 서로 어긋나는 것을 주의하자.

터미널 인터페이스를 제어하기 위한 termios 구조체를 이용한다. termios 는 POSIX 가 지정한 표준 인터페이스이다. 구조체와 함수들은 termios.h 에 정의되어 있다. 터미널을 제어하기 위한 입력, 출력, 제어, 로컬, 특수 제어 문자 모드가 있다. 자세한 내용은 예제를 통해 살펴보도록 하고 그전에 Serial 통신을 하기 위해 기본적인 설정을 해보자.

<Serial 통신을 위한 설정>
Serial 의 장치와 터미널 인터페이스를 제어하여 Serial 통신을 할 수 있다. 이 때 Serial 통신의 프로그래밍 기법으로 크게 Canonical, Non-Canonical, Asynchronous, Multu Flexing 4 가지 방식이 있다. 차례대로 알아보자.

1. Canonical

터미널의 기본 처리 방법으로 Canonical 모드 또는 Standard 모드라고도 한다. 모든 입력이 줄 단위로 처리한다. 한 줄의 의미는 다음과 같다.

NL (New Line, ASCII는 LF)
EOF (End of File)
EOL (End of Line) 에 의해 종료되는 문자열

사용자가 Enter 를 눌러야 입력을 받아들인다. 여기서 주의 해야할 점은 Enter 문자는 리눅스에서 ASCII 에서 CR (Carrige Return) 이 아니라 LF (Line Feed) 임을 알아야 한다. 다시 말해 리눅스는 라인피드를 주의 끝으로 간주한다. 반면 MS-DOS 는  캐리지 리턴과 라인피드를 하나의 쌍으로 사용한다. 만일 입력 장치 또는 출력 장치가 캐리지 리턴도 전송하거나 요구하는 경우에는 리눅스 터미널에서 적절히 처리해 준다.

Canonical 방식을 이용한 Serial 통신을 구현해보자.

< 소스 코드 >

위의 소스코들 분석을 해보자. 전체적인 흐름을 살펴보면서 분석하도록 하자.

1) 변수 선언
2) 장치 열기
3) 현재 터미널 설정 값 저장
4) Serial 통신 설정을 위한 termios 구조체에 값을 할당 후 터미널 인터페이스 적용
5) 수신된 데이터 읽기
6) 초기의 터미널 설정으로 변경
7) 장치 닫기

실행 결과를 살펴보기 앞서 하이퍼터미널을 열어서 설정해보자.

<하이퍼터미널 설정>

실행결과를 살펴보자.

<실행 결과>


2. Non-Canonical

한 번에 정해진 크기를 처리를 한다. Canonical 는 한 라인을 처리하는 것에 비해 자유도가 크다. 타이머를 사용하여 대기 시간을 설정할 수 있다.

Non-Canonical 방식을 이용한 Serial 통신을 구현해보자.

<소스 코드>

소스 코드를 분석해보자. 대부분 앞서 분석하였던 Canonical 방식과 동일하므로 차이가 있는 부분만 분석하고 전체적인 흐름을 살펴보자. 세부 내용이 없는 부분은 Canonical 부분을 참조하도록 하자.

1) 변수 설정
2) 장치 열기
3) 현재 터미널 설정 값 저장
4) Serial 통신 설정을 위한 termios 구조체에 값을 할당 후 터미널 인터페이스 적용
5) 수신된 데이터 읽기
6) 초기의 터미널 설정으로 변경
7) 장치 닫기

하이퍼터미널은 앞서 설명하였으므로 생략하고 실행 결과를 살펴보자. 실행결과의 그림에서 하얀부분은 하이퍼터미널이며 검은부분은 리눅스 콘솔창이다. 또한 소스 코드에 [ 5) 수신된 데이터 읽기 ] 부분에 while 문으로 무한반복을 하여 테스트 하였다.

<실행 결과>


3. Asynchronous

read 의 조건이 만족될 때까지 블록되는 방식으로 대부분의 API 에 디폴트로 설정되어 있다. 호출한 프로그램에 signal 을 전송하며 전송된 signal 에서 signal handler 를 처리한다.

Asynchronous 방식을 이용한 Serial 통신을 구현해보자.

<소스 코드>

소스 코드를 분석해보자. 역시 앞에서 설명한 부분은 생략하고 다른 부분만 살펴보자.

1) 변수 설정
2) 장치 열기
3) signal 설정
4) 현재 터미널 설정 값 저장
5) Serial 통신 설정을 위한 termios 구조체에 값을 할당 후 터미널 인터페이스 적용
6) 수신된 데이터 읽기
7) 초기의 터미널 설정으로 변경
8) 장치 닫기

출력 결과를 살펴보자.

<출력 결과>


4. Multi-Flexing

여러 장치를 다루기 위해서 사용하면 유용하다. 하지만 개념이 복잡한 단점이 존재한다. select() 를 사용하여 입력을 기다리는 동안에 CPU 에 부하를 주지 않는다.

 Multi-Flexing 방식을 이용한 Serial 통신을 구현해보자.

<소스 코드>

소스 코드를 분석해보자. 장치를 여러개 사용하기 때문에 새로운 장치가 추가 할 때마다 장치를 열어주고 사용이 끝나면 닫아야한다. 터미널 설정 또한 각각 설정을 해야한다.

1) 변수 선언
2) 장치 열기
3) 현재 터미널 설정 값 저장
4) Serial 통신 설정을 위한 termios 구조체에 값을 할당 후 터미널 인터페이스 적용
5) 수신된 데이터 읽기
6) 초기의 터미널 설정으로 변경
7) 장치 닫기

테스트를 하기 전에 하이퍼터미널을 하나 더 실행해야 함을 잊지말자. 첫 번째 하이퍼터미널과 동일한 COM11 을 사용하고 두 번째 하이퍼터미널은 COM13 을 사용하면 된다. 또한 초반에 VMPlayer 설정이 되어있어야 한다. 설정 방법은 앞서 설명하였으므로 생략한다.

실행 결과는 다음과 같다.

<실행 결과>

728x90