㉠   C -51 컴파일러

  프로그램 메모리 ( CODE Memory)

0003H 번지부터는 인터럽트 벡터가 차지하고 있으므로 점프 명령을 사용하여 프로그램이 수행할 번지로 점프할 수 있도록 해주어야 한다.

C-51 시스템에서 이를 제어하기 위해서는 .XCL 파일을 잘 설정해야 하는데 이는 링크할때에 참조하게 된다. 이중에는 프로그램 메모리가 어는 번지부터 시작되는가도 명시해준다.

예) code char Buffer[500]; ==> CODE 메모리(ROM)에 500바이트의 배열을 할당

내부 데이터 메모리 ( DATA, IDATA Memory)

하위 데이터 RAM (128 바이트)영역은 직접 또는 간접 어드레싱이 가능하다.

직접 어드레싱을 사용 (명령이 줄어들므로 빠른 시간에 처리될 수 있다.)

예) data char temp; ===> mov temp,#1

temp = 1;

간접 어드레싱을 사용

예) idata char temp; ===> mov r0,#temp

temp = 1; ===> mov @r0,#1

만약, 사용자가 물리적으로 존재하는 DATA 메모리 이상의 데이터들을 지정하려한다면, 링커는 7로 7FH 이상의 메모리에 존재해야할 데이터들에 대해서는 "out of range" 에러 메시지 출력

 

DATA 메모리는 20H 부터 2FH 까지 비트 어드레싱 가능 영역을 가지고 있다.

비트 어드레싱을 사용

예) bit CIRCLE = P1.1; bit LIGHT = 0x90; ==> P0.0

bit Bit_Variable; bit OnOff = 0x0; ==> 20h의 첫 번째 비트 선언

SFR ( Special Funtion Register)

내부 RAM 의 128바이트 즉, 80H에서 FFH까지의 영역이다.

예) sfr P0=0x80; P1.7 = 0; ==> 비트 억세스 가능

외부 데이터 메모리 (XDATA Memory)

외부 데이터 메모리는 칩 외부에 RAM을 확장해서 64KB까지 사용할 수 있다.(0000H - FFFFH) 0000H 와 00FFH사이에 있는 XDATA 메모리 영역에 위치한 데이터들은 더 빠르다.

-U 컴파일러 옴셥을 사용하여 외부 메모리에 스택을 설정가능.

예) xdata char Buffer[1000]; /* xdata 메모리에 1000바이트의 배열 할당 */

레지스터(REGISTER)

MCS-51의 레지스터들은 모두 메모리 매핑되어 있는 4개의 레지스터 뱅크(R0,R1,R2,R3)를 제외하고는 모두 SFR 영역에 존재한다. DATA 메모리 하위 영역에 존재하는 레지스터 뱅크들중 하나는 컴파일러에 의해 계산용으로 사용된다. 이 뱅크를 "현재" 혹은 "디폴트" 레지스터 뱅크라 부른다.(심볼 _R을 기본으로한 C-51 스타트업 코드에 의해서 세팅된다.)

심볼 _R은 -D 링커 옵션과 뱅크에서 첫 번째 레지스터의 16진 주소를 사용하여 세팅할 수 있다.

예) -D_R = 8 은 레지스터 뱅크 1을 의미

8051은 DPTR 이라는 오직 한 개의 "일반 목적" 16비트 레지스터를 1개 가지고 있다.

스택 (STACK)

컴파일러는 수식 계산에 있어서의 중간 결과들, 함수호출 복귀 주소, 인터럽트 루팅에서의 보존해야만 되는 레지스터들, 그리고 재귀함수 호출의 경우 저장해야되는 함수 지역 블록 데이터등을 임시 저장하는 장소로 스택을 사용한다.

CSTARTUP 코드에 의해서 세팅된다.(PUSH = SP는 +1, ∴ SP 초기값 = 정해진 스택영역 -1)

스택 용량 계산법)

1. 수식 계산 부동 소수점 연산이 쓰이지 않는 경우 : 15바이트

부동 소수점 연산이 쓰인 경우 : 30바이트

2. 함수 호출 복귀 주소 : 3바이트

3. 인터럽트 핸들러에서 사용되는 모든 레지스터 : 15바이트 이하

4. 재귀함수의 지역 블록들 : 지역변수들의 바이트수+함수 인수 바이트

Tiny 와 Small 메모리 모델에서는 내부 스택이 지역 블록 데이터를 저장하는데 사용된다.

그외 다른 메모리 모델에서는 외부 RAM내의 스택이 사용된다. 이 스택은 XDATA 메모리중에서 RF_XDATA 세그먼트내에 존재하도록 선언된다. 외부 재귀 스택은 200바이트의 기본 크기를 갖지만 아래의 에와 같이 링커 콘트롤 파일에서 -Z(XDATA)라인을 수정함으로서 SU만큼 확장

예) -Z(XDATA)... RF_XDATA+SU=ADDR ==> SU 만큼 확장

디폴트 스택 크기

CSTARTUP.S03 파일에서 기본 스택 크기는 30바이트로 세팅되어 있다.

스택 크기의 변경

링커 제어 파일에서 -Z(IDATA) 라인을 변경해야 한다.

) -Z(IDATA) .... CSTACK+10 ===> 디폴트+10

외부 스택 영역 사용

컴파일할 때 -U 옵션을 주어 스택을 외부 RAM 즉 XDATA 영역으로 지정한다.

변수를 자동으로 초기화 시키지 않는 법

cstartup 파일의 IDATALEN 0으로 지정 한다.

C-51 내부 구조

 

메모리 모델

tiny

small

compact

medium

large

banked

C-51 옵션

-mt

-ms

-mc

-mm

-ml

-mb

파일-레벨

DATA

IDATA

XDATA

XDATA

XDATA

XDATA

로컬 변수

DATA

IDATA

DATA

IDATA

XDATA

XDATA

외부 램

no

no

yes

yes

yes

yes

코드 크기

64K

64K

64K

64K

64K

>1M

칩 타입

8051

8052

8031/32

8032

8032

8032

C Library

cl8051t

cl8051s

cl8051c

cl8051m

cl8051l

cl8051b

 

6가지 메모리 모델

메모리 모델은 반드시 지정해야 할 두 군데가 있다.

1. C 파일을 컴파일할 때 컴파일러 커맨드 라인상에서 -m 옵션을 사용하여 지정해야 한다.

2. 링커 콘트롤 파일에서 사용자가 링커에 있어서의 C 라이브러리를 지정할 때 지정해야 한다.

