#include 전처리기 지시어

ex)

#include<filename> //표준 라이브러리 헤더 파일

#include"filename" //사용자 정의 헤더파일


#define 전처리기 지시어 : 기호 상수

ex)

#define 식별자  치환텍스트

#define PI 3.14159


#define 전처리기 지시어 : 매크로

ex)

#define CIRCLE_AREA(x) (PI*(x)*(x))


조건부 컴파일

#ifndef NULL //널이 정의 되지 않았다면

    #define NULL 0 //NULL을 0으로 정의

#endif //조건 디파인 종료

ex)

#if 0

    컴파일이 되지 않는 코드

#endif //주석처럼 사용 가능


#error 지시어

는 지시어에 지정된 토큰들을 포함한 시스템 구현에 의존적 메시지를 인쇄한다

ex)

#error 1 - Out of range error //#error지시어가 처리 될때 지시어에 있는 토큰들이 오류메시지로

                                        //표시되고 전처리가 중단되고, 프로그램은 컴파일 되지 않는다

#pragma 지시어

는 구현에 정의된 동작을 한다


#연산자

는 치환 텍스트 토큰을 큰따옴표로 둘러싸인 문자열로 변환

ex)

#define HELLOR(x) cout<<"Hello, " #x<<endl;

HELLO(John)은 cout<<"Hello, " "John"<<endl;로 치환됨

##연산

기호는 두개의 토큰을 연결한다

ex)

#define TOKENCONCAT(x, y) x ## y

TOKENCONCAT(O, K)는 프로그램에서 OK로 치환됨


#line 전처리기 지시어

는 뒤이어 나오는 소스 코드 줄번호를 지정된 상수 정수 값에서 시작하여 번호가 매겨지도록 함

ex)

#line 100 //다음 소스코드 줄 번호를 100부터 시작하도록


미리 정의된 기호 상수

_LINE_    현재 소스 코드 줄의 줄번호

_FILE_    소스 파일의 추정되는 이름

_DATA_    소스 파일이 컴파일된 날짜

_STDC_    프로그램이 ANSI C표준을 따르는지

_TIME_    소스 파일이 컴파일된 시간

_TIMESTAMP_    소스 파일의 최종 변경 날짜와 시간

참조 : http://www.whiteat.com/zbxe/4848



기본 지식

 

1. 병렬포트의 구조

프린트포트01.JPG
                    
그림 1 프린터 포트의 외형도



1, 14, 16, 17번은 input도 되고 output도 된다는 것을 알 수 있다.





그래서 여기서는 1, 14, 16, 17번은 사용을 안 하기로 한다.


OUTPUT

2, 3, 4, 5, 6, 7, 8, 9

INPUT

10, 11, 12, 13, 15

IN/OUT

1, 14, 16, 17

GND

18, 19. 20, 21, 22, 23, 24, 25

                           1 프린터 포트의 핀 종류



2. 병렬포트의 출력

병렬 테스트를 하기 위해 간단히 회로를 꾸며 보자.  아래의 회로도처럼 꾸민다.

프린트포트02.JPG

그림 2 프린터 포트 입력 테스트를 위한 회로도

회로도가 완성되면, PC 쪽에서 프린터 포트를 제어 해야 한다.

VC++를 사용해서 제어 하겠다. (C 보다는 VC++ 이 편하다.)

Dialog Based 로 한 다음, 버튼을 하나 만들고, 그 버튼 메시지 아래와 같은 코드를 입력

for(int i=0;i<256;i++)  {

_outp(0x378,i);

for(int j=0;j<10000;j++);

} 

그리고 버튼을 누르면  병렬포트에 연결시켰던 LED들이 우르르~ 켜지는 것을 볼 수 있다.

(하지만, win2000 이상에서는 잘 안될 것이다.)

그래서 다른 방법을 써야 한다.  라이브러리를 사용해야 한다.

라이브러리를 사용하면  2000 이하의 버전에서도 사용이 가능하므로, 라이브러리를 사용해서 하는게 좋을 것이다. (나중에 자세히 설명한다.)

 

파일은 자료실에 있다.

     _outp(0x378,i); 함수에서,

0x378 LPT1일때 즉 프린터포트의 주소이고,  그 뒤의 값은 데이터 값이다.

, 2번부터 9번까지(Data0 부터 Data7까지)데이터를 출력해 준다.

예를들어,  _outp(0x378,9)라고 했다면,
9 2진수로 1001이므로 2번핀과 5번핀이 HIGH 로 된다.



