From 320d2cee1a2e8d78eb4dc25b10d8a9f87a776433 Mon Sep 17 00:00:00 2001 From: Changwoo Park Date: Wed, 17 May 2023 18:24:32 +0900 Subject: [PATCH] =?UTF-8?q?[Timer]=20[Ethenet]=20-=20Timer=20=20=20?= =?UTF-8?q?=E3=84=B4=20=ED=83=80=EC=9D=B4=EB=A8=B8=20=EA=B5=AC=EC=A1=B0=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0=20=20=20=E3=84=B4=20=ED=83=80=EC=9D=B4?= =?UTF-8?q?=EB=A8=B8=20=EC=9D=B8=ED=84=B0=EB=9F=BD=ED=8A=B8=20=EB=82=B4=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=A0=9C=EA=B1=B0,=20=ED=94=8C=EB=9E=98?= =?UTF-8?q?=EA=B7=B8=20=EC=82=BD=EC=9E=85=20(=EC=8B=9C=EB=A6=AC=EC=96=BC?= =?UTF-8?q?=ED=86=B5=EC=8B=A0=20=EB=93=B1=20=EC=A0=9C=EA=B1=B0=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=B4)=20-=20Ethernet=20=20=20=E3=84=B4=20?= =?UTF-8?q?=EC=9D=B4=EB=8D=94=EB=84=B7=20=ED=86=B5=EC=8B=A0=EC=9D=84=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=EB=8F=85=EB=A6=BD=20=EC=8A=A4=EC=BC=80?= =?UTF-8?q?=EC=B9=98=20=EC=83=9D=EC=84=B1=20-=20=EA=B8=B0=ED=83=80=20=20?= =?UTF-8?q?=20=E3=84=B4=20=ED=86=B5=EC=8B=A0=EA=B4=80=EB=A0=A8=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=EC=97=90=EC=84=9C=20CR=20LF=20(\r=20\n)=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=86=A0=EC=BD=9C=20=EC=82=BD=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FC_InferfaceBoard/Ethernet.ino | 100 ++++++++++++ FC_InferfaceBoard/FC_InferfaceBoard.ino | 202 +++++++++--------------- FC_InferfaceBoard/MC9.ino | 34 ++-- FC_InferfaceBoard/Processes.ino | 31 ++-- FC_InferfaceBoard/TCPIP - Write Read.vi | Bin 35194 -> 37786 bytes FC_InferfaceBoard/Utils.ino | 38 ----- FC_InferfaceBoard/periodics.ino | 80 +++++++--- 7 files changed, 270 insertions(+), 215 deletions(-) create mode 100644 FC_InferfaceBoard/Ethernet.ino diff --git a/FC_InferfaceBoard/Ethernet.ino b/FC_InferfaceBoard/Ethernet.ino new file mode 100644 index 0000000..e408fc0 --- /dev/null +++ b/FC_InferfaceBoard/Ethernet.ino @@ -0,0 +1,100 @@ +// +void Ethernet_setup(){ + byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x00 }; + IPAddress ip(192, 168, 20, 177); + IPAddress gateway(192, 168, 20, 1); + IPAddress subnet(255, 255, 255, 0); + + // Mac as unique value by change last byte from ip last value. + mac[5] = ip[3] & 0xFF; + // initialize the ethernet device + Ethernet.begin(mac, ip, gateway, subnet); + // start listening for clients + server.begin(); + web.begin(); + + // Report address + Serial.print("MAC>>"); + for (int i = 0; i < 6; i++) { + if (mac[i] < 16) { + Serial.print("0"); + } + Serial.print(mac[i], HEX); + if (i < 5) { + Serial.print(":"); + } + } + Serial.println(); + Serial.print("IP >>"); + Serial.println(Ethernet.localIP()); +} + +void webReponse(){ + EthernetClient webClient = web.available(); + if (webClient) { + Serial.println("Web client connected"); + while (webClient.connected()) { + if (webClient.available()) { + // 웹 브라우저에서 요청이 도착한 경우 + String request = webClient.readStringUntil('\r'); + //Serial.println(request); + webClient.flush(); + + // 웹 브라우저에 출력할 문구 작성 + String response = "HTTP/1.1 200 OK\r\n"; + response += "Content-Type: text/html\r\n\r\n"; + response += ""; + response += Prcss_AI(); + //response += "

Hello, World!