예) medium 모델의 경우

컴파일시 -mm , 사용자 링커 콘트롤 파일의 링크할 모듈 리스트 라인에 Medium 모델

라이브러리 파일인 CL8051M.R03을 포함시켜야 한다.

주의) 서로 다른 모델로 컴파일된 모듈들은 링크할 수 없다.

확장된 C-51 코드

컴파일시 -E옵션을 사용하거나, 프로세서 지시자(#pragma language=extended)를 사용하면 된다.

 

데이터 형태

크 기

범 위

bit

1 bit

0 or 1

sfr

1 byte

0 to 255

char

1 byte

signed and unsigned char

enum

1 or 2 byte


signed char

1 byte

-128 to 127

unsigned char

1 byte

0 to 255

short

2 byte

-32768 to 32767

unsigned short

2 byte

0 to 65535

int

2 byte

-32768 to 32767

unsigned int

2 byte

0 to 65535

long

4 byte

-2147483648 to 2147483647

unsigned long

4 byte

0 to 4294967295

pointer/address

3 byte


float

4 byte

⁑1.18 E-38 to ⁑3.39 E+38

double

4 byte

⁑1.18 E-38 to ⁑3.39 E+38

long double

4 byte

⁑1.18 E-38 to ⁑3.39 E+38

 

특별한 형태 지시자

const : 물리적으로 수정 할 수 없도록 데이터를 ROM에 넣는다.

예) ∙const x = 5; ==> 롬에다가 5를 넣는다.

const int *pointer_to_const;

∙int y; int *const c_ptr = &y;

const char *ptr_to_const_str="Hellllloooooooooooooooo"; 스트링 롬, 포인터 램

code : 포인터와 포인트된 데이터 모두를 롬에 할당

code char *c_ptrs_to_c_strings[]={"elep","hant"}; 포인터와 스트링 모두 롬

절대 포인터 (Absolute pointer)

 

Memory Area Name

Pointer Value

비 고

DATA, IDATA

0

Internal RAM

XDATA

1

External data RAM

CODE

2

ROM Memory

PDATA

3

MOVX @R0 accessed external date memory

 

예) #define CODE_Area ((char *) 0x022048) /* 2048을 옵셋으로 하는 CODE 영역 */

#define XDATA_Pointer (*(char *) 0x012048) /* 2048 번지를 XDATA 포인터로 지정 */

#define XDATA_Area ((char *) 0x010000) /* 옵셋값을 갖는 XDATA 영역 */

#define XDATA_Area_&_Offset ((char *) 0x011024) /* 1024를 옵셋으로 하는 XDATA */

XDATA_Pointer = 100; /* XDATA 2048h 번지안의 값을 100으로 지정 */

XDATA_Pointer++; /* XDATA 2048h 번지안의 값을 1증가 시킨다. */

XDATA_Area[500]=200; /XDATA 500h 번지안의 값을 200으로 지정 */

 

#define Xdata ((char *) 0x012048) ==> Xdata[100]++;

#define Xdata (*(char *) 0x012048) ==> xdata++; 상수 포인터

#define Read_CODE(address) (((char *)0x010000)[address])

#define Read_XDATA(address) (((char *)0x020000)[address])

#define Write_XDATA(address,value) (((char *)0x010000[address])=value)

컴파일과 링크

C:\8051C> C-51 test1 -mc -L -q -e -A

-mc : compact 메모리 모델로 컴파일

-L : LST 파일 생성함

-q : LST 파일에 어셈블리 언어 니모닉을 포함시킴

-e : ANSI C 사용할 수 있게함.

-A : 어셈블리 언어 리스트 파일을 생성되게 시킨다. 확장자는 .S03

-s : 속도는 빠르고, 코드 크기 크게함.

-z : 속도 느리고, 코드 크기 작게함.

생성 파일 : 오브젝트 파일(.R03), LST 파일(.LST), 어셈블리어 리스트 파일(.S03)

C:\8051C>XLINK -f test1 test1 -o test1.hex -x -l test1.map

-f : 링커 콘트롤 파일을 지정하며 c-51에서 디폴트로 지정되는 파일을 복사하여 수정해서 여기서는 test1.xcl로        지정했다.

test1 : c 소스 파일이름

-o : .hex 파일을 생성함 여기서는 test1.hex 파일로 지정 하였다.

-x : 링크 리스트 파일을 생성하게 된다.

-l : 링크 리스트 파일의 이름을 지정하며 확장자가 map인 파일로 여기서는 test1.map이다.

cstartup.s03 파일의 수정이 필요할 때

defm(X).inc 파일을 defmodel.inc 파일로 카피함 => a8051 cstartup =>

XLIB => *def-cpu 8051 => *rep-mod cstartup cl8051(X) => exit

(X)는 메모리 모델입니다. Tiny 인 경우 Defmt.inc , cl8051t 입니다.

링크 콘트롤 파일(.XCL)

-c8051

==> -c 옵션을 사용하여 CPU를 정의 한다.

       -D_R=0

==> -D(Define symbol)옵션을 사용하여 레지스터 뱅크 설정(0,8,10,18)

       -Z(BIT)C_ARGB,BITVARS=20

==> -Z 옵션과 BIT 세그먼트 정의를 사용하여 8051 내부 RAM의 비트 어드레싱 영역에서 비트 어드레싱 세그먼트 위치를 지정한다.

       -Z(DATA)C_ARGD,D_UDATA,D_IDATA=8-19,22-FF

==> -Z옵션과 DATA 세그먼트 정의를 사용하여 내부 RAM의 DATA 세그먼트 위치를 지정한다.

      -Z(IDATA)C_ARGI,I_UDATA,I_IDATA,CSTACK

==> 내부 RAM에서 IDATA와 CSTCK세그먼트의 위치를 지정하며 이는 DATA 세그먼트의 끝의 주소에서 부터 시작된다. CSTACK 세그먼트는 IDATA 세그먼트의 끝에서 시작하며 IDATA의 끝과 어드레스 7로(내부 RAM이 128 바이트인 경우)사이의 공간을 사용한다.

      -Z(XDATA)C_ARGX,X_UDATA,X_IDATA,ECSTR,RF_XDATA=8000

==> 외부 RAM에서 XDATA세그먼트의 위치를 지정한다.

      -Z(CODE)INTVEC,RCODE,D_CDATA,I_CDATA,X_CDATA,

        C_ICALL,C_RECFN,CSTR,CCSTR,CODE,CONST=0

