PDA

Просмотр полной версии : ЧТЕНИЕ ДАННЫХ ИЗ ПОРТА RS-232



deniska13
13.04.2017, 16:49
Добрый день, уважаемые форумчане!
У меня стоит следующая задача:
К ПЛК подключен датчик, который по каналу RS232 постоянно шлет данные с частотой 10Гц в виде 'FF FF 75 2A 4B 9C', обращаться к датчику не нужно, только открыть порт и читать. В пересылаемых данных всегда присутствует "FF FF" остальные значения меняются.
При помощи каких программных средств CoDeSys можно извлекать из этого пакета данных только "75 2А" и писать это значение в переменную. Далее мне нужно это преобразовать в десятичный формат, так как данные в шестнадцатеричном формате. Я написал программку, которая преобразует шестнадцатеричное число в десятичное, но как мне кажется программа очень медленно работает, может есть у кого другое решение, буду очень признателен за помощь!

Вот собственно программка:
PROGRAM PLC_PRG
VAR
HEX_INPUT:STRING; (*ВВОДИМОЕ ШЕСТНАДЦАТЕРИЧНОЕ ЧИСЛО*)
DEC_OUTPUT:REAL; (*ПОЛУЧЕННОЕ ДЕСЯТИЧНОЕ ЧИСЛО*)
DEC_VALUE:REAL;
EXPONENT:WORD; (*СТЕПЕНЬ*)
STAGE:WORD;
X:INT;
START:BOOL;
STOP: BOOL;
HEX_VALUE:STRING;
I:WORD;
TRIG_I:R_TRIG;
LETTER:ARRAY [1..6] OF STRING := 'A', 'B', 'C', 'D', 'E', 'F';
NUMBER: ARRAY [1..6] OF INT := 1, 2, 3, 4, 5, 6;
J:WORD;
END_VAR

(*ЭТА ЧАСТЬ НУЖНА ДЛЯ АВТОМАТИЧЕСКОГО ПЕРЕСЧЕТА В СЛУЧАЕ ВВЕДЕННОГО НОВОГО ЗНАЧЕНИЯ*)
IF HEX_VALUE <> HEX_INPUT THEN
DEC_VALUE := 0;
STOP := FALSE;
START := FALSE;
TRIG_I(CLK := FALSE);
END_IF

EXPONENT := LEN(HEX_INPUT);
IF EXPONENT > 0 THEN
START := TRUE;
TRIG_I(CLK := TRUE);
IF TRIG_I.Q THEN
I := EXPONENT - 1;
END_IF
END_IF
(*ДО ЭТОГО МОМЕНТА*)
(*ДАЛЕЕ САМО ПРЕОБРАЗОВАНИЕ*)
IF START AND NOT STOP THEN
IF I >= 0 THEN
J := 0;
WHILE J<6 DO
J := J + 1;
IF LETTER[ J ] = MID(HEX_INPUT,1,(EXPONENT - I)) THEN
X := NUMBER[J];
EXIT;
END_IF
END_WHILE

CASE X OF
0: DEC_VALUE := DEC_VALUE + STRING_TO_REAL(MID(HEX_INPUT,1,(EXPONENT - I)))*EXPT(16,I);
1: DEC_VALUE := DEC_VALUE + 10*EXPT(16,I);
2: DEC_VALUE := DEC_VALUE + 11*EXPT(16,I);
3: DEC_VALUE := DEC_VALUE + 12*EXPT(16,I);
4: DEC_VALUE := DEC_VALUE + 13*EXPT(16,I);
5: DEC_VALUE := DEC_VALUE + 14*EXPT(16,I);
6: DEC_VALUE := DEC_VALUE + 15*EXPT(16,I);
END_CASE
IF I > 0 THEN
I := I - 1;
ELSE
I := 0;
DEC_OUTPUT := DEC_VALUE;
STOP := TRUE;
END_IF
X := 0;
END_IF
END_IF
HEX_VALUE := HEX_INPUT;

melky
13.04.2017, 17:22
а сразу из буфера прочитать word нельзя ?
Word_to_int и так далее ваших 75 2A ? Соответственно принимать портом в hex режиме.

deniska13
13.04.2017, 17:46
а сразу из буфера прочитать word нельзя ?
Word_to_int и так далее ваших 75 2A ? Соответственно принимать портом в hex режиме.
Как Вы предлагаете прочитать? Значение "75 2А" это одно из возможных, которое все время меняется с частотой 10Гц