"; + response += ""; + + // 문구를 웹 브라우저로 전송 + webClient.print(response); + delay(1); + + // 클라이언트 연결 종료 + webClient.stop(); + } + } + } + +} + +String demuxCMD(String command, String* rightPart) { + + // "::"를 기준으로 문자열을 분리 + int separatorIndex = command.indexOf("::"); + String leftPart = command.substring(0, separatorIndex); + *rightPart = command.substring(separatorIndex + 2); + + leftPart.replace(" ", ""); + return leftPart; +} + + +int demuxNum(String rightPart, unsigned int data[]) { + + // 우측의 16진수 배열을 분리하여 추출 + const char* delimiter = ","; + int startIndex = 0; + int endIndex = rightPart.indexOf(delimiter); + int index = 0; + + while (endIndex >= 0) { + String hexValue = rightPart.substring(startIndex, endIndex); + // 16진수 문자열을 16진수 숫자로 변환하여 data 배열에 저장 + data[index] = strtoul(hexValue.c_str(), NULL, 16); + index++; + + startIndex = endIndex + 1; + endIndex = rightPart.indexOf(delimiter, startIndex); + } + + // 남은 마지막 16진수 배열 원소 처리 + String hexValue = rightPart.substring(startIndex); + data[index] = strtoul(hexValue.c_str(), NULL, 16); + index++; + + // 왼쪽 부분인 "ABC"을 반환 + return index; +} diff --git a/FC_InferfaceBoard/FC_InferfaceBoard.ino b/FC_InferfaceBoard/FC_InferfaceBoard.ino index 891bdb3..b29f7bf 100644 --- a/FC_InferfaceBoard/FC_InferfaceBoard.ino +++ b/FC_InferfaceBoard/FC_InferfaceBoard.ino @@ -10,39 +10,47 @@ #define RcvErr "ER\r\n" #define MODE_DEBUG false -String demuxCMD(String command, String* rightPart); -int demuxNum(String rightPart, unsigned int data[]); -// Enter a MAC address and IP address for your controller below. -// The IP address will be dependent on your local network. -// gateway and subnet are optional: -byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x00 }; -IPAddress ip(192, 168, 20, 177); -IPAddress gateway(192, 168, 20, 1); -IPAddress subnet(255, 255, 255, 0); +// ========== ========== Periodic Flags +bool T_10ms = false; +bool T_20ms = false; +bool T_50ms = false; +bool T_100ms = false; +bool T_200ms = false; +bool T_500ms = false; +bool T_500ms_2 = false; +bool T_1000ms = false; + +// ========== ========== Communication +// ---------- Ethernet + +// Ethernet Client +EthernetClient client; // SCPI defaults to port 5025 EthernetServer server(5025); -EthernetClient client; - // HTTP defaults to port 5025 EthernetServer web(80); unsigned long lastDataReceivedTime; unsigned long timeoutPeriod = 5000; // 타임아웃 시간 (5초) -bool busy = false; -bool connection = false; -char buffer[1024]; +bool State_eth = false; + + +// ---------- 485 +String Buf_485; +bool Wait_485; +int Wait_485_cnt; + +// ========== ========== Processing +// Read Datas int Size_AI = 16; int Values_AI[16]; int Size_PV = 8; int Values_PV[8]; -String Buf_485; -bool Wait_485; -int Wait_485_cnt; int msCnt = 0; unsigned long timer = 0; @@ -51,135 +59,107 @@ void setup() { // put your setup code here, to run once: Serial.begin(9600); Serial.println("Start!"); - - TCPIP_setup(mac, ip, gateway, subnet); - - // scitech korea Library + + // modules setup (init.) + Ethernet_setup(); GPIO_setup(); MC9_setup(); // Timer set - MsTimer2::set(10, periodic_10ms); + MsTimer2::set(10, timer_10ms); MsTimer2::start(); - - // Report address - Serial.print("MAC>>"); - for (int i = 0; i < 6; i++) { - if (mac[i] < 16) { - Serial.print("0"); - } - Serial.print(mac[i], HEX); - if (i < 5) { - Serial.print(":"); - } - } - Serial.println(); - Serial.print("IP >>"); - Serial.println(Ethernet.localIP()); - } void loop() { + // wait for a new client: - webReponse(); client = server.available(); - - //Prcss_SV(); - //delay(100); + if (client) { + String Buf_eth; + String message; + String cmd; + String cmdData; + unsigned int data[32]; + int dataSize; + // check if client is connected Serial.println("Client Connected!!!"); // Do What Message Command while(client.connected()){ - int buffCnt = 0; - - // check for command byte - if (client.available() > 0) { - char c; - bool cr = false; - - String command; - String cmd; - unsigned int data[32]; - String message; - int dataSize; - - busy = true; - // Read message by byte - while ((c = client.read())) { - - // Read data until CR or LF - if((c != 13) && (c != 10)){ - command += c; - }else{ + // read data check + if(client.available() > 0) { + char c ;//= client.read(); + + while((c = client.read())) { + //If endwith CRLF + if((c == 10) && (Buf_eth.endsWith("\r"))){ + Buf_eth.remove(Buf_eth.length() - 1); //remove CR + message = Buf_eth; + Buf_eth = ""; break; + }else{ + Buf_eth += c; } } - - // -------------------- Process CMD -------------------- // - cmd = demuxCMD(command, &message); + // 데이터를 수신했으므로 타임아웃 타이머 초기화 + lastDataReceivedTime = millis(); + } + + // If data read + if(message != ""){ + cmd = demuxCMD(message, &cmdData); + message = ""; if(cmd=="AI"){ client.print(Prcss_AI()); }else if(cmd=="AO"){ - dataSize = demuxNum(message, data); + dataSize = demuxNum(cmdData, data); client.print(Prcss_AO(data, dataSize)); + }else if(cmd=="PV"){ client.print(Prcss_PV()); + }else if(cmd=="SV"){ - client.print(Prcss_SV()); + dataSize = demuxNum(cmdData, data); + client.print(Prcss_SV(data, dataSize)); }else if(cmd=="RS"){ - client.print(Prcss_RS(message)); + client.print(Prcss_RS(cmdData)); }//else if(cmd==""){ //} else{ client.print(cmd + " " + RcvErr); - - } - - - // Debug - if(MODE_DEBUG){ - //Serial.print("Received command: "); - //Serial.println(command); } + message = ""; + } + + // Debug + if(MODE_DEBUG){ + //Serial.print("Received command: "); + //Serial.println(command); + } - busy = false; - // 데이터를 수신했으므로 타임아웃 타이머 초기화 - lastDataReceivedTime = millis(); - - }// if end, client.available() - //Serial.println("end client available"); - - // 타임아웃 확인 + // check Timeout if (millis() - lastDataReceivedTime > timeoutPeriod) { Serial.println("Client Disconnected... (Timeout)"); client.stop(); } - + Periodic_run(); } Serial.println("Client Disconnected..."); - } - + Periodic_run(); } -void TCPIP_setup(byte mac[], IPAddress ip, IPAddress gateway, IPAddress subnet){ - mac[5] = ip[3] & 0xFF; - // initialize the ethernet device - Ethernet.begin(mac, ip, gateway, subnet); - // start listening for clients - server.begin(); - web.begin(); -} + void AnalogIn_Print(){ @@ -192,33 +172,3 @@ void AnalogIn_Print(){ -void webReponse(){ - EthernetClient webClient = web.available(); - if (webClient) { - Serial.println("Web client connected"); - while (webClient.connected()) { - if (webClient.available()) { - // 웹 브라우저에서 요청이 도착한 경우 - String request = webClient.readStringUntil('\r'); - //Serial.println(request); - webClient.flush(); - - // 웹 브라우저에 출력할 문구 작성 - String response = "HTTP/1.1 200 OK\r\n"; - response += "Content-Type: text/html\r\n\r\n"; - response += ""; - response += Prcss_AI(); - //response += "

Hello, World!