==> 코드세그먼트의 위치를 지정한다.

       -e_small_write=_formatted_write

==> -e 옵션을 사용하여 printf/sprintf의 형식자를 지정한다.

       -e_medium_read=_formatted_read

==> -e옵션을 사용하여 scanf()형식자를 지정한다.

       cl8051t -! or cl8051s, cl8051c, cl8051m, cl8051l -!

==> 링크될 메모리 모델에 적합한 c 런타임 라이브러리 파일을 지정한다.

      -FINTEL-STANDARD

==> INTEL HEX 형식의 출력 파일을 지정한다.

. 링커 .MAP 파일

링크후 링크 리스트 파일(.MAP)이 생성 되는데 다음과 같은 내용으로 구성된다.

∙링크 환경 헤더

∙모듈 맵

∙세그먼트 덤프 테이브

∙에러와 경고 메세지

확장된 C언어 키워드

-------------------------------------------------------------------

∙bit ∙code ∙data ∙idata ∙interrupt ∙monitor ∙non_banked ∙no_init ∙plm

∙reentrant ∙sfr ∙using∙xdata

-------------------------------------------------------------------

<bit>

bit Bit_Variable = Constant_Bit_Address;

bit Bit_Variable = Constant_Bit_Addressable_Byte_Address.Bit_Num;

bit Bit_Variable = SFR_ID.bit_Num;

Bit_Variable :사용자 비트 변수 이름

Constant_: 컴파일 시에 어드레스가 컴파일러에 의해 계산됨을 암시한다.

_Bit_Address : 유효한 비트 어드레스 (00h - FFh)이다.

_Bit_Addressable_Byte_Address: 하드웨어 비트 어드레싱 가능한 바이트 어드레스이다.

내부 램의 20h - 2Fh 와 sfr 영역(80h - FFh)에서 0h 과 8h로 끝나는 바이트 어드레스

-------------------------------------------------------------------

<code>

code char Buffer[500]; /* CODE 메모리에 500바이트의 배열을 할당 */

-------------------------------------------------------------------

<data>

data char char_var;

-------------------------------------------------------------------

<idata>

idata char char_Var;

-------------------------------------------------------------------

<xdata>

xdata char Temple[1000];

-------------------------------------------------------------------

<interrupt>

interrupt [0x1b] using [2] void Timer_1();

interrupt void Timer_1() { }

-------------------------------------------------------------------

<monitor> 인터럽트 시스템을 비활성화 시키면서 실행 할 수 있도록 해준다.

monitor void Function_1();

monitor void Function_2(); /* 이 함수를 수행중에는 인터럽트가 걸리지 않는다*/

-------------------------------------------------------------------

<no_init> 초기화되지 않는 데이터 메모리 영역에 정의한다.(xdata)

no_init int No_Init_Array[100];

no_init char *string = "Init_string";

-------------------------------------------------------------------

<sfr>

sfr P1=0x90;

-------------------------------------------------------------------

#pragma memory = xxx (xxx = default, code, data,idata, xdata, no_init)

#pragma function = xxx (xxx = default, interrupt, monitor)

세그먼트

BITVAR (DATA 메모리에서 어드레스 20h - 2Fh 사이의 비트 어드레싱 영역)

BIT 변수를 수용하고 사용자가 작성한 상대 BIT 변수를 수용할 수 있다.

C_ARGB (DATA 메모리에서 어드레스 20h - 2Fh 사이의 비트 어드레싱 영역)

반드시 비트 어드레싱 데이터 메모리에 할당되어야 하는 모든 C 함수에서 사용되는 지역 변 수와 파라미터 영역을 수용한다. 이 영역은 링커에 의해서 할당 된다.

C_ARGB (data)

반드시 data 메모리에 할당되어야 하는 모든 C 함수에서 사용되는 지역 변수와 파라미터 영역 을 수용한다. 이 영역은 링커에 의해서 할당된다.

C_ARGI (idata)

반드시 idata 메모리에 할당되어야 하는 모든 C 함수에서 사용되는 지역 변수와 파라미터 영 역을 수용한다. 이 영역은 링커에 의해서 할당된다.

C_ARGX (xdata)

반드시 XDATA 메모리에 할당되어야 하는 모든 C 함수에서 사용되는 지역 변수와 파라미터 영역을 수용한다. C_ARGX는 -u(함수 리턴 스택 확장) 컴파일러 옵션이 사용되었을 경우 함 수 리턴 어드레스도 수용한다. 이 영역은 링커에 의해서 할당된다.

CCSTR (code)

-y 컴파일러 옵션이 사용되었을 경우 C 문자열 초기자를 수용한다. CSTR 세그먼트를 참조하 기 바란다.

C_ICALL (code)

함수 간접 호출을 관리하기 위해 링커에 의해 사용된다.

CODE (code)

실행 코드를 수용하기 위해서 C컴파일러에 의해서 사용되는 디폴트 세그먼트이다. 그리고 임 의의 뱅크 가능한 실행 라이브러리 코드가 링커에 의해서 이 세그먼트에 위치한다. 사용자가 작성한 어셈블리 코드를 수용할때도 사용될 수 있다. CODE 세그먼트는 반드시 뱅크 변환 코 드를 포함해야 한다.

CONST (code)

const 객체와 code 객체를 저장하기 위해서 사용된다. 상수 데이터를 선언하기 위해서 어셈블 리어 루틴에서 사용될 수 있다.

C_RECFN (code)

재귀 함수를 관리하기 위해 링커에 의해서 사용된다.

CSTACK (data and/or idata)

스택을 수용한다.

CSTR (code)

C 문자열을 수용한다. 디폴트로서 C 문자열은 읽기만 가능하고 ROM의 CSTR세그먼트에 저 장된다. -y 컴파일러 옵션은 그와 같은 문자열이 ROM의 CCSTR 세그먼트에 위치하는 초기 자를 갖도록하고, RAM의 ECSTR 세그먼트에 그 문자열을 위한 예약된 공간을 할당 받도록 한다.

-y 컴파일러 옵션을 사용함으로서, START_UP시에 C문자열은 ROM의 CCSTR 세그먼트에 저장되고, 런타임시에 RAM의 ECSTR 세그먼트에 복사된다.

D_CDATA (code)

D_IDATA 세그먼트에 저장되는 변수에 대한 변수 초기자를 수용한다. 이 값은 초기화 과정에 서 CSTARTUP에 의해 D_CDATA에서 D_IDATA로 복사된다.