capzap
13.04.2017, 18:03
Как Вы предлагаете прочитать? Значение "75 2А" это одно из возможных, которое все время меняется с частотой 10Гц

о ком Вы так заботитесь с этим переводом различных систем исчисления на такой скорости, контроллер понимает любой из них

deniska13
13.04.2017, 18:17
о ком Вы так заботитесь с этим переводом различных систем исчисления на такой скорости, контроллер понимает любой из них
Я просто в симуляторе прогонял эту программу (преобразования шестнадцатеричного числа в десятичное) и как мне показалось время преобразования не мгновенное, а около секунды, а мне нужно быстрее, так как по этому значению будет строится график и производиться дополнительные расчеты.
Подскажите как мне читать из всей кучи данных получаемых от устройства только часть, а именно "75 2А"......

capzap
13.04.2017, 18:33
чего там читать то, если в принятом массиве байт встретились два байта, равные максимальному значению в диапазоне, значит следующие два байта идут информационные данные, через указатель нужного типа их записываете в соответствующую переменную

deniska13
13.04.2017, 21:24
чего там читать то, если в принятом массиве байт встретились два байта, равные максимальному значению в диапазоне, значит следующие два байта идут информационные данные, через указатель нужного типа их записываете в соответствующую переменную
С указателями у меня непонимание, могли бы Вы отразить свои мысли программно?)

deniska13
13.04.2017, 22:53
PROGRAM Scan
VAR_OUTPUT
Ok : BOOL;
Result : INT;
END_VAR
VAR
i : INT;
END_VAR
---------------------------
Ok:=FALSE;
WHILE SysComRead(0,ADR(Result),1,0)=1 THEN
CASE i OF
0,1: i:=SEL(INT_TO_BYTE(Result)=255,0,i+1);
2: Result:=Result*256; i:=3;
3: Result:=ROL(INT_TO_WORD(Result),8); Ok:=TRUE; i:=0; EXIT;
END_CASE
END_WHILE
***********************
Scan();
IF Scan.Ok THEN
Scan.Result ....
END_IF


Что делает эта программа?
Можете комментарии добавить в строках....

deniska13
13.04.2017, 23:27
Возвращает int после двух 255.
PS
Должна ))
PS PS
Ok := False; (*Ok устанавливается в False*)
..

Можете пояснить что происходит в этих строках
WHILE SysComRead(0,ADR(Result),1,0)=1 THEN
2: Result:=Result*256; i:=3; (*полученное значение умножаем на 256 и записываем в нашу переменную затем переходим на 3*)
3: Result:=ROL(INT_TO_WORD(Result),8); Ok:=TRUE; i:=0; EXIT; (*побитовый сдвиг влево на 8, для чего?*)

А можно просто с "FF" сравнивать?

deniska13
13.04.2017, 23:45
Можно. Это в 0,1:.... и есть
А в этой части "ADR(Result)" я с этой функцией никак не могу разобраться....

deniska13
14.04.2017, 00:41
Я ж говорил. Не надо. Примите как данность. До момента легкоусваеваения слова "указатель"
Ну как не надо)....вот сейчас появилась необходимость в применении и в последующем появится, не буду ведь я надоедать всем с одним и тем же вопросом. Может объясните "на пальцах" что это такое и как оно работает.
VAR
X:STRING := 'FFFF752A';
Y:POINTER TO STRING;
END_VAR
Y := ADR(X); (*в таком виде Y становится равным X, а смысл тогда какой в ADR когда можно просто написать Y := X; будет тоже самое*)
Y := ADR(X) + 4; (*так уже интереснее получается "752A" происходит сдвиг на 4 символа если я правильно изъясняюсь*)


Может все таки расскажете что это за функция)...просто сейчас у меня началась работа с портами, а там нужно ее применять...

deniska13
14.04.2017, 09:53
Нет. Y^ - да.
А какое из 2-х предложений хэлпа непонятно ?

я в справке CodeSys нашел тоже самое что и в обычной книге, ничего нового...

deniska13
14.04.2017, 09:58
Нет. Y^ - да.
А какое из 2-х предложений хэлпа непонятно ?
...Вот что нашел...
"Функция адрес
ADR возвращает адрес аргумента в формате DWORD. Полученный адрес может быть передан функции
в качестве аргумента или присвоен переменной типа указатель."
Возвращает адрес, какой адрес в моем случае, место нахождения входных данных? и что мне с этого адреса? Или же это указатель например на второй байт входящих данных...или что?