"; - response += ""; - - // 문구를 웹 브라우저로 전송 - webClient.print(response); - delay(1); - - // 클라이언트 연결 종료 - webClient.stop(); - } - } - } - -} \ No newline at end of file diff --git a/FC_InferfaceBoard/MC9.ino b/FC_InferfaceBoard/MC9.ino index e1db381..cb43b09 100644 --- a/FC_InferfaceBoard/MC9.ino +++ b/FC_InferfaceBoard/MC9.ino @@ -11,15 +11,18 @@ void MC9_setup(){ digitalWrite(RS485_OE_1, Rcv_485); } -void read_mc9_req(){ +void read_mc9_req(String address){ if(!Wait_485){ - String command = "10DRS,03,0011C7\r\n"; + String command = ""; + command += address; + command += "DRS,03,0011C7\r\n"; // Send request to return pv data digitalWrite(RS485_OE_1, Snd_485); delay(5); Serial1.print(command); Serial1.flush(); digitalWrite(RS485_OE_1, Rcv_485); delay(5); + Wait_485 = true; Wait_485_cnt = 0; } @@ -32,34 +35,39 @@ void read_mc9(int arr[], int size){ // Timeout code if(Wait_485){ Wait_485_cnt++; - if(Wait_485_cnt > 200){ // Timeout = periodic(10ms) x 200 = 2sec + if(Wait_485_cnt > 10){ // Timeout = periodic(10ms) x 10 = 10 msec Wait_485 = false; Wait_485_cnt = 0; } } // Receive pv data while(Wait_485 && (Serial1.available() > 0)) { - c = Serial1.read(); - Buf_485 += c; - Serial.print(c, HEX); - Serial.print(" "); + c = Serial1.read(); - if(c == '\n'){ + if((c == '\n') && (Buf_485.endsWith("\r"))){ + Buf_485.remove(Buf_485.length() - 1); //remove CR message = Buf_485; Buf_485 = ""; + Wait_485 = false; Wait_485_cnt = 0; } + else{ + Buf_485 += c; + } } - + // save pv if(message != ""){ - Serial.println(message); + for(int i = 0 ; i < size ; i++){ + //arr[i] = ???; + } } } void write_mc9(int arr[], int size){ - cli();//stop interrupts - Serial1.print("485 Write^^"); //Serial Write ADC_Value to RS-485 Bus - sei();//allow interrupts + digitalWrite(RS485_OE_1, Snd_485); delay(5); + Serial1.print("485 Write^^\r\n"); //Serial Write ADC_Value to RS-485 Bus + Serial1.flush(); + digitalWrite(RS485_OE_1, Rcv_485); delay(5); } \ No newline at end of file diff --git a/FC_InferfaceBoard/Processes.ino b/FC_InferfaceBoard/Processes.ino index c906066..5cc8bd4 100644 --- a/FC_InferfaceBoard/Processes.ino +++ b/FC_InferfaceBoard/Processes.ino @@ -1,13 +1,13 @@ +// String Prcss_AI(){ - String str = ""; - for (int i = 0; i < Size_AI; i++) { - char formattedNumber[5]; // 4자리 숫자 + 널 종료 문자 - sprintf(formattedNumber, "%04X", Values_AI[i]); // 4자리로 고정된 형식의 문자열 생성 - str += formattedNumber; // 형식화된 문자열 추가 - //str += String(AI_VALUES[i]); - str += ','; - } + + for (int i = 0; i < Size_AI; i++) { + char formattedNumber[5]; // 4자리 숫자 + 널 종료 문자 + sprintf(formattedNumber, "%04X", Values_AI[i]); // 4자리로 고정된 형식의 문자열 생성 + str += formattedNumber; // 형식화된 문자열 추가 + str += ','; + } str += RcvOK; return str; @@ -29,18 +29,23 @@ String Prcss_RS(String message){ } String Prcss_PV(){ + String str = ""; + + for (int i = 0; i < Size_PV; i++) { + char formattedNumber[5]; // 4자리 숫자 + 널 종료 문자 + sprintf(formattedNumber, "%04X", Values_PV[i]); // 4자리로 고정된 형식의 문자열 생성 + str += formattedNumber; // 형식화된 문자열 추가 + str += ','; + } - String str = "PV "; - digitalWrite(RS485_OE_1, Snd_485); - Serial1.print("485 Read!!"); //Serial Write ADC_Value to RS-485 Bus str += RcvOK; return str; } -String Prcss_SV(){ +String Prcss_SV(unsigned int data[], int dataSize){ String str = "SV "; - + write_mc9(data, dataSize); str += RcvOK; return str; diff --git a/FC_InferfaceBoard/TCPIP - Write Read.vi b/FC_InferfaceBoard/TCPIP - Write Read.vi index 5ea2f966ba55d497d2d2bbcbc5251fb39b678758..6973b410ac208da05261050538505b17c9a0fa7f 100644 GIT binary patch delta 18661 zcmX`S19&7&+rJ&#wzaX1jcwbuo!Mk#+vdi$y>YU!xzWaUzRCT(|F4gu`ghh<=)%=A z(^Wk$iC~#!U?eK4Dx!#RAmDNu(h71S8k!&=G07kxP*5NsAS6I`OCTWxfPkR@qhKJQ zAYh-s1IYjX0oby(V++R=OET}&7wS90115asMFGJE0f7@T3`IZCm1`tC2*375{#YQ4 zUX253fH?U9n|}5r67c^jv4gY~ktxfQsPDGy@1n(}~zef*^(*1!hhgCo+a}7C(#=!fH%CH588jmH!-b9Rq zdPryhgxaUg-J+EyoAkPH9H1tV|3sKRIC@ns&>7r7s__o+U;8nDX9TZoQzPT_@jlQ{ z1Q5t`kOpAGs(^#oxdtfsag zi9!Kk9IW&i#3$4j0*`&4w{ct5JUyA6FsT7ekm$V zVF38v`#n#pCw3`6Z*+TWd5M(_TxgaO=IN7-V=3+KU8M1t)n~TXx)~t-?<$4SKdSsA z+E<1V7e4X%&$~CxcT|yZKmQJ_Z=wjcMhpmjyekk{#_)C__H~3FeF`{1`gO!eeGV(+ zJ$bK2ZI}*z;dyDtI4^JlK|K;>vs}mQFD(G744(V%Ooc_i4ox5g%2*aC9!HOUpMD@d z`W(J{fA&0AdD9nh@jC#B1{w60G4rB1lA#+%WFQa#Yth79AvsF77*P(8 zX;w)wy6XJBlUVpk;eZeur(Tg%C649B(qP1~tQnh#cTiqTy+h;|3~vwvx`>;!iN=Oa z`ntH4YNr&>$iRFRZE$r-#s35M@y{Gi%&Eafsyo&3?qAFJ3gpFqaQwmh-W*%Fg6EpU+Hf;w6yeKm- z#_F~c$?l%_X&TkjY$FDk|4wwas6g2F8yec%r+Ae`J3qfS{b8ZwckKII@7WEYll=y$ZA1|hHDFa(TX2Q_i! zeGGvOSH$L$``#F`Cx1QpXySxg`0rG?ch~SyYg=S_wrM%W0YoGG;QID}ZQt#6|JLxP zjJvq$19s2X^Vfh+uS@^erV~8zc31BS_x+g2J$1|yV{M()>&09?zze@q?bXan$#~u* zHRv|l6I2O{`alXA(x~6nB8A?{@KKVJIb*irKuV_*C~R4$lQ1l{^R9>)@*b@ocifPs zG`G-Pnp7L@KnjXtd2l6Fwn9&eY+HMEHmMkkB zg&yIqjg$rD?wBE>yIZJ3PGV=ti&8;SZtCF z%-}5Q-JoDwk_|stY%)FaXHB|Y5^9_FgS==ua=q;Jj965M?9t(UcbNk95pS5*aJ%v( zCmj|;ogu<|^)?fReOg%TlJu#Bvux3}VYu2yA6QNCwi2@mfCwyCn$vRpB(PP!1-PdZB%) zT6)Tt)WaLPq$%6;E8~wj3}B9&_jGIv4>RkUsjO-M<*Z1a`Ap@u)zj(qWs)b3nL3?> zk}LAv^_CHTgcONwb+0XLvo4~F9~sqOWTU&!BXhMO=45Ge^yP%YiEx&oUyQ1r?LL&5 z`y?Qy#@_P7Rtr3Wa0RSJ46J{wrUVCOUqjIo!|u(eOJ<-;S$Dz0D8;WrxLS3=Lo&RaT zPRwP<`&jV&QWj9~G0m@s6os9>uHRM`cNUc|Aan&Y+$o&sjYH{tpCW!5GY3s^|5wBx zZV~_YowcdJTjm*8Hy6_N`}h9vDobSr+6Xf#07Mh*r>wXYp=MN$pZXt{l35i8+ua+6 zB51m9$Yj576lV-c=P`JlzQO6@B9j{h_cU z3@|OEs1wBJJ_eW*DLK|*cQze2*DPzahnptLMA9!Z*i}}{oGRh25~}e0!=KC8uyPQx z01mk}>yb$V=~8Z#>U|h?3?tDm{DmU{ut9eZ^YM)js)yzFh97_O6jxj-V>bOoj!j7K z2yqF~k14_4XMT<}8XXFggNtQctD$#THJG{cKqgkC>Q!Mf65+5HqC}&OWOYz=w-T|k zK+{^YPoi~xpM&m!j~K%yaZZBLh~<5-1vruPVg=OkssJ+Bc*n)fXt|B~7~!_cuP#~$() zJfqa<*s@c2zl#(&8F8h9Z5lmTI?eM3$N&zPko|5T?jMF;3|$o8VdHH#@Xi+l5`> zy*_?>5k{W=@jA~v7y}U-Tfe9-)CP+B&qv-AzUcgCf$z#J+I(M7^O8MFj6vvng`YrS z9FA+h^Ta?wPATtV3o@58jD5I>E%5VaB$~Rp<(VEMU(m>3#JV#=5t5z0d|X?Xad?`} zq!o8XVj?5UT?tLJZu8(0-blJwi7qYVfv&JcrC{ z>!nR;M~0c#D6L3r1_#G2Y>Yac=o1H%GQBWgcCNrgykh4WerF8VSYuXC8z8c#&gzNX z=nb*%-r}E*#4NnRWj!=eqNA^3CP7O(b_1{7+x>$wc0N&qD9%;@A?jWU_1`Xx21C(( zyVZV>24>R|LOuOZhjdjT8Dpjd$VKF3QX&( z$q)X_F}ghk$HE^eOD4%mUb*nfgv3VNioecXAd#*zQ3wSXXzjXdD^ps52elAe&4;O4 zIh)p(T7nO;`nJ$R&hFdF16YU^d}T!!6Sn&jIK?7KvGd)~W=^+}7-D zsdz@=AyMHIQ%?Rw(l~|5o&a(RG1b zPZX*y&YW!VS4z{IZh4f9#&tZEw*z7KH@Xtd_R?2SxtqlMjq8Za>i?rzXYe`4%RbKb z$_bkQK_B2GNDojf?=!<|EFSn-V6a`WGiZbYGw`BC^GKqCK!9%wZFgQaH9x|l=z{^h z`_Q~G|2teZ>(6T@G`#iTq1ktCjP1kUY$LkpA!_`4{Pl?0@{}s2a+PiOGmYr zWx37XAO(55fDa{4p@zRb@yBPwx}D9;my)|7wbl({(E^8kE7-_%?@<@LSQERn#adM8 z&B`$f&6UPgcx{}!CyI(Pp&qh-}EtifVC%RTr4AR9FHQlAPuwn^JQuIFHd258Eknk}1?- zrC)_r81bP>H&CX1mtemO%`;&6W|#Z_GCy_%jj8-q7hGLf`BOzH_XcjWo^10(Iq&p1 z7H*ShBkK*AQ4WyKg(+J7n(#HXn&)bslv(r-P~_)74^t?d`(0}Y3hJ|2|J zQK}cYo9Lq}6L?q)Nw$T^tL!5iH%gevHz>3e~WW)M3or}) zA%PlEJ2GyrO3D?y8JRJ>t;gBFlPlAbjUk~kQO{~x6VYyV$Wy_*xb-T7kL=VYDq35{L6oF+w{Kaa!xi+NqTw2eK=H=R@& zrx*SYDrIwj7MeFed8f`&Wl9U$%nA$53?L%M==l<|C-+JV$60I>O_oSZLY(EIL z4d>8R5>ma3&0ik0v66qWyufAk@)pG;J)Qh>;i8UAO$a`axWDZUy$4@P`T&5uK29}l z`yo=zY4b*Ce0=(8Jwo$5Y<5b!0gO*Sp7eN_IRq=?d=B}8+RSo6jm|_0uB3_PhTj<; z04vzP%FDbj!#=fAvyxc9dESa&^i;N4rmUgF=7kr4PC% zMysL)n9c@DQgUOt?6CKj)KOPb6y=?175;kAq8S)rmu*#82^!&=gOXFhq%OhK$2b$g6WC&x?vIy42S@^YQxF z7{uxowM=L;h|FmD^}G>BnrK}r;l=zNIA&6WJ;3gU~fB07^ zhYulE|D~LrlYZDzWPo-$5Ohf3>C(>$2(!#nblB)0JGs31#{t;Vp3@E6zw;=p)!)-e z+I7BL1kfXdN9H68utkX2HT7(nf4faj~=YF0)e;0cw}&SZrc@jw;v099z8 z=mx1yy=`Jga(o~bJynELm3(Y)6aK^_$O$#{qGTNR{&PE{b6|wJD^_1H58N|&<94Oi zFXRnY+B8hfQvnbp(|mf2YC3^IooaGsKAf|kf5RQqEaMv-ci8RKjlLU}FSteWgbEvg zxf2{WC`66(m{tjEh-f>?nls3vCkf*K;ibtFRtv^0zdr>MhrWTfOFalfjS}wUm4tZf z+CvmF_%!JjZKRi!`obMeZH_7wmTfpADeGiL>8&bnznX6QcC-6Z$s_ zio^u^WFM3T(!=uGIQsPwX2f$Gj1;LA#1FgwiFY~*!n8{feFN#L9Sx~=v@2eK(8<3# zdGINB)^UJf3&u$uH>?$;D`lq|#IV-Ii?8nyCEED~VeBkrN3boI6px>#E7ea?nwf|` zV0_S+UmtK*aLwMQYem4gjY#+ESi;R73O7)z@sdUQJ> z1&*t)%Dxk@-42FSc$4RwX84B>=y; zxiBs`uDS{xJ|*c!4!vl5?}Xbk?+=}&ZDp^kTH%{p3d|!fs6i}C*svp7%V-1%JG2#C zXN2vs`R_z_>)7j#D#ge>Y>Wmt!>lXywxi3b7y9dNmXfN=Tst4VpgoId^#837l_rs( zR|4#T%bcWN%b!Mmv$$y_s!R==h;E$&|7ZI_e}4e_-NONM1T78pv?_#57``aH#BkV$ zJD5fS8Bhikj$m(j5iEyFF|-a+7;I@FVcE!r04;sSday|~5$um(buAlo4P$HVGr&N( z6)K}OL|W41V3LaYRv)=K3v$6LyU3&A$4}wI-@&g708;UjQ3?l|KBgqGo5-;0@D|00DCxX1}bo)3L^A>`kx;FC*waizy&G;&<^yC|E3Hdm~R0XCjjc# z1;5lDsD!}qbsG@_8|3ys{qo1J_yU`m>lb=6lrpM~# z>CM7Icc8-2hZm?2Nfk186r|0iBNn+66ApfqsV0Ih%IAaXq`T38i{hrAK+9#oBFu9( z!QzNkA}L|h5Eme^F^9AyN$aYl&raN*=Ux;iDWn$SEGG+j3|V+?cW!Q90?uE%`M|66 zENcHw4=|viyjs828-T5gbz-7@a>V`ghkwS9srVN@bU&9`Wpa*Vt62XLu$IYLN0fWt zC9FH4-}EQdE3Yrr3yL2FSowWxX9 zD)%K%f5(J|e9+iH_XU2?X0bM5G7mnToD4v}-T*~M|G$4G(pCCjXuuYx!zt$nzj~ zg6EJt@Djk8zzgRQt^rVY%eSl7f{32Ktkoh^A$y zG*jiU`DSwCYBg5f&FekPJ@(P)_Lce7xltb)ad6340%7nK4fY)s0{w9cId&Qf`e9Nq z{6A8g09B}qG3)nEiVPbh|-RcbNGI4s*zmSyKgN6-MEw6S;9G7l!>c{ zvCHle^MA+3hyn6MVu(Jshq|M4S##H6>0A~zK{YoKvMi$khKV=p88@8*&#(JJ#Vhow zlay`XQA5_}2XrVl_OsQ)2!@Go7_xZJQzcRXkJMQ*Rv=Dp&Qtq(jUZDoF0SZWui~v| zD!44w#_a@y?{)$c3<$Z=*#9-fm-L9(FwHn5>$}(ss z4oyXXAXn^PMvwh;bhpNhicRjR0}Q(ZUN^VKvl*X#y@awT@nq|QxnBvcrR=%dNEiXz zPDg&*S`K-Nk1>B^pWU{#diWlJXcP!MDG)Bx|890RCXU5%+=z-WO>{232K`a-j)&XE zMW8Pp4ZAF}A)5?qw|;q8vGeUBDjK#c6X4b(li|c+DiZUt*UoJDf@{nB@Vg#xRBD+q z)E#Poafw=nU5I=Aou^p^Qk+CY)yBuMn04q(L#hhXtiyO=DR_QzJ`nGwZP|I7#jsZT zf)5nB$*eDS*|Z!l6|Z06g&Eyrd=_Cvn%E5A=cCf54==Gz=-U%_`OaV@oXZ;&FMy8$ zMYB-NY_6Ugm2j7RcnGh98mwNJxLpF9aCg3HuAZm%IJ|=yW15b2000*geT0W8oT;dc zIz3(X3+84+Qd|TsIx=`(Ts%t{%H$OH*GmFaz&w;;cAv7OrZm_`X=T%a5$r0sA=Tya zj-yT*<_F)c91>O)Zqy6;Ku4D38({0#cA5q$4{3(awCaxwKJ4SHnq0+ME`Mu5;q3*! z$62m>Oc?)p4jBK@`yHGg6reKmutvhTYiuB6$20fjpluG4nz-cOd&QVf12(5+{HbB% zSzLMrshQ^!^9yj!Cxt-_sz;v&ca^k$ClddwR31jN>_=>m*4R(9(+Y<><^x=T>w6d} zjqXQYy{SAlpjB^zJ|1nzPG>fxWqJPTZbIJaB}n3~DNOa@Q>IS3QMavGATnR1w5`FA z;7@>2;hV$7a<~cp8MvcBin4(UcljU&UO+-f7wiE;v`g15!cKwk5;7OQO^px>TW}mN z6upUBHr4X2&Xs2Ef)L5e6Be+-V3rOC;SX9%E#n(xHx%ncgCmX{^kLkOeg}*C$vlG1 zi%LFKM~#B9GzYn2mYwpaSN%Hi9loX^ivb&VKzA*w=i&ic64K3Zg%Ix5U2zY$ct!-8 zZ8>|mc?nc<8LU~u-URblXNl3+K1{>+P{!~25YG3-yL2hH9r9bVr2t?SD^K;B2fAx~ z^Ln_oc(G{L0A{dg)pjCVKO?zHa^LI6`py>aq1s+{w~T;}e>O8-hdc+nsBmVb%jo$_ zB>M);<3W{_>mpukN(Z}QxJKGX`5RibY;79$@3Ozh+WKolhx%dEArCMNoR=y3H?B7< z9;_DkW{gvKU@j#;Y+wL&Vj@MxjzrMG&!a^hBz7eunJ7#OKjC0%As4Y#!Oq~n^-`+_ z2<4%9U6*UnYAQg8VnRhkW4NB?u=2Z5Q4{zEGL89w<7_#|4!|f4jI@FN$p3u zdb}uzZ&7TM0O&yVIsEriEkYb(^9#$d9e<}mJ19!&!IwI_TU&34)b*>Z^3zF3F&;bApK{zX^hkBBnO60j~5#k0=h3+cSdatEBTi@0)LFk%~gtYz+2dI6tRrA~UCpmR)6j(Br(cD!>rp<>wT zg^J{1G;bJ!5(wq=v!Hplg6oJf+T%$2Q76GZEcX)%-f~;NX5{~U>qPvgF8^GoTa2x` zfKC{5K;@M`_kg{?NOQNh8dRe(xsQKMVG%-Ti6*^dD5Fj0^)0k>ZKkzXPAO-o$_ z6)pij<#A}Fq{5~crg>8;>=(xKvQTuS%!sJsU!glaO?d`&*wDIOk__wCIs90{Xt?*O ztd=Ttot9=eP`Q$ywD4V9b51x()^D5h-95yTUSV%r`key1`qk{K3PxLTtF1EF1bBou zVj)H}_6aipjxgE<7ekJVyHE^vo$XwL#U9%F2fmhaP0JE71!c;%wK?^2+J539G>F`9 z!YIFS-eg8OZ=$L^%c*Bnq*5Ako}L&^KUxoynvyKxmVytKA#Fr%vg|VB`E$ii!$T9k z$LEw_&z)TRypt;npDPk=$%95}cx=$T1}D@36iL_tc(_D^)`NrL!p5>gabZzE6mvqQ z9-g~F^9+SQ)9Xyxk4rxHaFN7DX>26I{MEFPVp+sbi})r<8b*oDPLtZvlw&umCGk$;L9XrSlSGW-YElle2x+qL~YjK*B4$w?L zrntrhh#j^5%~P85CRgi+bW)+_9rLw9Mk^y10!tew?kiUCO6;91zw+~P2&R6v<=pkQ z%v9);Wp~~zJ3y85`}5D;V(5KJ$uB_2bLF+uBQw^~rCj;apW`%V;or9xv1-l% zp}6*m8ud$SddlgMj(egI-PW-h^|T|yM%JxTj@g=&d+I*vf}cf2Quc2nFW8D{C51)l zEe@I9u`Jr|xS7z?>}|7}3}KhVw3BABa(_1ZG~!@}7YZ*MMoQ}EeLWe4o72zg1BzN) zfXPRS8CkDeuJrV?e13@csr;P1{5w)=H04$glSv}FYoET%4px5J4?(tGmVc6U6Sq$o zJ-^nE;9toTnp)3sDh4yO4Hzs8_o^(st*8rER+An`E#Vt~Vp-5-MZfHc`0%!e~&w z`$q73!1B6jW*FA^D5JD*p!?j=ZHcWH^hRU=Oi2(B5iqapVLf;+HSttI_sjG3R(uiO!0%vI zyudG>I0yu$Zn1;8of{;_1wxc_7%~|2Lhu1g;PWvXSw2EITu}hu&$#>g*zvZXKfytZ zmzRG`_`w7f{^X7Ah>UYwmTfs*@K2ma^n*$V7TFSbIn3t>oR5BHI0u z>yyRhWwl{y^(lqaO+WvfF&I-U?8wBQ+9J_lgOSO2>&Iwjf|Df8b@{q+Q+cACAjr4lb87ufgk z_RVJl-+PS@S;YS^HT~s3)l#-)B{2~Ty_TFY>ZYA_FVxL> zg-B1K>^1u*hTY!5zG~_`5x{B7&`C2(WlY3oX0MS4ZI3iSz>O5A>$9*(#VXhmrt?_+mPA&KQk zJVoU}hpMQGqceEZO0b>mwWgij!@J*>nSSYbsmiPBICCrTF081WlLP)9M$j-q<*}8+ zyyw6V`>`}$RT?o^Sy}DaE@JkdM{MvW35>Og>Bp!q9r1b=Xv7jJ6vNrwig9X=8~yu* zxGl^{;|~Ar5-QD`bQ`wju+@LX@6pw9*EQp+o&D);Dhne+#B(aV2tPutxYm0>GdfER zTd{s7-K2l*qN_cYhy|dC&{zZVPe#fQKOpM#w#MA^q(g#*sy0KBXJZ=S&(99MppH26 zEU*Qi1mt_J_r}mbalAfNh)K7A@_WxZDIS<4JBxjID0rV-kf?Uq=v(v9^XNndau0muG$TtJP06L z?8%KRy(|0z`#67e8i1U6p{|fGv4)tgSO3FXOz(0GU^JgUER-FeV8nBB*7nY8h=M}G z=r{NlsBgPUxfcP*z09%7jF&5dm2O6OWMbvLOmZ8ZW(eYA_1GN{cRuXbb*o9szSZ-z zf!*1@v||!LwtP*Ew(N9mwDi>uZQR`S+>OToK|YH55w@=Dfed<8w+k*vEMu*q{|%JL zAqn-0ONXF(9YI$|wV7McWUR2l*0v&%L0BOB9o_rZ>8uPO$)9~Y*yYX51->Vs?^pvm zLyFr=y{qwHdLs6VT%>i+3p+NeF0&1JR54nBCp69zntB75O&|n2Lh8o7xGY7JeXq%c zq6K+TKaiLECG&@hVZ=T;nK^fUHmQ<{FnR~^w||QN@HT%0%9y;?34%U@1QO8Y%?cc$ z6jXoDh)He*L?zQFa6AcSF5+!AWK_cMbU$wGBUqWs=NhGORQHvPzi^b$x}p4I?rjjP z(!*TKs&Am0p-^#vb<8Kgzk=6kHk9)IIic%1Q|LmH5P4mswMXM^5eb1u^Xkn1oukgT z9&T4?F`&*+zUo4_dY7+KEJ|Q{NxaZ!-+4Ef4q7_|(7)9`H&! z;uU0(^6R{(!0;%diwKiak6N}3d{h#*m38DCm3CJ(gK~pJHa(GIgXGE&VH9J372jKB zELSGYN#AH&R@(Ol`CMj5a{p-|ar&T%lhXCbG&N2UOYrm@N88U^le36nF+I)FpP-0v zai!rEa0SNz=N)euPz;}mbN0EUL?f5xFpV$uA6I04p)p3Aesp85NA`5*!7jzl*Z=Q`R1@7RIW$>Zb)%SdJi+^hPW+QAcb0Y*D&2?Q#msJdh7Qf}vQ)Wy!uDUIr$CZJ8??VQ zKI@s>O5w*~1rjtHUV($DZu?i>6{^XDK z1vvSEk0x;k>}8hkWm-QOtj1U!SM0j;6L3heuaGiPtFj+DE9>k3w*Bz#o+NcFyf>I+ zV1?pA!Cs(}3=);Hj-yh=`(bXlw^|FzlJJr&_RclYqP^A^&U33(huPQ{EFS-z%~3vQ zlj71XsfhbyDt)0Q@#DF4qPrEGBO-a=9I$nTMZlOX>hjHoHJl+$5im-c`xGv?LBGb0 z`)yikCmN2?NDwoA#!C{_G8)ZNFP4q*@5|A=_65S?hFy5lNTg(Lbjw-4Uu3^WpdxJ4 zT?*PeH^fu}(|!lY;_yyVu{f1%5|z#aiUjd~qO;Fj=omYk;dh~7eKRYQ7E+@F1weEp zdTl&bro-wW7`W4kF61m@Ad?aN*l-JB2sj@z%!U~_mv~xgPe2(wVf0J_H%? z(j+lMqt#EceHI$TIFX1Cun8i{eZW@)-x$7X@M`q>30Y!rp1&FGeORm2zpVYd^C}g> zeJ@;@ZU#~?T@Df4iYxG?u)2o+{6tQNwhCt;m$vBIC@IRAG-LOH3e#qs@HcY-*E8-o zu45@$_#m7V24$1nSnu9FsXyt0OqFIj%BdICkjn~0Z_tq*=|V(CNctOq98MTL6|de( zrGmk?Ns0a2@{@lpc0N8q@UF^SG5xp}`+LiL= zbhzHI_A8bkA`js(P1Yd52dKX3_X*m+Ie9{l!ee`xt6Wr;n$)^KJn5jV1V?sq`*uIr z!aAWtIsxP`7>=?tH83rYcGY#=)PyUt=N(45mO{V4&AnL6(^1YPYuYs_l2di$Q^D_R zB3e@A*k#g==k%Pn-9D%FYR`Z_fT=q1tq?j-I{sBuR3@%nNt;RnBqSKLlv26^Jmgax zW$Ty{#tU1-+G?sZNO)=D#dC_Imbr*6ny7g_0TO%!v)P0LpiQDh(5-{c3rMaXvFa1s z+Jwj^;qae<9mkj(;zGpyo7nuD===g0ZMR%OWo1ES)IZDeAQgqK^K3jLT57B7&aQjT z<2>1QU`8@>Z@;MkCJM-PdiESbJ!-pf5w|)0CQQ0pqo@JYoUHgC6WfUPjkEJ@r{F!* z=p8knu1cV`W~XOUni}jd0ij7|LM!X}{c+F&E8(Vy7MV<)@6q(F;`#4XG#uUv@(PgM z&|uoA<&XIr*zrjT4$LJ7LzIr5!X}+)@nO9f9h6#}@%$73Lw_BP-!T#At?E!sWso{m zYEq0xCELL8UO2yQpu zt z1CP0-e{r)MDbmlow)&*pp9^5xpZiebU5i1M$KqqZKvmXzk1>QZx~}jngT`v!gL08r zW89|-%wAr*w?=_jUku^cT)Q_NKcaDap`z{*$Y31}luj)sKqR}r|a)@(M z`F;lC=CIs!tbjYrVDLri0M0NOT^7Lq==$HQpE7x`DM)Z140d2lF|YgR1AyYkFG+{ zlXJ`!i)B@aFwHn|Cv=_N#zdF2}!!4%oLa9`ao*@F2fG6vi)8u|O?p{a{ zpsC=Gcd1()f5C6nq(jiK^>5sIHIQv_7TKDIyT$yy(Aw@i?RX7(zSCvRZJhGZJ-5jj z;KC=L^@F^_+@5!zJ;zxGPSOZ78)H=u9Y%C@G8tcMZIOF=($tkHY8=*PWr6=%CsyX) zOJ$HPPg>R}`-x609uM-eOKvDj9W`k$G3&R%t`ZsiLNvCt9z`Rs?%M4|LhDbQJB+>F?4xs^;f$w-S#3!ryf3Wmho z*NgefEm&HpKH^5r{1hboB`9Eo0C=I3&eJmW=Z$;;zVF_c*)g}W%YQuo^VIbl!q75q zpkOzl3!n(9wnfyc$40SGP;&xt3$DGtk`T+XD}>Er;(QJ6mXHO0Ha48?!)A5)s)mko zB$tm8+i=2Kav0*f@47r*O^R+Ori-m6AEUg_XhV{VZL5gGxeYa?k4}}w7@&F+uD!W3 zC-Hc@_3Yoll0(SC8ledI-eMiRqp?JN^DBMPHG{0}*;tdl3CjG3)v9YIjLF*bm8s`| zR>iUad%OHvH3`N+Y;%wPGpJo)__It?Vta%B>Y>G$%ms?&Mg&_;+WGj%GKdPAM=QjH z&$7nhSc^&7>bQh+i7)*t6ad$U5Aj9*4_q|^zO@^PLqd%zG^ zS2%Gh7d^GIhp(K4I1& za6{xqmF$^c)ke)qq*rpif8I2KzfwfOL=f#a^6iEJg`;Q0Lc?ru6#g0*foH^28B9XE z5Ka8;-OEM(^MZD1w_*O@kbbHJcTVYSv|Fau@uzZ5`lB&ht0OC7)Ucl4r4$R}S&DHsc{Q>MwxUDx zh(mfwh@g4L*?s>!A?SI>&WS1LdFW2a-?@(D zLz}X`UC~0M|&fi|#f6Y^PG9C-}MiYXdBR(u!8;B9mNG~4>Za6|C%bYiY z$PI8+kd0oQc<^JYnx?x+o6KWcK2oUN9PyZEv@x2TLIS{rWR2ZgC4861j2*L3lx`av zs3lDsREfVe&9y7+5r*YME7+&Ip6V!Jfc|H=bQV% zW=?+JzE39G^q?r!2Uf6~ZOQ!=HNG#}_=HsME(@-`iJx^nT&D2M-iPe(2KyT&)&7}1 z^~QOTG7DH+TU$Zm-7MZpE?cf4zp!3~*G{^V2~YH%ohy9kAwQy&u~tT&@DoD)opJX- zCSf2k9p4XU`*soAm7Mg?HY04mL(1WT7D1`4}B31HWP?RHB?kn{3NdJG|iZ zNWOIBK*M>2fxD=qeIdOnnXzc0VzRCg2VOHHVVl&ZG9w*CNf63gBZ>pV12{ZoBXDf|pGXL2kQqzt+G)*ju|AB!P5P^}1< zt12sm1qALlG{H+9@Cb##dRvb*kT7VEx1oClAM_D1F=*!!RpH?wu}lFLDkTo0zQa5m zX5N*EARq@nvC6~z2t8-twl@e@-xh^2w{beLVMQ<0^NmKBNAmeL*)(a~*`-Z-+B2hY z+^?`B^e|q+r%Z4r*2Y3m_9@McXUPnBfii@7cc2o(rWG?Zgz+~uCEc=1K(W=y?c-m) zVt?(2khn#|>1#ve$}ccX*O)pT7UAdwg;k7FH}Dm$uvjb~_-8>lCWJNSdnAQfk;$M3 z#T^S)Jd|C;k+4S`0e8S(K_o|wz3uOa8LSA4kJrMWKV^9I81f%4I zbo+0}NpQTcZUbNZNHGPP+6D2Ji!4 zQHlrtFI`>NbzKbOgJ3K*dnh)G`x_~u0kjnQ_^?9eod~?lA1D=(EUMjrN|UkvXghB+ z+_ly>oDVQIf3O#&50Ku#M}Fq6fwDy(+qDd&r^&ehUx!ZL=~a#&m&_MxuH7p!uL4Gs zEJmCnGte>$=Z+sP-F3tq+{_xu4PvLFlH7Q4jY6&@f9H0!`P2DB9m31k!<kK0^*SI$6GWL;n!NG#kezQXK>5IhYK-EkuCcNCcn~s78iK zkxTL-#6K=Y&N@wlr&l`Zmj0_^bv?V}_v|s+T()V!h6AK<Is>y(GR4`ML0f_qtHJFMJ;`)bx63} z-yU(IY%fBT`LBozhA|l6BpU#G&NO7(_skhfGY=apDgK3%A%bh2ur3vcMa0DK;?=Gu zJ^`-Cw9--Bwegh7d%Miq*8UP#nSa)Fe6=MM%)HOD=GQ706qt3NH<`~O57@_xYhpqq zFbl2mu$${wTz-xiIohrW%2#j8W|Q>irqwF1H|^^+(_yqr1VXK_G`V|WLv z^<(a*({4MmrgY51tls#C?FjXn-|u0i@gzKjkrQ>rMoFu(Hlchy^v@?ctDDw4?D*G_C)AxDBU0ke+=ti{e zAKG2vJU-cj{04~)aOj5S(^yvx+3RN;tOg}ph3XkC^IBv~t{$MZ`-olA0a2~iA^WtW zQ3T6lX}{B)Auq20@-B6O@;-K`+kNt!yHH!?y^39f*I3WsXM3WHAg$`)8;1d>F2vg1 zjlAya8^)??&YBU*uH*-Rr=*y|otygBhuMC>`ThlvdvMcYooJ|LP&TW3G z8#jej^Lwh9?W<>%eNR-XkCaFDws?KAR#%pqq_xE_%wNg8v%hnH=<2A9kJhK7#ID?0 z`6PbZe+J<)MWx9Tnw%ILCSPtUu17tP16bt1fC7+V0$ir}0Z425garpdBpCk$g#-g9 zi$H)$z}Y!C1j<(N@hr=PvMrqb{XokUfq=;;#Mii;95^U^&V3CfFI~2<8A69~Y>Dm{Z&WLO^QfqMM-ohcD&#;C zg9bVSCz4nTR2|pkl6K?z15h6L2p9-k;sF-17nov_9GGHKcQD1Iu>^@M)T_YQMmS9t zo5BuE17-JM5&MEECI?Mt$aW~zps0i7HYHe?AUQ^93REG|Av{WRP&9)%;Tf1>DI2he z?Z6^-0AfE-1`!G=7qBRVr2-^%RajD06_ym#j>Wuon0cN^2DU%Iw77!@i`WFHSOdb* LJr^b?bV>mL9aE^3 delta 16045 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 0) { - String hexValue = rightPart.substring(startIndex, endIndex); - // 16진수 문자열을 16진수 숫자로 변환하여 data 배열에 저장 - data[index] = strtoul(hexValue.c_str(), NULL, 16); - index++; - - startIndex = endIndex + 1; - endIndex = rightPart.indexOf(delimiter, startIndex); - } - - // 남은 마지막 16진수 배열 원소 처리 - String hexValue = rightPart.substring(startIndex); - data[index] = strtoul(hexValue.c_str(), NULL, 16); - index++; - - // 왼쪽 부분인 "ABC"을 반환 - return index; -} diff --git a/FC_InferfaceBoard/periodics.ino b/FC_InferfaceBoard/periodics.ino index 97c7cff..ce01890 100644 --- a/FC_InferfaceBoard/periodics.ino +++ b/FC_InferfaceBoard/periodics.ino @@ -1,34 +1,64 @@ -void periodic_10ms(){ - msCnt += 10; - - if(!busy){ - // Call a function every 10ms +// +void Periodic_run(){ + if(T_10ms){ read_analog(Values_AI, Size_AI); read_mc9(Values_PV, Size_PV); - - // Call a function every 50ms - if (msCnt % 20 == 0){ - - } + T_10ms = false; + } + if(T_20ms){ - // Call a function every 50ms - if (msCnt % 50 == 0){ - - } + T_20ms = false; + } + if(T_50ms){ - // Call a function every 100ms - if (msCnt % 100 == 0){ + T_50ms = false; + } + if(T_100ms){ - } + T_100ms = false; + } + if(T_200ms){ - // Call a function every 500ms - if (msCnt % 500 == 0){ - read_mc9_req(); - } + T_200ms = false; + } + if(T_500ms){ + read_mc9_req("10"); + T_500ms = false; + } + if(T_500ms_2){ + read_mc9_req("11"); + T_500ms_2 = false; + } + if(T_1000ms){ + AnalogIn_Print(); + T_1000ms = false; + } +} +void timer_10ms(){ + msCnt += 10; - // Call a function every 1000ms - if (msCnt > 1000){ - msCnt = 0; - } + T_10ms = true; + if (msCnt % 20 == 0){ + T_20ms = true; + } + if (msCnt % 50 == 0){ + T_50ms = true; + } + if (msCnt % 100 == 0){ + T_100ms = true; + } + if (msCnt % 200 == 0){ + T_200ms = true; } + if (msCnt % 500 == 0){ + T_500ms = true; + } + if ((msCnt+250) % 500 == 0){ + T_500ms_2 = true; + } + if (msCnt > 1000){ + T_1000ms = true; + msCnt = 0; + } + }