D_IDATA (data)

초기값과 함께 선언되고 DATA 메모리에 상주하도록 정의된 static 변수를 수용한다. 그들의 초기값은 초기화 과정에서 CSTARTUP에 의해 D_CDATA 세그먼트로 복사된다.

D_UDATA (data)

초기값없이 선언되고 DATA 메모리에 상주하도록 정의된 static 변수를 수용한다. ANSI C는 프로그램에 의해 억세스 되기 전에 이 변수들을 모두 0으로 초기화 되도록 지정한다. 그들의 값은 초기화 과정에서 CSTARTUP에 의해 모두 0으로 초기화 된다.

ECSTR (xdata)

-y 컴파일러 옵션이 사용되었을 경우 C 문자열의 복사본을 수용한다. CSTR세그먼트를 참조 하기 바란다.

I_CDATA (code)

I_IDATA 세그먼트에 저장되는 변수에 대한 변수 초기자를 수용한다. 이 값은 초기화 과정에 서 CSTARTUP에 의해 I_CDATA에서 I_IDATA로 복사된다.

I_UDATA (code)

초기값 없이 선언되고 IDATA 메모리에 상주하도록 정의된 static 변수를 수용한다. ANSI C 는 프로그램에 의해 억세스 되기 전에 이 변수들을 모두 0으로 초기화 되도록 지정한다. 그들 의 값은 초기화 과정에서 CSTARTUP에 의해 모두 0으로 초기화 된다.

INTVEC (code)

INTVEC 세그먼트는 코드 어드레스 0000H 부터 시작하도록 링크되기 때문에 반드시 CODE 어드레스 0000H으로 참조되어야 하는 코드를 위해서 CSTARTUP에 의해서 사용된다. INTVEC는 초기 코드로의 점프 명령을 포함한다. 프로세서 리셋이나 전원 ON 후에 0000H 부 터 실행을 시작하기 때문에 점프 명령은 이 어드레스에 상주한다. INTVEC는 또한 interrupt 확장 키워드의 사용에 의해서 발생되는 인터럽트 벡터 테이블을 포함한다.

NO_INIT (xdata에서의 사용자 제공하는 비휘발성 RAM영역)

비휘발성 XDATA 메모리에 확장 키워드 no_init으로 선언된 변수를 할당하기 위해서 사용된 다. 또한 비휘발성 메모리에 포함되는 변수를 선언하기 위한 어셈블리어 루틴에서 사용될 수 있다.

RCODE (code)

런 타임 라이브러리 루틴과 non_banked 코드를 위해 사용된다. 또한 사용자가 작성한 인터럽 트 핸들러나 non_banked 코드를 위해 사용될 수 있다.

RF_XDATA (xdata)

외부 재귀 스택을 할당하기 위해서 링커에 의해서 사용된다.

X_CDATA (code)

X_IDATA 세그먼트에 저장되는 변수에 대한 변수 초기자를 수용한다. 이 값은 초기화 과정에 서 CSTARTUP에 의해 X_CDATA에서 X_IDATA로 복사된다.

X_CDATA (xdata)

초기값과 함께 선언되고 XDATA 메모리에 상주하도록 정의된 static 변수를 수용한다. 그들의 초기값은 초기화 과정에서 CSTARTUP에 의해 X_CDATA 세그먼트로 부터 복사된다.

X_CDATA (xdata)

초기값 없이 선언되고 XDATA 메모리에 상주하도록 정의된 static 변수를 수용한다. ANSI C 는 프로그램에 의해 억세스 되기 전에 이 변수들을 모두 0으로 초기화 되도록 지정한다. 그들 의 값은 초기화 과정에서 CSTARTUP에 의해 모두 0으로 초기화 된다.

인터럽트

8051은 2개의 외부 요인과 3개의 내부 요인의 모두 5개의 인터럽트 요인이 있다.

∙외부 인터럽트 0, 외부 인터럽트 1

∙타이머/카운터 0, 타이머/카운터 1

∙시리얼 포트

인터럽트는 IE,IP의 2개의 레지스터로 제어한다.

외부 인터럽트 /INT0와 /INT1은 레지스터 TCON에 있는 비트 IT0와 IT1에 따라 레벨에서 동기되거나 로직 변화시에 동기될 수 있다. ( IT0, IT1가 '0'일 때 레벨동기 즉, Low 일 때 인터럽트 호출 )

TCON의 IE0와 IE1에 의해서 인터럽트 발생 하드웨어에 의해 소거

타이머 0와 타이머 1 인터럽트는 TF0와 TF1에 의해서 발생한다.

하드웨어에 의해 소거

직렬 단자 인터럽트는 RI와 TI의 논리 OR에 의해서 만들어 진다.

하드웨어에 의해서 소거되지 않는다. 인터럽트를 만들어 내는 것이 RI인지 TI인지를 결정해야 하며 그 비트는 소프트웨어로 소거해야 한다.

TCON 레지스터

 

TF1

TR1

TF0

TR0

IE1

IT1

IE0

IT0

 

TR(Timer Run) 비트는 타이머/카운터를 ON/OFF 하는데 사용되며, TR비트가 1이면 ON(스타트)되고, 0이면 0FF(스톱) 된다.

TF(Timer overFlow)비트는 타이머/카운터 레지스터가 오버플로우가 되면 1로 세트되며, 이때 인터럽트가 인에이블 되어 있으면 인터럽트를 요구하고 8051이 인터럽트를 받으면 TF 플래그는 자동적으로 클리어 된다. (명령이 줄어들므로 빠른 시간에 처리될 수 있다)

IT 비트는 외부인터럽트를 하강에지(IT=1일 때)또는 'L'레벨(IT=0일 때)일 때 감지할 것인지를 결정하는 비트 이다.

IE 인터럽트가 호출 될 때 하드웨어로 세트된다. 인터럽트가 진행중 일 때 클리어 된다.

IE 레지스터

 

EA



ES

ET1

EX1

ET0

EX0

 

EA : 모든 인터럽트 인에이블 ES : 시리얼 포트 인터럽트 인에이블

ET1 : 타이머 1 인터럽트 인에이블 EX1 : 외부 인터럽트 인에이블

ET0 : 타이머 0 인티럽트 인에이블 EX0 : 외부 인터럽트 인에이블

IP 레지스터

 



PS

PT1

PX1

PT0

PX0

 

PS : 시리얼 포트 우선순위 높이기 PT1 : 타이머 1 우선순위 높이기