cf. 라이브러리를 이용한 제어

http://www.driverlinx.com/ 에 자세한 설명이 있고,

라이브러리를 제작, 배포하는 곳이다. 다운 받으려면 가입을 해야 하지만

http://www.driverlinx.com/DownLoad/DlPortIO.htm 여기에서 그냥 받을 수 있다.

또는 자료실 (http://rtcontrol00.ee.hallym.ac.kr ) 에 있다.

 

port95nt.exe Port I/O Driver (1,573k)

를 다운 받아 설치한다. 다 끝나면 (꼭 리붓을 해야 한다.)

프린트포트03.JPG

그림 3 생성된 단축 아이콘



그림의 C++ PortIO 를 실행하면

프린트포트04.JPG    프린트포트05.JPG                  

그림 4 실행초기 화면                   

그림 5 프린터 포트를 쓰는 화면

프린터 포트를 쓰는 그림에서 Write 를 누르면 프린터 포트에 데이터를 쓰는 것이다.

0x378 은 프린터 포트를 쓰는 주소이고, 0은 데이터 이다.

즉 프린터 포트에 0을 쓰는 것이다.

값을 읽을 때에는 Read 를 누르면 된다.

일단 여기서 에러 없이 잘 되면, 프린터 포트 제어에 문제가 없는 것이다.

이제 자신의 코드를 만들어 보자. VC6.0++ 을 이용하겠다.


VC++로 라이브러리 추가하여 프로그램 짜기

다이러로그 방식으로 프로그램을 짜서 버튼을 만들고 메시지를 연결한다.

라이브러리를 연결해야 하는데,

우선, 라이브러리를 사용할 폴더로 복사한다. [ Dlportio.h 파일과 Dlportio.lib 파일 ]

프린트포트06.JPG

설치된 폴더에서 API 폴더에 있다.

 

그리고, 라이브러리를 연결하고, 헤더파일을 추가한다.

(VC++ 에 대한 설명은 생략한다.)

 

그리고 코드를 연결한다.

 

void CPTESTDlg::OnButton1() {

             for(int i=0;i<256;i++)  {

                           DlPortWritePortUchar(0x378,i);

                           Sleep(1);

             }           

}DlPortWritePortUchar() 함수는 포트에 값을 쓰는 함수이다.

함수를 알아보려면 Dlportio.h 를 열어 보기 바란다.(절대 수정하지는 말고 ^^;; )

 

그리고 버튼을 누르면 LED 가 빠르게 깜빡거릴 것이다.


dlportio.h 파일을 보면 다음과 같은 함수가 있다.

<Read 함수>
DlPortReadPortUchar(IN ULONG Port);
DlPortReadPortUshort(IN ULONG Port);
DlPortReadPortUlong(IN ULONG Port);
DlPortReadPortBufferUchar(IN ULONG Port,IN PUCHAR Buffer,IN ULONG Count);
DlPortReadPortBufferUshort(IN ULONG Port,IN PUSHORT Buffer,IN ULONG Count);
DlPortReadPortBufferUlong(IN ULONG Port,IN PULONG Buffer,IN ULONG Count);

<Write 함수>
DlPortWritePortUchar(IN ULONG Port,IN UCHAR Value);
DlPortWritePortUshort(IN ULONG Port,IN USHORT Value);
DlPortWritePortUlong(IN ULONG Port,IN ULONG Value);
DlPortWritePortBufferUchar(IN ULONG Port,IN PUCHAR Buffer,IN ULONG Count);
DlPortWritePortBufferUshort(IN ULONG Port,IN PUSHORT Buffer,IN ULONG Count);
DlPortWritePortBufferUlong(IN ULONG Port,IN PULONG Buffer,IN ULONG Count);

 

뒤에 붙은 char(1byte), short(2byte), long(4byte) 은 데이타 타입이다.

자주 사용하는 함수는  DlPortReadPortUchar(), DlPortWritePortUchar() 이고, 바이트 단위로 통신하는 것이다
.
 

이제부터 라이브러리를 사용한다고 가정하고 설명하겠다.



3. 병렬포트의 입력

parallel port를 통해 입력을 받아보기 위해 회로를 꾸미자.

 

프린트포트07.JPG

그림 6 입력과 출력 회로도

주의 사항

최상위 비트는 11번이다.

11,10,12,13,15번 순이다. 주의 요

 

입력 버튼을 만들고, 코드를 넣자.

void CPTESTDlg::OnButton2() {

             int a=DlPortReadPortUchar(0x379);

             m_strData.Format("%x",a);

             UpdateData(FALSE);

}

 

테스트를 해 보면 11(최상위) 핀은 반전되어서 나오는 것을 알수 있다.

( 뒤쪽의 3비트는 I/O 공동으로 사용한 데이터 같은데 뭔지 모르겠음)

입력 값

PC 에서 읽은 값

1111 1XXX

0111 1XXX

0000 0XXX

1000 0XXX

1010 1XXX

0010 1XXX

0110 0XXX

1110 0XXX



실시간으로 프린트 포트로부터 입력 받기

약간의 C++ 지식이 필요하다.

일단 소스를 보면

void CPTESTDlg::OnButton2() {

        // 실시간으로 프린터 포트의 입력 값을 읽어서 화면에 보여줌

             while(1){

                           MSG msg;

                           while(::PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)){

                                        switch(msg.message){

                                        case WM_QUIT:

                                        case WM_DESTROY:

                                        case WM_CLOSE:

                                                     PostQuitMessage(0);

                                                     return ;

                                        }

                                        ::TranslateMessage(&msg);

                                        ::DispatchMessage(&msg);

                           }

                          

                           int a=DlPortReadPortUchar(0x379);

                           m_strData.Format("%x",a);

                           UpdateData(FALSE);

             }

}

