MP STUDIO 2 · 메모리 · V1.3.0부터

MP STUDIO 2 · 인덱스 주소(포인터)

인덱스 주소는 D100[D0]처럼 앞 주소에 인덱스 값을 더한 칸을 명령이 읽고 쓰게 하는 기능입니다(V1.3.0부터). D0이 3이면 그 명령은 D103을 씁니다. 인덱스 값만 바꾸어 레시피 설정값이나 기록 버퍼처럼 표 형태로 놓인 데이터를 차례로 다룰 수 있습니다.

예제 보기 쓰는 법

예제 프로그램을 시뮬레이션하며 인덱스 칸에 값과 가리킨 칸이 함께 표시된 MP STUDIO 2 창 전체

쓰는 꼴 가리킬 영역 인덱스 지원 판
D100[D0] DㆍDDㆍCㆍDCㆍR DㆍC 워드ㆍ##이름 V1.3.0부터

이 페이지에서

쓰는 법

인덱스 주소의 꼴은 앞주소[인덱스]입니다. *D0ㆍ&D100 같은 C 언어의 포인터 꼴은 쓸 수 없습니다.

  1. 래더에서 명령의 값 칸(예: MOVE의 IN)을 선택하고 D100[D0]을 입력해주시기 바랍니다. 펑션 삽입 창(Ctrl+E)에 MOVE D100[D0] D200처럼 한 줄로 입력해도 됩니다.
  2. 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(으)로 적었습니다.»처럼 알림이 표시됩니다.

그림 1. MOVE의 IN에 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])를 쓸 수 없어 컴파일되지 않습니다. 이 칸에는 상수(숫자)를 입력하세요.»

그림 2. 타이머의 TIMER 칸에 적어 붉게 표시된 인덱스 주소와 인스펙터에 표시된 이유

범위 밖과 @IXERR

실행 중에 인덱스가 가리킨 원소가 그 영역(데이터 메모리에서 정한 크기) 밖이면 장비는 다음과 같이 동작합니다.

모니터링ㆍ시뮬레이션 중에는 @IXERR가 켜지는 순간 알림이 표시되고, 장비가 마지막으로 건너뛴 명령의 행이 함께 표시됩니다(탭이 둘 이상이면 탭 이름도 함께). 래더에 @IXERR 접점이 없어도 알림은 표시됩니다.

그림 3. 시뮬레이션에서 인덱스가 범위를 벗어난 모습

@IXERR는 저절로 꺼지지 않음
@IXERR는 인덱스가 범위 안으로 돌아와도 켜진 채로 남습니다. 래더의 RESET 코일(@IXERR)로 끄거나, 모니터링ㆍ시뮬레이션 중 데이터 테이블에서 0을 써서 꺼주시기 바랍니다. 다른 @ 시스템 비트와 달리 @IXERR에는 0을 쓸 수 있습니다. 다운로드하면 꺼진 상태로 시작합니다.

@IXERR는 비트 제어 펑션의 BSFTㆍBRSTㆍBSETN이 실행 중 영역을 벗어나거나 TFLK의 한 주기가 타이머에 담기지 않을 때도 켜집니다(V1.4.0부터). 인덱스 주소를 쓰지 않은 프로그램에서는 @IXERR가 래더 화면이나 데이터 테이블에 있을 때만 알림이 표시되므로, 래더의 @IXERR 접점으로 확인해주시기 바랍니다.

입력 도움

인덱스 후보 목록