PX1 : 외부 인터럽트 우선순위 높이기 PT0 : 타이머 0 우선순위 높이기

IP0 : 외부 인터럽트 0 우선순위 높이기

디폴트 우선순위 : 1. IE0 2. TF0 3. IE1 4. TEF1 5.RI+TI

 

벡터 주소

인터럽트 소스

0003H

000BH

0013H

001BH

0023H

002BH

External Interrupt 0 (IE0)

Timer 0 Overflow (TF0)

External Interrupt 1 (IE1)

Timer 1 Overflow (TF1)

Serial Port (RI+TI)

Timer 2 Overflow (TF2+EXF2)

 

인터럽트 서비스 루틴의 사용

interrupt [vector] using [bank] 함수

예) interrupt [3] using [1] void int_handler(void);

interrupt void int_handler() { /* 실제 인터럽트 처리 코드 */ }

외부 인터럽트

외부요소는 TCON 레지스터에서 비트 IT1이나 IT0를 세트하거나 클리어함으로서 레벨 동기나 로직변환시 동기되도록 프로그램할 수 있다. 만일 ITx=0이면 외부 인터럽트 x는 /INTx핀에서 검출된 Low에 의해 시작되고, ITx=1일 때는 하강 에지 트리거의 영향을 받는다. 이 모드에서 /INTx핀의 연속적인 샘플은 한 사이클에서 High를 다음 사이클에서 Low를 나타낸다.

TCON에 있는 인터럽트 요구 플래그 IEx는 세트되어 플래그 비트 IEx는 인터럽트를 요구한다.

동기가 되면 인터럽트 요구플래그 IEx는 세트되며 IEx는 서비스루틴이 호출될 때 CPU에 의해 자동적으로 클리어 된다.

예) External Interrupt 0

IT0=0; IT1=0; /* INT0 핀이 Low 일 때 Active */

IE=0x81; /* 외부 인터럽트 0 이 활성화 된다. IE 레지스터 참조 */

TCON 레지스터

 

TF1

TR1

TF0

TR0

IE1

IT1

IE0

IT0

 

TR(Timer Run) 비트는 타이머/카운터를 ON/OFF 하는데 사용되며, TR비트가 1이면 ON(스타트)되고, 0이면 0FF(스톱) 된다.

TF(Timer overFlow)비트는 타이머/카운터 레지스터가 오버플로우가 되면 1로 세트되며, 이때 인터럽트가 인에이블 되어 있으면 인터럽트를 요구하고 8051이 인터럽트를 받으면 TF 플래그는 자동적으로 클리어 된다. (명령이 줄어들므로 빠른 시간에 처리될 수 있다)

IT 비트는 외부인터럽트를 하강에지(IT=1일 때)또는 'L'레벨(IT=0일 때)일 때 감지할 것인지를 결정하는 비트 이다.

IE 인터럽트가 호출 될 때 하드웨어로 세트된다. 인터럽트가 진행중 일 때 클리어 된다.

IE 레지스터

 

EA



ES

ET1

EX1

ET0

EX0

 

EA : 모든 인터럽트 인에이블 ES : 시리얼 포트 인터럽트 인에이블

ET1 : 타이머 1 인터럽트 인에이블 EX1 : 외부 인터럽트 인에이블

ET0 : 타이머 0 인티럽트 인에이블 EX0 : 외부 인터럽트 인에이블

IP 레지스터

 



PS

PT1

PX1

PT0

PX0

 

PS : 시리얼 포트 우선순위 높이기 PT1 : 타이머 1 우선순위 높이기

PX1 : 외부 인터럽트 우선순위 높이기 PT0 : 타이머 0 우선순위 높이기

IP0 : 외부 인터럽트 0 우선순위 높이기

타이머/카운터0,1

2개의 16비트 타이머/카운터 즉, 타이머/카운터 0과 타이머/카운터 1을 가지고 있다.

타이머는 머신 사이클 12개의 발진 주기를 구성하며 카운터 비는 발진 주파수의 1/12이 된다.

 

카운터 기능 에서의 레지스터는 외부 입력 핀 T0,T1에서 1에서 0으로 변화에 따라 증가한다.

그리고 최대 카운터비는 발진 주파수 1/24이 된다.(한 펄스 인식하는데 2머신 사이클 사용)

카운터 레지스터가 오버플로우가 발생하면 TF 가 세트된다.

타이머로서 사용할 때에는 설정된 값과 같게 되면 인터럽트가 발생한다.

타이머/카운터 1의 경우는 시리얼 포트의 비동기 통신 모드에 있어서 보레이트 발생기로서 동작시킬 수 있다.

타이머/카운터는 SFR 영역내에 TLx,THx레지스터를 사용.

 

타이머/카운터는 TMOD(Timer Mode Resister) TCON(Timer Control Resister)의 2개의 레지스터로 제어한다.

예) Timer Interrupt 0

모드를 설정한다(TMOD=(0,1,2 OR 3) => 타이머 시간을 설정한다(TH0,TL0)

IE 레지스터를 설정한다 (EA=ET0=1) => (우선순위 (IP))

타이머 런(TR0=1)

∙모드 0 : 13비트로 레지스터 구성

∙모드 1 : 16비트로 레지스터 구성

∙모드 2 : 8비트 오토 리로드 모드

1) TMOD 레지스터

 

GATE

C/T

M1

M0

GATE

G/T

M1

M0

 

Timer 1 Timer 0

GATE 비트는 외부 인터럽트 단자(INT0,INT1)에 동기시켜 타이머/카운터를 동작시키도록 제어한다. 이 비트가 1로 세트되어 있으면, 외부 인터럽트 단자가 H 레벨 때에 타이머/카운터로 동작한다. L 레벨일때는 타이머/카운터 동작이 정지된다.

GATE 비트가 0이 될 경우는, 외부 인터럽트 단자에는 영향을 받지 않고 타이머/카운터로서 작동시킬 수 있다.

2) TCON 레지스터

 

TF1

TR1

TF0

TR0

IE1

IT1

IE0

IT0

 

TR(Timer Run) 비트는 타이머/카운터를 ON/OFF 하는데 사용되며, TR비트가 1이면 ON(스타트)되고, 0이면 0FF(스톱) 된다.

TF(Timer overFlow)비트는 타이머/카운터 레지스터가 오버플로우가 되면 1로 세트되며, 이때 인터럽트가 인에이블 되어 있으면 인터럽트를 요구하고 8051이 인터럽트를 받으면 TF 플래그는 자동적으로 클리어 된다. (명령이 줄어들므로 빠른 시간에 처리될 수 있다)