그리고 종료 할 때,

PostQuitMessage(0);

를 꼭 해주어야 한다. 그렇지 않으면 리소스를 반납하지 않기 때문에, PC 가 느려진다.

 

꼭 리소스가 제대로 반납되는지 확인 하기 바란다.




<참고> ECP , EPP 모드에 관해

하이텔 :신동익  (kbread  )님께서 쓰신 글입니다.

안녕하세요.
프린터포트로 뭔가를 하려는 분이 많이 계신가본데,제가 얼마 전에 인터넷에서
자료를 좀 구했습니다.

보통 centronics라고 불리우는 일반적인 프린터 포트 방식으로는 4bit의 데이타를 그것도 출력으로만 사용할 수 있지요.

최근에는 외장 하드디스크나 zip drive 등 대용량, 고속으로 동작하는 외부기기를 프린터포트에 접속하여 사용하는 경우가 늘고 있습니다. 따라서 병렬포트(프린터 포트보다 치기가 쉬워서)도 기존의 규격으로는 부족한 감이 있지요.

그래서 기존의 모드를 그대로 지원하면서, 고속의 확장모드를 지원할 수 있도록  새로운 규격의 병렬포트가 등장한 겁니다. 이른바 EPP, ECP라는 것 말입니다.

EPP Enhanced Parallel Port의 약자로서 프린터를 제외한 고속, 대용량(외장 하드, 캐너 등)의 외부기기를 지원하는 모드입니다. 8bit의 데이타 버스를 양방향으로 이용할 수 있습니다.

ECP Extended Compatibility Port의 약자로서 프린터로의 데이타 전송을 고속화 하려는 목적으로 고안된 것입니다. 마찬가지로 8bit의 양방향 통신을 할 수 있습니다. 최근의 레이저 프린터들은 대개 이 모드를 지원합니다.

또한 이러한 모드를 이용하기 위해서는 PC에 이 모드를 지원하는 병렬포트가 장착되어 있어야 하는데, PC의 부팅 시 cmos setup에 들어가서 지원여부를 확인할 수 있습니다. setup menu에서 communication port쪽을 살펴보면, com1은 어쩌구, com2는 저쩌구, lpt1은 어쩌구 에서 LPT부분의 메뉴를 변경해 보면 normal, ECP, EPP, ECP+EPP등이 나타나면 이게 지원되는 보드입니다.

ECP 모드에서의 전송 속도는 500Kbyte/sec에서 최대 2MByte/sec까지 가능합니다.
이 정도의 속도라면 보통 ISA bus에 인터페이스 한 것과 거의 대등한 속도라고 봅니다. 그리고 프로토콜도 매우 간단해서 프린터포트 인터페이스를 해 보신 분이라 면 누구나 쉽게 할 수 있습니다.

보다 자세한 규격은 인터넷주소 http://www.fapo.com/ieee1284.htm에 있습니다.
참고로 ECP, EPP를 지원하는 병렬포트 규격을 IEEE1284라 합니다.

+ Recent posts