baritone
18.12.2014, 15:08
Возможно, глупый вопрос: как читать данные из последовательного порта с помощью библоитеки UNM?
Гляжу пример - там читают по одному байту за цикл программы, и сразу же анализируют:
(*Ïðèåì îòâåòà*)
t1;
otvet_RB:=GetByte(DeviceNumber);
(*Åñëè ïîëó÷èëè íîâûé áàéò, òî ñîáèðàåì åãî â ðåçóëüòàò*)
(*è âåäåì ïîäñ÷åò ïðèíÿòûõ áàéò*)
IF otvet_RB>0 THEN
p:=ADR(otvet)+count;
p^:=otvet_RB^.data;
count:=count+1;
END_IF
(*Åñëè ïîëó÷èëè ïåðâûé áàéò, ïðîâåðÿåì àäðåñ óñòðîéñòâà*)
IF count=1 AND otvet[0]<>DeviceAdr AND t1.Q=FALSE THEN
error:=1;
t1(IN:=FALSE);
t1;
stat:=6;
ready:=TRUE;
END_IF
(*Åñëè ïîëó÷èëè âòîðîé áàéò, òî ïðîâåðÿåì ðàçìåð ïîñûëêè*)
(*Èëè ïðîâåðÿåì êîä îøèáêè*)
IF count=2 AND t1.Q=FALSE THEN
IF otvet[1]<>16#03 AND otvet[1]<>16#83 THEN
error:=2;
t1(IN:=FALSE);
t1;
stat:=6;
ready:=TRUE;
ELSIF otvet[1]=16#83 THEN
modbus_error:=TRUE;
END_IF
END_IF
(*Åñëè ïîëó÷èëè òðåòèé áàéò, òî ïðîâåðÿåì ðàçìåð ïîñûëêè*)
IF count=3 AND modbus_error=FALSE AND otvet[2]<>Quantity*2 AND t1.Q=FALSE THEN
error:=3;
t1(IN:=FALSE);
t1;
stat:=6;
ready:=TRUE;
END_IF
(*Åñëè â îòâåòå áûë êîä îøèáêè, òî â òðåòüåì áàéòå ÷èòàåì èñêëþ÷åíèå*)
IF count=3 AND modbus_error=TRUE AND t1.Q=FALSE THEN
IF otvet[2]=1 THEN
error:=4;
ELSIF otvet[2]=2 THEN
error:=5;
ELSIF otvet[2]=3 THEN
error:=6;
ELSIF otvet[2]=4 THEN
error:=7;
ELSE
error:=8;
END_IF
END_IF
(*Åñëè ïîëíîñòüþ ïðèøåë îøèáî÷íûé îòâåò çà äîïóñòèìîå âðåìÿ, ïðîâåðÿåì CRC*)
IF count=otvet_len_error AND modbus_error=TRUE AND t1.Q=FALSE THEN
(*Ðàñ÷åò CRC*)
p:=ADR(otvet);
CRC:=MB_CRC(p, otvet_len_error-2);
p:=ADR(CRC);
crc1:=p^;
p:=ADR(CRC)+1;
crc2:=p^;
(*Ñâåðÿåì CRC*)
IF crc1=otvet[otvet_len_error-2] AND crc2=otvet[otvet_len_error-1] THEN
error:=error;
ELSE
error:=9;
END_IF
t1(IN:=FALSE);
t1;
stat:=6;
ready:=TRUE;
modbus_error:=FALSE;
END_IF
(*Åñëè ïîëó÷åí îòâåò çà äîïóñòèìîå âðåìÿ îæèäàíèÿ, òî ïðîâåðÿåì CRC *)
(*È ôîðìèðóåì ðåçóëüòàò*)
IF count=otvet_len AND t1.Q=FALSE THEN
(*Ðàñ÷åò CRC*)
p:=ADR(otvet);
CRC:=MB_CRC(p, otvet_len-2);
p:=ADR(CRC);
crc1:=p^;
p:=ADR(CRC)+1;
crc2:=p^;
(*Ñâåðÿåì CRC*)
IF crc1=otvet[otvet_len-2] AND crc2=otvet[otvet_len-1] THEN
error:=0;
(*Âûäàåì ðåçóëüòàò*)
FOR i:=0 TO Quantity*2-1 DO
out[i]:=otvet[3+i];
END_FOR
FOR i:=Quantity*2 TO 127 DO
out[i]:=0;
END_FOR
(*Âûäàåì ÷èñëî áàéò â îòâåòå*)
ByteCount:=Quantity*2;
ELSE
error:=10;
END_IF
t1(IN:=FALSE);
t1;
stat:=6;
ready:=TRUE;
END_IF
IF t1.IN AND t1.Q THEN
error:=11;
t1(IN:=FALSE);
t1;
stat:=6;
ready:=TRUE;
END_IF
Для сравнения, с помощью библиотеки SysLibCom читают буфер в цикле целиком, не дожидаясь следующего вызова программы:
(*×òåíèå áóôåðà ïðèåìà*)
0:
(*Âûçûâàåì òàéìåð îæèäàíèÿ îòâåòà*)
T1();
(* ïåðåìåííóþ byte_read ìû ïîëó÷àåì ÷èñëî ïðèíÿòûõ áàéò ïðè ÷òåíèè ïîðòà*)
byte_read:=SysComRead(port_number, ADR(buf_otvet), 8, 0);
(*Åñëè ìû ïîëó÷èëè îòâåò îò óñòðîéñòâà, òî ïðèíÿòóþ èíôîðìàöèþ ñîáèðàåì â áîëåå áîëüøîé áóôåð îòâåòà
òî åñòü ñîáèðàåì îòâåò â óäîáíûé äëÿ îáðàáîòêè ôîðìàò*)
IF byte_read>0 THEN
FOR i:=0 TO byte_read-1 DO
otvet[l+i]:=buf_otvet[i];
END_FOR
l:=l+byte_read;
(*Â äàííîì ìåñòå ïðîãðàììû íåîáõîäèìî ðåàëèçîâàòü îáðàáîòêó ïðèíÿòîé èç ïîðòà èíôîðìàöèè*)
(*Äàáû ñèëüíî íå ïåðåãðóæàòü ïðèìåð èíôîðìàöèè íèæå èñïîëüçóåòñÿ ïîäîáèå çàãëóøêè*)
(*Èçâåñòíî ÷òî äëèíà îòâåòà íà èñïîëüçóåìûå â ïðîãðàììå çàïðîñû ñòîðîãî 8 áàéò*)
(*Ïîýòîìó íèæå ïðîèçâîäèòñÿ àíàëèç ðàçìåðà ïðèíÿòîãî îòâåòà*)
(*Êàê òîëüêî ïðèõîäèò çà îòâåäåííûé èíòåðâàë âðåìåíè íóæíîå êîëè÷åñòâî áàéò, íà÷èíàåì îáðàáîòêó ïðèíÿòîé êîìàíäû*)
IF ( l=7) THEN
(*Ïîëó÷èëè íóæíîå êîëè÷åñòâî áàéò*)
(*Ïðîèçâîäèì ðàñïàêîâêó îòâåòà è çàïèñûâàåì åãî íà âûõîä áëîêà*)
p1:=ADR(otvet[4]);
p:=ADR(rez);
p^:=p1^;
p1:=ADR(otvet[3]);
p:=p+1;
p^:=p1^;
(*Îñòàíàâëèâàåì òàéìåð îæèäàíèÿ îòâåòà*)
T1(IN:=FALSE, PT:=T#0s );
(*Îøèáîê íåò*)
errors:=0;
(*Çíà÷èíèÿ íà âûõîäå áëîêà ñôîðìèðîâàíû, èõ ìîæíî èñïîëüçîâàòü â ïðîãðàììå*)
ready:=TRUE;
(*Ïåðåâîäèì áëîê â ðåæèì îòïðàâêè çàïðîñà*)
status:=1;
END_IF
END_IF
Нельзя ли и с помощью функции из библиотеки UNM так же по байту читать буфер в цикле целиком? И, кстати, какова длина входного буфера у ПЛК110?
Гляжу пример - там читают по одному байту за цикл программы, и сразу же анализируют:
(*Ïðèåì îòâåòà*)
t1;
otvet_RB:=GetByte(DeviceNumber);
(*Åñëè ïîëó÷èëè íîâûé áàéò, òî ñîáèðàåì åãî â ðåçóëüòàò*)
(*è âåäåì ïîäñ÷åò ïðèíÿòûõ áàéò*)
IF otvet_RB>0 THEN
p:=ADR(otvet)+count;
p^:=otvet_RB^.data;
count:=count+1;
END_IF
(*Åñëè ïîëó÷èëè ïåðâûé áàéò, ïðîâåðÿåì àäðåñ óñòðîéñòâà*)
IF count=1 AND otvet[0]<>DeviceAdr AND t1.Q=FALSE THEN
error:=1;
t1(IN:=FALSE);
t1;
stat:=6;
ready:=TRUE;
END_IF
(*Åñëè ïîëó÷èëè âòîðîé áàéò, òî ïðîâåðÿåì ðàçìåð ïîñûëêè*)
(*Èëè ïðîâåðÿåì êîä îøèáêè*)
IF count=2 AND t1.Q=FALSE THEN
IF otvet[1]<>16#03 AND otvet[1]<>16#83 THEN
error:=2;
t1(IN:=FALSE);
t1;
stat:=6;
ready:=TRUE;
ELSIF otvet[1]=16#83 THEN
modbus_error:=TRUE;
END_IF
END_IF
(*Åñëè ïîëó÷èëè òðåòèé áàéò, òî ïðîâåðÿåì ðàçìåð ïîñûëêè*)
IF count=3 AND modbus_error=FALSE AND otvet[2]<>Quantity*2 AND t1.Q=FALSE THEN
error:=3;
t1(IN:=FALSE);
t1;
stat:=6;
ready:=TRUE;
END_IF
(*Åñëè â îòâåòå áûë êîä îøèáêè, òî â òðåòüåì áàéòå ÷èòàåì èñêëþ÷åíèå*)
IF count=3 AND modbus_error=TRUE AND t1.Q=FALSE THEN
IF otvet[2]=1 THEN
error:=4;
ELSIF otvet[2]=2 THEN
error:=5;
ELSIF otvet[2]=3 THEN
error:=6;
ELSIF otvet[2]=4 THEN
error:=7;
ELSE
error:=8;
END_IF
END_IF
(*Åñëè ïîëíîñòüþ ïðèøåë îøèáî÷íûé îòâåò çà äîïóñòèìîå âðåìÿ, ïðîâåðÿåì CRC*)
IF count=otvet_len_error AND modbus_error=TRUE AND t1.Q=FALSE THEN
(*Ðàñ÷åò CRC*)
p:=ADR(otvet);
CRC:=MB_CRC(p, otvet_len_error-2);
p:=ADR(CRC);
crc1:=p^;
p:=ADR(CRC)+1;
crc2:=p^;
(*Ñâåðÿåì CRC*)
IF crc1=otvet[otvet_len_error-2] AND crc2=otvet[otvet_len_error-1] THEN
error:=error;
ELSE
error:=9;
END_IF
t1(IN:=FALSE);
t1;
stat:=6;
ready:=TRUE;
modbus_error:=FALSE;
END_IF
(*Åñëè ïîëó÷åí îòâåò çà äîïóñòèìîå âðåìÿ îæèäàíèÿ, òî ïðîâåðÿåì CRC *)
(*È ôîðìèðóåì ðåçóëüòàò*)
IF count=otvet_len AND t1.Q=FALSE THEN
(*Ðàñ÷åò CRC*)
p:=ADR(otvet);
CRC:=MB_CRC(p, otvet_len-2);
p:=ADR(CRC);
crc1:=p^;
p:=ADR(CRC)+1;
crc2:=p^;
(*Ñâåðÿåì CRC*)
IF crc1=otvet[otvet_len-2] AND crc2=otvet[otvet_len-1] THEN
error:=0;
(*Âûäàåì ðåçóëüòàò*)
FOR i:=0 TO Quantity*2-1 DO
out[i]:=otvet[3+i];
END_FOR
FOR i:=Quantity*2 TO 127 DO
out[i]:=0;
END_FOR
(*Âûäàåì ÷èñëî áàéò â îòâåòå*)
ByteCount:=Quantity*2;
ELSE
error:=10;
END_IF
t1(IN:=FALSE);
t1;
stat:=6;
ready:=TRUE;
END_IF
IF t1.IN AND t1.Q THEN
error:=11;
t1(IN:=FALSE);
t1;
stat:=6;
ready:=TRUE;
END_IF
Для сравнения, с помощью библиотеки SysLibCom читают буфер в цикле целиком, не дожидаясь следующего вызова программы:
(*×òåíèå áóôåðà ïðèåìà*)
0:
(*Âûçûâàåì òàéìåð îæèäàíèÿ îòâåòà*)
T1();
(* ïåðåìåííóþ byte_read ìû ïîëó÷àåì ÷èñëî ïðèíÿòûõ áàéò ïðè ÷òåíèè ïîðòà*)
byte_read:=SysComRead(port_number, ADR(buf_otvet), 8, 0);
(*Åñëè ìû ïîëó÷èëè îòâåò îò óñòðîéñòâà, òî ïðèíÿòóþ èíôîðìàöèþ ñîáèðàåì â áîëåå áîëüøîé áóôåð îòâåòà
òî åñòü ñîáèðàåì îòâåò â óäîáíûé äëÿ îáðàáîòêè ôîðìàò*)
IF byte_read>0 THEN
FOR i:=0 TO byte_read-1 DO
otvet[l+i]:=buf_otvet[i];
END_FOR
l:=l+byte_read;
(*Â äàííîì ìåñòå ïðîãðàììû íåîáõîäèìî ðåàëèçîâàòü îáðàáîòêó ïðèíÿòîé èç ïîðòà èíôîðìàöèè*)
(*Äàáû ñèëüíî íå ïåðåãðóæàòü ïðèìåð èíôîðìàöèè íèæå èñïîëüçóåòñÿ ïîäîáèå çàãëóøêè*)
(*Èçâåñòíî ÷òî äëèíà îòâåòà íà èñïîëüçóåìûå â ïðîãðàììå çàïðîñû ñòîðîãî 8 áàéò*)
(*Ïîýòîìó íèæå ïðîèçâîäèòñÿ àíàëèç ðàçìåðà ïðèíÿòîãî îòâåòà*)
(*Êàê òîëüêî ïðèõîäèò çà îòâåäåííûé èíòåðâàë âðåìåíè íóæíîå êîëè÷åñòâî áàéò, íà÷èíàåì îáðàáîòêó ïðèíÿòîé êîìàíäû*)
IF ( l=7) THEN
(*Ïîëó÷èëè íóæíîå êîëè÷åñòâî áàéò*)
(*Ïðîèçâîäèì ðàñïàêîâêó îòâåòà è çàïèñûâàåì åãî íà âûõîä áëîêà*)
p1:=ADR(otvet[4]);
p:=ADR(rez);
p^:=p1^;
p1:=ADR(otvet[3]);
p:=p+1;
p^:=p1^;
(*Îñòàíàâëèâàåì òàéìåð îæèäàíèÿ îòâåòà*)
T1(IN:=FALSE, PT:=T#0s );
(*Îøèáîê íåò*)
errors:=0;
(*Çíà÷èíèÿ íà âûõîäå áëîêà ñôîðìèðîâàíû, èõ ìîæíî èñïîëüçîâàòü â ïðîãðàììå*)
ready:=TRUE;
(*Ïåðåâîäèì áëîê â ðåæèì îòïðàâêè çàïðîñà*)
status:=1;
END_IF
END_IF
Нельзя ли и с помощью функции из библиотеки UNM так же по байту читать буфер в цикле целиком? И, кстати, какова длина входного буфера у ПЛК110?