IT 비트는 외부인터럽트를 하강에지(IT=1일 때)또는 'L'레벨(IT=0일 때)일 때 감지할 것인지를 결정하는 비트 이다.

IE 인터럽트가 호출 될 때 하드웨어로 세트된다. 인터럽트가 진행중 일 때 클리어 된다.

IP 레지스터

 



PS

PT1

PX1

PT0

PX0

 

PS : 시리얼 포트 우선순위 높이기 PT1 : 타이머 1 우선순위 높이기

PX1 : 외부 인터럽트 우선순위 높이기 PT0 : 타이머 0 우선순위 높이기

IP0 : 외부 인터럽트 0 우선순위 높이기

시리얼 통신

입력은 RXD(P3.0) 단자를 통해 하고, 출력은 TXD(P3.1) 단자를 통해서 한다.

완전 이중통신 방식으로 동시에 전송과 수신을 할 수 있다. 또 완충 수신으로서 수신 바이트가 수신 레지스터에 읽혀지기 전에 두 번째 바이트의 수신을 시작할 수 있다.

시리얼 포트의 수신과 송신 레지스터는 둘다 SFR SBUF에서 불러서 쓸 수 있다.

SCON 레지스터

 

SM0

SM1

SM2

REN

TB8

RB8

TI

RI

 

SM2 : Serial Mode Control bit 2

모드 2,3에서 MPU 통신 특성을 가능하게 한다.

모드 2,3에서 SM2가 1로 세트되면 RI는 동작되지 않는다.

REN: Receiver Enable 수신 가능시 세트, 수신 불가능시 클리어 된다.

TB8: Transmit Bit 8 9번째 데이터 비트로 모드 2,3에서 전송된다.

세트와 클리어는 소프트웨어로 한다.

RB8: Receive Bit 8 모드 2,3에서 9번째 데이터 비트로 수신되고, 모드 1에서 SM2=0일 경우 RB8은 스톱 비트로 수신되고, 모드 0에서 RB8 은 사용되지 않는다.

TI: Transmit Interrupt Flag 모드 0에서 8번째 비트의 끝에서 하드웨어로 세트되고 기타 모드에서는 스톱 비트의 시작으로 된다. 또 시리 얼 전송에서는 소프트웨어로 항상 클리어해야 한다.

RI: Receive Interrupt Flag 모드 0에서 8번째 비트의 끝에서 하드웨어로 세트되고 기타 모드에서는 스톱비트의 중간에서 세트된다, 또 시리얼 수신에서 소프트웨어로 항상 클리어 해야한다.

SMO, SM1 비트에 의한 모드 기능.

 

SM0 SM1

모드

기 능

보오레이트

0 0

0 1

1 0

1 1

0

1

2

3

시프트 레지스터

8비트 UART

9비트 UART

9비트 UART

Fxosc/12

가변

Fxosc/64 또는 /12

가변

 

타이머 1에 의한 일반적인 보오레이트 발생

 

보오레이트

발진 주파수

SMOD

타이머 1

C/T

Mode

Reload value

Mode 0 Max : 1Mhz

Mode 2 Max : 375K

Mode 1,3 : 62.5K

19.2K

9.6K

4.8K

2.4K

1.2K

137.5K

110K

110K

12Mhz

12Mhz

12Mhz

11.059Mhz

11.059Mhz

11.059Mhz

11.059Mhz

11.059Mhz

11.059Mhz

6Mhz

12Mhz

x

1

1

1

0

0

0

0

0

0

0

x

x

0

0

0

0

0

0

0

0

0

x

x

2

2

2

2

2

2

2

2

1

x

x

FFH

FDH

FDH

FAH

F4H

F8H

E8H

1DH

72H

 

시리얼 포트를 사용하기 위해선 SCON TMOD TCON PCON 레지스터를 목적에 맞게 세팅해야 한다.

예) Sirial Interrupt (9600BPS)

TMOD = 0x20; (Auto Rrload Mode) TCON = 0x40; (Timer 1 Run For Communication)

SCON = 0x52; (Serial Mode = 1, REN = 1, TI = 1) PCON = 0x00; (PCON.7 = SMOD = 0)

TH1 = 0xFD; (9600bps) IE = 0x90; (시리얼 인터럽트 인에이블)

IP = 0x10; (우선 순위 높임)

-----------------------------------------------------------------------------------

char Rx_Data(void) void Tx_Data(char T)

{ {

char Rx_Value; while(!TI);

while(!RI); SBUF=T;

Rx_Value=SBUF; TI=0;

RI = 0; }

return(Rx_Value);

}

*** 부 록 ***

/* - IO51.H - Special header for the 8051/52/31/32 processors. Version 4.00 [IANR] */

#pragma language=extended

/*===============================*/

/* Predefined SFR Byte Addresses */

/*===============================*/

sfr P0= 0x80; sfr P1= 0x90; sfr P2= 0xA0; sfr P3= 0xB0; sfr PSW= 0xD0;

sfr ACC= 0xE0; sfr B= 0xF0; sfr SP= 0x81; sfr DPL= 0x82; sfr DPH= 0x83;

sfr PCON= 0x87; sfr TCON= 0x88; sfr TMOD= 0x89; sfr TL0= 0x8A; sfr TL1= 0x8B;

sfr TH0= 0x8C; sfr TH1= 0x8D; sfr IE= 0xA8; sfr IP= 0xB8; sfr SCON= 0x98;

sfr SBUF= 0x99; sfr T2CON= 0xC8; sfr RCAP2L = 0xCA;

sfr RCAP2H = 0xCB; sfr TL2= 0xCC; sfr TH2= 0xCD;

/*==============================*/

/* Predefined SFR Bit Addresses */

/*==============================*/

 

/*========PSW========*/

bit CY = 0xD7; bit AC = 0xD6; bit F0 = 0xD5; bit RS1 = 0xD4; bit RS0 = 0xD3;

bit OV = 0xD2; bit P = 0xD0;

/*========TCON=======*/

bit TF1 = 0x8F; bit TR1 = 0x8E; bit TF0 = 0x8D; bit TR0 = 0x8C;

bit IE1 = 0x8B; bit IT1 = 0x8A; bit IE0 = 0x89; bit IT0 = 0x88;

/*========IE=========*/

bit EA = 0xAF; bit ET2 = 0xAD; bit ES = 0xAC; bit ET1 = 0xAB;

