MP STUDIO 2 · 메모리 · V1.3.0부터
MP STUDIO 2 · 인덱스 주소(포인터)
인덱스 주소는 D100[D0]처럼 앞 주소에 인덱스 값을 더한 칸을 명령이 읽고 쓰게 하는 기능입니다(V1.3.0부터). D0이 3이면 그 명령은 D103을 씁니다. 인덱스 값만 바꾸어 레시피 설정값이나 기록 버퍼처럼 표 형태로 놓인 데이터를 차례로 다룰 수 있습니다.
| 쓰는 꼴 | 가리킬 영역 | 인덱스 | 지원 판 |
|---|---|---|---|
D100[D0] | DㆍDDㆍCㆍDCㆍR | DㆍC 워드ㆍ##이름 | V1.3.0부터 |
- 배열처럼 세기
인덱스는 원소 단위로 셉니다.DDㆍDC는 원소 하나가 번호 2개입니다. - 범위 밖은 건너뜀
가리킨 칸이 영역 밖이면 그 명령만 건너뛰고@IXERR를 켭니다. 다른 메모리를 덮어쓰지 않습니다. - 가리킨 칸 표시
모니터링ㆍ시뮬레이션 중 인덱스 칸에 «2000 (→D103)»처럼 값과 가리킨 칸이 함께 표시됩니다. - 안 쓰면 그대로
인덱스 주소를 쓰지 않은 프로그램은 메모리와 실행 시간이 전과 같습니다.
이 페이지에서
쓰는 법
인덱스 주소의 꼴은 앞주소[인덱스]입니다. *D0ㆍ&D100 같은 C 언어의 포인터 꼴은 쓸 수 없습니다.
- 래더에서 명령의 값 칸(예:
MOVE의 IN)을 선택하고D100[D0]을 입력해주시기 바랍니다. 펑션 삽입 창(Ctrl+E)에MOVE D100[D0] D200처럼 한 줄로 입력해도 됩니다. Enter로 칸을 확정해주시기 바랍니다. 소문자와 괄호 안팎의 빈칸은 확정할 때 정리됩니다(d100[ d0 ]→D100[D0]).
인덱스는 C 언어의 배열처럼 원소 단위로 셉니다. DㆍCㆍR은 인덱스만큼 떨어진 칸을, 원소 하나가 번호 2개를 차지하는 DDㆍDC는 인덱스의 2배만큼 떨어진 칸을 가리키므로 원소끼리 겹치지 않습니다.
| 칸에 적은 주소 | 인덱스 값 | 명령이 쓰는 칸 |
|---|---|---|
D100[D0] | D0 = 3 | D103 |
C10[D1] | D1 = 5 | C15 |
DD100[D0] | D0 = 1 | DD102(D102ㆍD103) |
R5[D0] | D0 = 2 | R7 |
인덱스에 숫자를 적으면 고정 주소로 바뀝니다. D100[3]은 D103으로, DD100[3]은 DD106으로, R5[2]는 R7로 적히고 «D100[3]을(를) D103(으)로 적었습니다.»처럼 알림이 표시됩니다.
가리킬 영역과 인덱스
| 구분 | 쓸 수 있는 것 | 쓸 수 없는 것 |
|---|---|---|
| 앞 주소(가리킬 영역) | D 워드ㆍDD 더블워드ㆍC 워드ㆍDC 더블워드ㆍR 실수 | PㆍMㆍTㆍBDㆍWMㆍ사용자 변수 등 |
| 인덱스(괄호 안) | DㆍC 워드 주소, ##이름 사용자 워드(예: D100[##IDX]) | DDㆍDCㆍRㆍ###이름ㆍ#이름 |
겹친 괄호(D100[D0[D1]]), 비트 꼬리(D100[D0].3), 괄호 안의 주소 둘도 쓸 수 없습니다. 쓸 수 없는 것을 적거나, 앞 주소의 번호가 음수이거나, 인덱스가 데이터 메모리 영역 밖의 번호(예: D100[D9999])이면 칸이 붉게 표시되고 컴파일되지 않습니다.
인덱스 값은 부호 있는 16비트(-32768~32767)로 읽으므로 음수 인덱스로 앞쪽 칸을 가리킬 수도 있습니다. 가리킬 수 있는 범위는 데이터 메모리에서 정한 그 영역의 크기이며, 범위를 벗어나면 범위 밖과 @IXERR에서 설명하는 대로 동작합니다.
인덱스 값은 명령이 시작할 때 한 번 읽습니다. 같은 명령이 인덱스를 바꾸어도 결과는 처음에 가리킨 칸에 씁니다. 예를 들어 DIV 7 2 D100[D0] D0은 나머지를 D0에 쓰고, 몫은 명령이 시작할 때 D0이 가리킨 칸에 씁니다.
쓸 수 있는 명령과 칸
인덱스 주소는 명령의 값 칸과 비교 접점에 쓸 수 있습니다. 가리킨 칸의 주소를 그 자리에 직접 적었을 때와 같이 동작하며, 주황색 경고도 같은 조건에서 표시됩니다.
| 분류 | 인덱스 주소를 쓸 수 있는 칸 |
|---|---|
| 비교 | 비교 펑션의 IN1ㆍIN2, 접점 칸에 적은 비교(예: D100[D0]>D9) |
| 변환 | H2DㆍD2HㆍINVㆍNEG의 INㆍOUT |
| 수학 | ADDㆍSUBㆍMULㆍDIV의 모든 칸, INCㆍDEC, SCALE의 여섯 칸, FLOORㆍSQRT |
| 카운터 | CTUㆍCTDㆍCTUD의 SET VALUE, HCNTㆍENCODERㆍENMOVㆍHRST |
| 타이머 | TONㆍTOFFㆍTPLㆍTMONㆍTMR의 SET VALUE |
| 워드 논리 | WANDㆍWORㆍWXORㆍSHLㆍSHRㆍSWAP의 모든 칸 |
| 아날로그 | ADCㆍADC2ㆍDAC의 모든 칸, AFILTER, NTEMPㆍPTEMP, PWMㆍFPWMㆍFDPWMㆍNPWMㆍPOFFㆍPSR, PID의 모든 칸, PID_PWM(PORT 제외) |
| MOVE | MOVEㆍGMOVEㆍFMOVE의 모든 칸 |
| 데이터 처리 | MAXㆍMINㆍSUMㆍAVEㆍMUXㆍENCOㆍDECO의 모든 칸 |
| 시리얼 포트 | PUT의 CHANNELㆍDATAㆍLENGTH, GET의 CHANNELㆍLENGTHㆍOUT, PUT_LENㆍGET_LEN, SERIDㆍSERRATE, MNETㆍMNET_READ |
| I2C | ISTA의 ADDRESS, IWR, IRD의 OUT, ISR, IBR |
| CLCD (문자 LCD) | CINIㆍCLOCㆍCSTRㆍCINTㆍCREALㆍCHEXㆍCCLSㆍCCONㆍCCOFㆍCPUTㆍCGET의 ADRㆍ값 칸(아래 쓸 수 없는 칸 제외), CSCR의 PAGE |
| 7세그 | FINT의 INㆍPOSITIONㆍLENGTHㆍDOT, FDATA, FSCR의 PAGE |
| DS3231 (RTC) | DS3231_WRㆍDS3231_RD의 모든 칸 |
GMOVEㆍFMOVEㆍMAXㆍMINㆍSUMㆍAVEㆍMUXㆍPUTㆍGET처럼 여러 칸을 차례로 다루는 명령에서는 인덱스 주소가 시작 칸이 됩니다.
블록 명령은 끝 칸이 영역 밖이면 실행되지 않음
시작 원소부터 그 명령이 닿는 끝 칸까지 영역 안에 있어야 합니다. 닿는 범위는GMOVEㆍFMOVEㆍMAX등은 N개 원소,MUX는 N번째 원소,PUTㆍGET은 LENGTH 바이트입니다. 예를 들어 D 영역이D0~D255일 때D0이 152이면GMOVE D100[D0] D200 5의 IN은D252~D256이 되어 범위 밖입니다.MUX를 뺀 명령은 N이 0이면(MAXㆍMINㆍSUMㆍAVE는 N이 0 이하이면) 아무것도 하지 않고 범위도 검사하지 않습니다.MUX는 N이 0이면 시작 원소를 고릅니다.
쓸 수 없는 칸
아래 칸에 인덱스 주소를 적으면 칸이 붉게 표시되고 컴파일되지 않습니다. 칸을 선택하면 인스펙터에, 칸에 마우스를 올리면 툴팁에 이유가 표시됩니다.
| 구분 | 칸 | 표시되는 이유 |
|---|---|---|
| 고정 주소만 받는 칸 | 접점ㆍ코일ㆍ엣지 칸, 타이머의 TIMER(T0)ㆍ카운터의 COUNT(C0), CTU의 RESETㆍCTD의 SETㆍCTUD의 CUㆍCDㆍRESET, JMPㆍJMPNㆍLABEL, ISTA의 READ, IRD의 ACK, CINI의 TYPE, CPUT의 DEFINE, CSTR의 STRING, CINTㆍCREALㆍFINT의 ZEROㆍSIGN, CHEX의 ZERO, PID_PWM의 PORT | «D100[D0]은(는) 인덱스 주소라 이 칸에 쓸 수 없어 컴파일되지 않습니다. 인덱스 주소는 명령의 값 칸(예: MOV의 IN·OUT)과 비교 접점에만 씁니다 — 이 칸에는 D100 같은 고정 주소를 입력하세요.» |
| 상수만 받는 칸 | CSCR의 ADR, FSCR의 DSP, MCSㆍMCSCLR의 NUM, FINI의 CLKㆍDIO, MBTRIGㆍUPTRIG의 NO, CREAL의 DIGIT | «CSCR의 ADR 칸은 상수만 받아 인덱스 주소(D100[D0])를 쓸 수 없어 컴파일되지 않습니다. 이 칸에는 상수(숫자)를 입력하세요.» |
범위 밖과 @IXERR
실행 중에 인덱스가 가리킨 원소가 그 영역(데이터 메모리에서 정한 크기) 밖이면 장비는 다음과 같이 동작합니다.
- 그 명령만 건너뜁니다. 다른 메모리를 덮어쓰지 않습니다.
- 그 명령의 전원 출력은 꺼집니다. 비교 접점은 거짓이 되어 뒤의 코일이 꺼집니다.
- 시스템 비트
@IXERR가 켜집니다. 타이머ㆍ카운터의 SET VALUE는 렁이 꺼져 있어도 범위를 검사하므로 그때도 켜집니다.
모니터링ㆍ시뮬레이션 중에는 @IXERR가 켜지는 순간 알림이 표시되고, 장비가 마지막으로 건너뛴 명령의 행이 함께 표시됩니다(탭이 둘 이상이면 탭 이름도 함께). 래더에 @IXERR 접점이 없어도 알림은 표시됩니다.
- ① 범위 밖 칸:
D0이 -200이라D100보다 앞쪽 영역 밖을 가리켜 붉은 «범위 밖 (D0 = -200)»으로 표시됩니다.MOVE를 건너뛰어D200은 앞의 값 그대로입니다. - ②
@IXERR렁:@IXERR가 켜져 뒤의 코일이 켜졌습니다. - ③ 알림: «인덱스가 범위를 벗어났습니다 — @IXERR가 켜졌고 그 명령은 건너뛰었습니다. (마지막: 0행)»
@IXERR는 저절로 꺼지지 않음
@IXERR는 인덱스가 범위 안으로 돌아와도 켜진 채로 남습니다. 래더의 RESET 코일(@IXERR)로 끄거나, 모니터링ㆍ시뮬레이션 중 데이터 테이블에서 0을 써서 꺼주시기 바랍니다. 다른@시스템 비트와 달리@IXERR에는 0을 쓸 수 있습니다. 다운로드하면 꺼진 상태로 시작합니다.
@IXERR는 비트 제어 펑션의 BSFTㆍBRSTㆍBSETN이 실행 중 영역을 벗어나거나 TFLK의 한 주기가 타이머에 담기지 않을 때도 켜집니다(V1.4.0부터). 인덱스 주소를 쓰지 않은 프로그램에서는 @IXERR가 래더 화면이나 데이터 테이블에 있을 때만 알림이 표시되므로, 래더의 @IXERR 접점으로 확인해주시기 바랍니다.
입력 도움
인덱스 후보 목록
칸 입력 상자(접점 편집ㆍ펑션 인자 칸ㆍ펑션 삽입ㆍ펑션 편집 창)에 D100[까지 입력하면 인덱스로 쓸 수 있는 것만 목록으로 표시됩니다. 인덱스 후보 — 프로젝트에서 쓴 주소에는 지금 탭에서 쓴 주소 중 인덱스로 쓸 수 있는 DㆍC 워드 주소와 ##이름 사용자 워드가, 등록된 심볼에는 그런 주소의 심볼이 묶음마다 8개까지 표시됩니다.
↑ㆍ↓로 후보를 고르고 Tab 또는 Enter를 누르면 들어가며(고르지 않고 Tab을 누르면 첫 후보), 마우스로 눌러도 됩니다. 고르면 [ 뒤만 바뀌고 ]가 붙습니다(이미 있으면 붙이지 않습니다). [ 앞이 DㆍDDㆍCㆍDCㆍR이 아니거나 인덱스 주소를 받지 않는 칸이면 평소의 자동완성이 표시됩니다.
심볼로 쓰기
앞 주소와 인덱스에 심볼을 쓸 수 있습니다. RECIPE가 D100, IDX가 D0의 심볼이면 칸에 RECIPE[IDX]를 입력해도 D100[D0]으로 저장됩니다. 보기 → 심볼 표시를 켜면 칸에 «RECIPE[IDX]»가 표시되고, 설명문은 앞 주소의 것이 표시됩니다. 심볼 테이블에 인덱스 주소 꼴을 심볼로 등록할 수는 없습니다.
같은 주소 밝힘과 줄바꿈
커서를 D0 칸에 두면 D0을 인덱스로 쓰는 칸에 점선 테두리가 표시되고, 커서를 D100[D0] 칸에 두면 D100ㆍD0 칸도 함께 밝게 표시됩니다. 칸 안에서 긴 주소는 [ 앞에서 줄을 바꾸어 표시합니다(DD1000 / [D10]). 인쇄도 같습니다.
모니터링과 시뮬레이션
모니터링ㆍ시뮬레이션 중에는 인덱스 칸에 값과 지금 가리킨 칸이 함께 표시됩니다. 시뮬레이션에서도 범위 검사와 @IXERR, 알림의 마지막 행이 장비와 같이 동작합니다. 시뮬레이션되지 않는 펑션(PUT 등)에서도 범위 검사와 @IXERR는 동작합니다.
- ① 인덱스 칸: «2000 (→D103)»처럼 값과 지금 가리킨 칸이 표시됩니다.
- ② 인덱스
D0: 인덱스 레지스터의 값(3)입니다. - ③ 결과
D200:MOVE가 옮긴 값(2000)입니다.
| 표시 | 뜻 |
|---|---|
| «2000 (→D103)» | 값과 가리킨 칸입니다. 더블워드는 «70000 (→DD102)»처럼 표시됩니다. |
| «— (→?)»(흐린 글자) | 그 명령이 아직 한 번도 실행되지 않아 가리킨 칸과 값을 모릅니다(캔버스와 인스펙터에만 표시). |
| «범위 밖 (D0 = -200)»(붉은 글자) | 지금 인덱스가 범위 밖입니다. |
캔버스와 인스펙터의 현재 값은 그 명령이 마지막으로 실행될 때 가리킨 칸을, 감시 카드와 데이터 테이블은 지금 인덱스 값이 가리키는 칸을 같은 꼴로 표시합니다. 렁이 꺼져 명령이 실행되지 않는 동안 인덱스를 바꾸면 두 쪽이 서로 다른 칸을 보일 수 있습니다. GMOVE의 IN 같은 블록 칸은 «(→D252)»처럼 시작 칸만 표시합니다. 비교 접점의 통전은 장비가 실제로 비교한 결과로 표시되며, 범위 밖이거나 아직 실행되지 않은 칸은 거짓입니다. 인덱스 값이 바뀐 직후에는 값을 한 번 더 읽을 때까지 가리킨 칸 표시가 늦게 따라옵니다.
값 쓰기
인덱스 칸을 선택하고 메모리에 값 쓰기(Alt+Enter)를 열면 주소에 «D100[D0] → D103에 씁니다»처럼 지금 가리킨 칸이 표시되며, 값은 그 칸에 씁니다. 아직 한 번도 실행되지 않은 칸에는 쓸 수 없습니다.
데이터 테이블
데이터 테이블의 행에 D100[D0]을 넣으면 값이 «2000 (→D103)»처럼 표시되고, 값을 쓰면 지금 가리킨 칸에 씁니다. 인덱스가 범위 밖이거나 가리킨 칸을 아직 모르면 보내지 않고 이유를 표시합니다. 심볼 칸에는 «RECIPE[IDX]»가 표시되며, 그 칸에 RECIPE[D7]처럼 입력하면 주소가 D100[D7]이 됩니다.
사용한 데이터
실행 → 사용한 데이터에서는 앞 원소와 인덱스 레지스터가 쓰인 칸으로 칠해지고, 앞 원소부터 그 영역의 끝까지는 인덱스로 접근할 수 있는 칸으로 빗금이 표시됩니다. 인덱스가 ##이름 사용자 워드이면 그 인덱스는 이 창에 표시되지 않습니다.
- ① 쓰인 칸: 앞 원소(그림에서는
D100)와 인덱스 레지스터가 칠해집니다. - ② 빗금: 인덱스로 접근할 수 있는 칸입니다. 마우스를 올리면 «D100[D0]이(가) 여기까지 도달할 수 있습니다 · 음수 인덱스면 앞쪽 주소에도 도달합니다»가 표시됩니다.
- ③ 범례: 인덱스로 접근할 수 있음
예제
두 예제는 MPA-8A8R(T)의 새 프로젝트(데이터 메모리 기본값)에 차례로 작성해 시뮬레이션으로 확인할 수 있습니다.
예제 1. 레시피 번호로 설정값 고르기
D100~D109에 레시피 10개의 설정값을 두고, P0을 누를 때마다 다음 레시피의 값을 D200으로 옮기는 예제입니다.
- 설정 → 심볼에서
D100에 RECIPE,D0에 IDX,D200에 NOW_SV,P0에 NEXT_BTN,M0에 IXERR_LAMP를 등록해주시기 바랍니다. - 아래 렁을 작성해주시기 바랍니다.
| 렁 | 입력 | 펑션ㆍ코일 | 하는 일 |
|---|---|---|---|
| 0 | @ON | MOVE D100[D0] D200 | 고른 레시피의 값을 D200으로 옮깁니다. |
| 1 | P0 → 상승 엣지 | INC D0 | P0을 누를 때마다 다음 레시피를 고릅니다. |
| 2 | D0>=10(비교 접점) | MOVE 0 D0 | 10번째를 넘으면 첫 레시피로 돌아갑니다. |
| 3 | @IXERR | 코일 M0 | 인덱스가 범위를 벗어나면 켜집니다. |
실행 → 시뮬레이션을 시작하고 데이터 테이블에서 D100~D104에 1200ㆍ1500ㆍ1800ㆍ2000ㆍ2500을 쓴 뒤 P0을 세 번 켰다 꺼주시기 바랍니다. D0이 3이 되면 렁 0의 IN 칸에 «2000 (→D103)»이 표시되고 D200은 2000이 됩니다(그림 6). 데이터 테이블에서 D0에 -200을 쓰면 렁 0이 범위 밖이 되어 건너뛰고 @IXERR와 M0이 켜집니다(그림 3). D0을 0으로 되돌려도 @IXERR는 켜진 채로 남습니다.
예제 2. 측정값을 돌아가며 기록하기
1초마다 D10의 값을 D150~D169 20칸에 차례로 기록하고, 끝에 닿으면 처음부터 덮어쓰는 예제입니다.
- 설정 → 심볼에서
D10에 TEMP,D1에 POS,D150에 LOG를 등록해주시기 바랍니다. - 예제 1의 렁 뒤에 아래 렁을 작성해주시기 바랍니다.
| 렁 | 입력 | 펑션 | 하는 일 |
|---|---|---|---|
| 4 | @100 | MOVE D10 D150[D1] | 1초마다 D10의 값을 D150에서 D1만큼 떨어진 칸에 적습니다. |
| 5 | @100 | INC D1 | 다음 칸으로 넘어갑니다. |
| 6 | D1>=20(비교 접점) | MOVE 0 D1 | 20칸을 다 쓰면 처음 칸으로 돌아갑니다. |
시뮬레이션 중 데이터 테이블에서 D10에 25를 쓰고 몇 초 기다리면 렁 4의 OUT 칸에 «25 (→D157)»처럼 지금 기록하는 칸이 표시됩니다. 사용한 데이터의 D 메모리에서는 D150이 쓰인 칸으로, 그 뒤 영역 끝까지가 인덱스로 접근할 수 있는 칸으로 표시됩니다. @100은 타이머 기준이 10 ms일 때 1초입니다. 타이머 기준을 1 ms로 바꾼 프로젝트에서는 @1000을 써주시기 바랍니다.
확인할 점
- 인덱스 주소는 사용자 메모리(USER MEMORY)를 씁니다. 서로 다른 인덱스 주소 하나마다 6바이트(같은 주소를 여러 칸에 쓰면 한 번만)와 프로그램 전체에 2바이트가 듭니다. 모자라면 컴파일 오류 문장 끝에 «(그중 인덱스 주소 N개가 숨은 영역 M바이트를 씁니다)»가 붙으므로 설정 → 데이터 메모리의 USER MEMORY를 늘려주시기 바랍니다.
- 인덱스 칸마다 실행 시간이 조금 늘어납니다.
- 인덱스 주소는 래더의 칸과 데이터 테이블에서 씁니다. Modbus 장비 표의 바인딩과 CLCD 화면 편집기의 값 칸에는 쓸 수 없습니다.
- 칸의 글자가
[로 시작하면 인덱스 주소가 아니라 북마크로 읽습니다. - 프로젝트 파일(
.mpx)에는 칸에 적은 그대로(D100[D0]) 저장됩니다.


![그림 1. MOVE의 IN에 D100[3]을 적어 D103으로 바뀐 칸과 알림 그림 1. MOVE의 IN에 D100[3]을 적어 D103으로 바뀐 칸과 알림](https://www.ilogics.net/docs/_media/products:mp_studio:ix-fold.png?w=900&tok=1b37dc)


![그림 5. 심볼 표시를 켠 래더의 RECIPE[IDX] 칸 그림 5. 심볼 표시를 켠 래더의 RECIPE[IDX] 칸](https://www.ilogics.net/docs/_media/products:mp_studio:ix-symbol.png?w=1000&tok=1cde6d)