칸 입력 상자(접점 편집ㆍ펑션 인자 칸ㆍ펑션 삽입ㆍ펑션 편집 창)에 D100[까지 입력하면 인덱스로 쓸 수 있는 것만 목록으로 표시됩니다. 인덱스 후보 — 프로젝트에서 쓴 주소에는 지금 탭에서 쓴 주소 중 인덱스로 쓸 수 있는 DㆍC 워드 주소와 ##이름 사용자 워드가, 등록된 심볼에는 그런 주소의 심볼이 묶음마다 8개까지 표시됩니다.

그림 4. 펑션 삽입 창에 MOV D100[까지 입력했을 때 표시되는 인덱스 후보

↑ㆍ↓로 후보를 고르고 Tab 또는 Enter를 누르면 들어가며(고르지 않고 Tab을 누르면 첫 후보), 마우스로 눌러도 됩니다. 고르면 [ 뒤만 바뀌고 ]가 붙습니다(이미 있으면 붙이지 않습니다). [ 앞이 DㆍDDㆍCㆍDCㆍR이 아니거나 인덱스 주소를 받지 않는 칸이면 평소의 자동완성이 표시됩니다.

심볼로 쓰기

앞 주소와 인덱스에 심볼을 쓸 수 있습니다. RECIPE가 D100, IDX가 D0의 심볼이면 칸에 RECIPE[IDX]를 입력해도 D100[D0]으로 저장됩니다. 보기 → 심볼 표시를 켜면 칸에 «RECIPE[IDX]»가 표시되고, 설명문은 앞 주소의 것이 표시됩니다. 심볼 테이블에 인덱스 주소 꼴을 심볼로 등록할 수는 없습니다.

그림 5. 심볼 표시를 켠 래더의 RECIPE[IDX] 칸

같은 주소 밝힘과 줄바꿈

커서를 D0 칸에 두면 D0을 인덱스로 쓰는 칸에 점선 테두리가 표시되고, 커서를 D100[D0] 칸에 두면 D100ㆍD0 칸도 함께 밝게 표시됩니다. 칸 안에서 긴 주소는 [ 앞에서 줄을 바꾸어 표시합니다(DD1000 / [D10]). 인쇄도 같습니다.

모니터링과 시뮬레이션

모니터링ㆍ시뮬레이션 중에는 인덱스 칸에 값과 지금 가리킨 칸이 함께 표시됩니다. 시뮬레이션에서도 범위 검사와 @IXERR, 알림의 마지막 행이 장비와 같이 동작합니다. 시뮬레이션되지 않는 펑션(PUT 등)에서도 범위 검사와 @IXERR는 동작합니다.

그림 6. 시뮬레이션 중 인덱스 칸에 표시된 값과 가리킨 칸

표시 뜻
«2000 (→D103)» 값과 가리킨 칸입니다. 더블워드는 «70000 (→DD102)»처럼 표시됩니다.
«— (→?)»(흐린 글자) 그 명령이 아직 한 번도 실행되지 않아 가리킨 칸과 값을 모릅니다(캔버스와 인스펙터에만 표시).
«범위 밖 (D0 = -200)»(붉은 글자) 지금 인덱스가 범위 밖입니다.

캔버스와 인스펙터의 현재 값은 그 명령이 마지막으로 실행될 때 가리킨 칸을, 감시 카드와 데이터 테이블은 지금 인덱스 값이 가리키는 칸을 같은 꼴로 표시합니다. 렁이 꺼져 명령이 실행되지 않는 동안 인덱스를 바꾸면 두 쪽이 서로 다른 칸을 보일 수 있습니다. GMOVE의 IN 같은 블록 칸은 «(→D252)»처럼 시작 칸만 표시합니다. 비교 접점의 통전은 장비가 실제로 비교한 결과로 표시되며, 범위 밖이거나 아직 실행되지 않은 칸은 거짓입니다. 인덱스 값이 바뀐 직후에는 값을 한 번 더 읽을 때까지 가리킨 칸 표시가 늦게 따라옵니다.

값 쓰기

인덱스 칸을 선택하고 메모리에 값 쓰기(Alt+Enter)를 열면 주소에 «D100[D0] → D103에 씁니다»처럼 지금 가리킨 칸이 표시되며, 값은 그 칸에 씁니다. 아직 한 번도 실행되지 않은 칸에는 쓸 수 없습니다.

그림 7. 인덱스 칸에서 연 메모리에 값 쓰기 창

데이터 테이블

데이터 테이블의 행에 D100[D0]을 넣으면 값이 «2000 (→D103)»처럼 표시되고, 값을 쓰면 지금 가리킨 칸에 씁니다. 인덱스가 범위 밖이거나 가리킨 칸을 아직 모르면 보내지 않고 이유를 표시합니다. 심볼 칸에는 «RECIPE[IDX]»가 표시되며, 그 칸에 RECIPE[D7]처럼 입력하면 주소가 D100[D7]이 됩니다.

그림 8. 인덱스 주소 행이 있는 데이터 테이블

사용한 데이터

실행 → 사용한 데이터에서는 앞 원소와 인덱스 레지스터가 쓰인 칸으로 칠해지고, 앞 원소부터 그 영역의 끝까지는 인덱스로 접근할 수 있는 칸으로 빗금이 표시됩니다. 인덱스가 ##이름 사용자 워드이면 그 인덱스는 이 창에 표시되지 않습니다.

그림 9. 사용한 데이터 창에서 D100 뒤로 인덱스로 접근할 수 있는 칸(D 메모리)

예제

두 예제는 MPA-8A8R(T)의 새 프로젝트(데이터 메모리 기본값)에 차례로 작성해 시뮬레이션으로 확인할 수 있습니다.

예제 1. 레시피 번호로 설정값 고르기

D100~D109에 레시피 10개의 설정값을 두고, P0을 누를 때마다 다음 레시피의 값을 D200으로 옮기는 예제입니다.

  1. 설정 → 심볼에서 D100에 RECIPE, D0에 IDX, D200에 NOW_SV, P0에 NEXT_BTN, M0에 IXERR_LAMP를 등록해주시기 바랍니다.
  2. 아래 렁을 작성해주시기 바랍니다.
렁 입력 펑션ㆍ코일 하는 일
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칸에 차례로 기록하고, 끝에 닿으면 처음부터 덮어쓰는 예제입니다.

  1. 설정 → 심볼에서 D10에 TEMP, D1에 POS, D150에 LOG를 등록해주시기 바랍니다.
  2. 예제 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을 써주시기 바랍니다.

확인할 점

관련 문서

← MP STUDIO 2 사용설명서로 돌아가기