bit EX1 = 0xAA; bit ET0 = 0xA9; bit EX0 = 0xA8;

/*========IP=========*/

bit PT2 = 0xBD; bit PS = 0xBC; bit PT1 = 0xBB;

bit PX1 = 0xBA; bit PT0 = 0xB9; bit PX0 = 0xB8;

/*========P3=========*/

bit RD = 0xB7; bit WR = 0xB6; bit T1 = 0xB5; bit T0 = 0xB4;

bit INT1 = 0xB3; bit INT0 = 0xB2; bit TXD = 0xB1; bit RXD = 0xB0;

/*========SCON========*/

bit SM0 = 0x9F; bit SM1 = 0x9E; bit SM2 = 0x9D; bit REN = 0x9C;

bit TB8 = 0x9B; bit RB8 = 0x9A; bit TI = 0x99; bit RI = 0x98;

/*========T2CON=======*/

bit TF2 = 0xCF; bit EXF2 = 0xCE; bit RCLK = 0xCD; bit TCLK = 0xCC;

bit EXEN2 = 0xCB; bit TR2 = 0xCA; bit C_T2 = 0xC9; bit CP_RL2 = 0xC8;

/*==============================*/

/* Interrupt Vector Definitions */

/*==============================*/

interrupt [0x03] void EX0_int (void); /* External Interrupt 0 */

interrupt [0x0B] void T0_int (void); /* Timer 0 Overflow */

interrupt [0x13] void EX1_int (void); /* External Interrupt 1 */

interrupt [0x1B] void T1_int (void); /* Timer 1 Overflow */

interrupt [0x23] void SCON_int (void); /* Serial Port */

/* interrupt [0x2B] void T2_int (void); */ /* Timer 2 Overflow (8031) */

/* interrupt [0x2B] void T2EX_int (void); */ /* Negative Transition on T2EX (8031) */

#define Read_CODE(address) (((char *)0x010000)[address])

#define Read_XDATA(address) (((char *)0x020000)[address])

#define Write_XDATA(address,value) (((char *)0x010000[address])=value)

1) TMOD 레지스터

 

GATE

C/T

M1

M0

GATE

G/T

M1

M0

 

Timer 1 Timer 0

GATE 비트는 외부 인터럽트 단자(INT0,INT1)에 동기시켜 타이머/카운터를 동작시키도록 제어한다. 이 비트가 1로 세트되어 있으면, 외부 인터럽트 단자가 H 레벨 때에 타이머/카운터로 동작한다. L 레벨일때는 타이머/카운터 동작이 정지된다.

GATE 비트가 0이 될 경우는, 외부 인터럽트 단자에는 영향을 받지 않고 타이머/카운터로서 작동시킬 수 있다.

2) TCON 레지스터

 

TF1

TR1

TF0

TR0

IE1

IT1

IE0

IT0

 

TR(Timer Run) 비트는 타이머/카운터를 ON/OFF 하는데 사용되며, TR비트가 1이면 ON(스타트)되고, 0이면 0FF(스톱) 된다.

TF(Timer overFlow)비트는 타이머/카운터 레지스터가 오버플로우가 되면 1로 세트되며, 이때 인터럽트가 인에이블 되어 있으면 인터럽트를 요구하고 8051이 인터럽트를 받으면 TF 플래그는 자동적으로 클리어 된다. (명령이 줄어들므로 빠른 시간에 처리될 수 있다)

IT 비트는 외부인터럽트를 하강에지(IT=1일 때)또는 'L'레벨(IT=0일 때)일 때 감지할 것인지를 결정하는 비트 이다.

IE 인터럽트가 호출 될 때 하드웨어로 세트된다. 인터럽트가 진행중 일 때 클리어 된다.

SCON 레지스터

 

SM0

SM1

SM2

REN

TB8

RB8

TI

RI

 

SM2 : Serial Mode Control bit 2

모드 2,3에서 MPU 통신 특성을 가능하게 한다.

모드 2,3에서 SM2가 1로 세트되면 RI는 동작되지 않는다.

REN : Receiver Enable 수신 가능시 세트, 수신 불가능시 클리어 된다.

TB8 : Transmit Bit 8 9번째 데이터 비트로 모드 2,3에서 전송된다.

세트와 클리어는 소프트웨어로 한다.

RB8 : Receive Bit 8 모드 2,3에서 9번째 데이터 비트로 수신되고, 모드 1에서 SM2=0일 경우 RB8은 스톱 비트로 수신되고, 모드 0에서 RB8 은 사용되지 않는다.

TI : Transmit Interrupt Flag 모드 0에서 8번째 비트의 끝에서 하드웨어로 세트되고 기타 모드에서는 스톱 비트의 시작으로 된다. 또 시리 얼 전송에서는 소프트웨어로 항상 클리어해야 한다.

RI : Receive Interrupt Flag 모드 0에서 8번째 비트의 끝에서 하드웨어로 세트되고 기타 모드에서는 스톱비트의 중간에서 세트된다, 또 시리얼 수신에서 소프트웨어로 항상 클리어 해야한다.

IT 비트는 외부인터럽트를 하강에지(IT=1일 때)또는 'L'레벨(IT=0일 때)일 때 감지할 것인지를 결정하는 비트 이다.

IE 인터럽트가 호출 될 때 하드웨어로 세트된다. 인터럽트가 진행중 일 때 클리어 된다.

IE 레지스터

 

EA



ES

ET1

EX1

ET0

EX0

 

EA : 모든 인터럽트 인에이블 ES : 시리얼 포트 인터럽트 인에이블

ET1 : 타이머 1 인터럽트 인에이블 EX1 : 외부 인터럽트 인에이블

ET0 : 타이머 0 인티럽트 인에이블 EX0 : 외부 인터럽트 인에이블

IP 레지스터

 



PS

PT1

PX1

PT0

PX0

 

PS : 시리얼 포트 우선순위 높이기 PT1 : 타이머 1 우선순위 높이기

PX1 : 외부 인터럽트 우선순위 높이기 PT0 : 타이머 0 우선순위 높이기

IP0 : 외부 인터럽트 0 우선순위 높이기

PSW 레지스터

 

CY

AC

F0

RS1

FS0

OV


P

 

CY : 캐리 플래그 AC : 보조 캐리 플래그 (BCD 동작) F0 : 플래그 0 (일반 목적용)

RSx : 레지스터 뱅크 정의 ( 0 - 3 ) OV : 오버 플로오 플래그 P : 패리티 플래그

PCON 레지스터

 

SMOD1

SMOD0


POF

GF1

GF0

PD

IDL

 
 

1999. 8.

미래의 블럭로봇의 선구두자 로보블럭시스템에서 드리는 자료.......

D.S, SHIN

* 메모리 옵션 지정 C-51 컴파일러에서 사용자가 하드웨어의 메모리 크기와 형태에 따라서 어떻게 적용할 것인지에 대하여 효율적으로 사용하는 방법을 제시

** 메모리 옵션을 반드시 지정해야 할 두 가지

1. C파일을 컴파일 할 때 컴파일러 커맨드 라인에서 -m 옵션을 사용하여 지정 (Page 80, 81 참고)

ex) C:\8051\c51\bin\>c-51 test.c51 -mc -e -L -g -s -K

2. 링커 컨트롤 파일(*.XCL)에서 사용자 링커에 있어서의 C라이브러리를 지정할 때 또 한 번 지정한다. 예를 들어 사용자가 Medium모델을 사용한다면 컴파일 커맨드 라인상 -mm을 지정하고 사용자 링커 컨트롤 파일의 링커할 모듈 리스트 라인에 Medium 모델 라이브러리인 파일 CL8051M.R03을 포함시켜야 한다.

파일레벨과 로컬변수는 메모리 모델에 의해 정의된 메모리 영역으로 고정적으로 지정되어 있다. ---> 디폴트 영역이라한다.

어떠한 객체를 특정한 메모리 영역으로 지정할 때는 확장언어 키워드(DATA, IDATA, XDATA, CONST)를 이용하여 언제든지 지정을 바꿀 수 있다.

* 파일레벨 : 함수정의 밖에 정의된 변수

* 로컬변수 : 함수내의 정의된 파라미터와 로컬변수

 

메모리 옵션

Tiny

small

compact

medium

large

banked

C-51

-mt

-ms

-mc

-mm

-ml

-mb

파일레벨

DATA

IDATA

XDATA

XDATA

XDATA

XDATA

로컬변수

DATA

IDATA

DATA

IDATA

XDATA

XDATA

외부램

NO

NO

YES

YES

YES

YES

코드크기

64K

64k

64k

64k

64K

64k

칩형태

8051

8052

8031/32

8032

8032

8032

C라이브러리

cl8051t

cl8051s

cl8051c

cl8051m

cl8051l

cl8051b

 

1) 하드웨어에 따른 옵션 고려

- 사용자가 외부 램을 갖고 있지 않고 128바이트의 내부 램만을 갖고 있다면 사용자는 반드시 "Tiny"모델 선택하여야 한다.

- 사용자가 외부 램을 갖고 있지 않고 256바이트의 내부 램만 갖고 있다면 "small" 모델 사용할 수 있다.

- 사용자가 외부램과 128바이트 내부 램을 가지고 있다면 "compact"모델 사용(8031 : 내부램이 없다)

- 사용자가 256바이트 내부 램과 약간의 외부 램을 가지고 있고 코드영역이 64K byte이내 라면 compact, medium, large 모델을 사용할 수 있다.

이 중의 하나를 선택하여 사용하는 것은 소프트웨어에서 고려한다.

1. 사용자의 코드영역 64k byte 이상 요구할 경우 사용자는 반드시 banked모델 사용해야 한다.

2 램 메모리는 "banked"모델이 허용되지 않는다. 따라서 컴파일러에 의해서 호출될 수 있는 최대의 램영역은 64Kbyte이다.

2) 소프트웨어에 따른 고려

사용자가 약간의 외부 램을 갖고 64K byte이하의 롬영역을 사용할 수 있다면 compact, medium, large모델 중에서 하나를 선택할 수 있다.

DATA메모리는 호출하는데 있어서 아주 적은 기계명령이 필요. 따라서 속도는 아주 빠르다.

반면에DATA메모리 용량은 아주 적기 때문에 빠른 호출 속도를 요구하는 변수들만 이곳에 저장시킨다.

IDATA는 DATA메모리 보다 느리다. 대부분의 경우 스택으로 사용

XDATA는 DATA의 반대로서 64K BYTE까지 확장할 수 있기 때문에 변수들을 가장 많이 적재 할수 있다.

*DATA:직접번지 지정 가능한 내부 램(00h~7Fh)

*IDATA:간접번지 지정 가능한 내부 램(00h~FFh)

*XDATA:외부 데이터 램(0a*)h~FFFFh)

*메모리 옵션을 지정하지 않은 경우 -mt옵션이 된다.

메모리 형태

 

포인터 값

비고

DATA, IDATA

0

내부 램

XDATA

1

외부 데이터 램

CODE

2

롬 프로그램 메모리

PDATA

3

MOVE @RO 호출하는 외부 데이터 메모리

 

#define CODE_Area((char *) 0x022048) //프로그램 메모리 어드레스2048

#define XDATA_Pointer((char *)0x022048) //외부데이터 메모리 어드레스2048

#define XDATA_Area((char *)0x010000) //외부데이터 메모리 어드레스0000

viod main(void)

{

XDATA_Pointer=100; //외부 데이터 메모리 2048h번지에 100을 저장

XDATA_Pointer++; //외부 데이터 메모리 2048h번지의 내용을 1 증가

XDATA_Area[i*2]-5; //외부 데이터 메모리 [0000h+05000h*2]의 내용을 -5한다.

XDATA_Area[i] ; //외부 데이터 메모리 05000h에 200을 저장

XDATA_Area[100]++ //외부 데이터 메모리 100번지의 내용을 +1증가 시킨다.

상수 포인터

메모리 영역의 종류를 나타내는 1바이트와 어드레스를 나타내기 위한 2바이트로 구성 모두 3바이트가 컴파이러에 저장된다.

외부 데이터 메모리의 8000h 어드레스에 대한 포인터를 생성하기 위해 다음과 같이 포인터 상수 정의 #define PORT(*(chat*)0x018000)

상수 포인터를 사용하여 외부램의 최하위 바이트 PDATA 메모리 영역을 지정할 수 있다. MOVX@RO형태를 사용하여 발생 할수 있다.

#define PDATA_PORT(*char*)0x30008)

ex) 외부데이터 메모리 3000h 어드레스에 대한 포인터를 생성하기 위해서

#define PORT(*(char*)0x0130000)

#define PDATA_PORT(*(char*)0x030008)

1999. 8.

미래의 블럭로봇의 선구두자 로보블럭시스템에서 드리는 자료.......

D.S, SHIN