Добрый день, еще раз.
Пытаюсь организовать обмен по RS-232 между платой и контроллером СПК210-07-CS, версия прошивки которой 3.6.0318.1402. Для обмена использую библиотеку SysCom. С приемом разобрался: мне в контроллер поступает кольцевой буфер myrs232, из которого извлекается 55-байтная посылка packet с заголовком (первые 3 байта), контрольной суммой (2 последних байта) и остальными значениями. Отправляю посылку в 7 байт packet1 тоже с заголовком (первые 3 байта) и контрольной суммой (последние 2 байта). Пока при отправке пытаюсь изменить значение TempZad (значение 4-го байта packet1 (номер настройки) = 1) с 4 на 5 (то есть, 5-ый байт в посылке отправки задан 50 и через какое-то время получаю 18-ый байт тоже равный 50). Контрольную сумму программа точно считает правильно. Но проверка осциллографом показала, что отправляются не 7 байт, как задано в packet1, а гораздо больше. Даже больше, чем в приемной посылке packet. И поэтому, значение TempZad не меняется при отладке. Хотя метод Write при той же отладке выводит значение, равное 7. Как исправить эту реализацию, чтобы отправленная посылка действительно оказалась 7 байт?
Проект высылаю в виде файла и в текстовом режиме. Заранее надеюсь на оперативные ответы и решения.
FUNCTION_BLOCK Com
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
hCom : POINTER TO BYTE;
rCom : UDINT;
ComSettings : SysCom.COM_Settings;
END_VAR
METHOD CRC16Modbus : WORD
VAR_INPUT
DataArray : ARRAY[*] OF BYTE;
Length : UDINT;
END_VAR
VAR
crc : WORD := 16#FFFF;
i, j : UDINT;
dataByte : BYTE;
END_VAR
FOR i := 0 TO Length - 1 DO
dataByte := DataArray[i];
crc := crc XOR dataByte;
FOR j := 0 TO 7 DO
IF (crc AND 16#0001) <> 0 THEN
crc := SHR(crc, 1) XOR 16#A001;
ELSE
crc := SHR(crc, 1);
END_IF;
END_FOR;
END_FOR;
CRC16Modbus := crc;
METHOD Read : BOOL;
VAR_INPUT
END_VAR
VAR
Size : UDINT;
END_VAR
// Reads a number bytes from the specifed device to the receive buffer
Size := SIZEOF(myrs232 );
Read_Size:=SysComRead(hCom, ADR(myrs232) , Size, SYS_INFINITE, ADR(rCom));
IF (rCom <>0) THEN
Read:=FALSE;
Read_Size:=0;
ELSE
Read := TRUE;
END_IF
IF Read_Size > 0 THEN
SysComWrite(hCom:= hCom, pbyBuffer:= ADR(myrs232), ulSize:= size, SYS_INFINITE, pResult:= ADR(rCom));
END_IF
SysComPurge(hCom);
METHOD ExtractAndVerifyPacket : BOOL
VAR
i,j : UDINT;
calculatedCRC : WORD;
receivedCRC : WORD;
packet : ARRAY [0..54] OF BYTE;
END_VAR
FOR i:=0 TO 54 DO
IF (myrs232[i]=16#55) AND
(myrs232[i+1]=16#AA) AND
(myrs232[i+2]=16#32) THEN
FOR j:=0 TO 54 DO
packet[j]:=myrs232[j+i];
receivedCRC := SHL(packet[54],8) OR packet[53];
END_FOR;
END_IF;
END_FOR;
calculatedCRC := CRC16Modbus(packet, 53);
IF calculatedCRC = receivedCRC THEN
ExtractAndVerifyPacket := TRUE;
ELSE
ExtractAndVerifyPacket := FALSE;
END_IF
IF ExtractAndVerifyPacket := TRUE THEN
packet[0]:=16#55;
packet[1]:=16#AA;
packet[2]:=16#32;
TEMP01_:=SHR(packet[3],8) OR packet[4];
TEMP02_:=SHR(packet[5],8) OR packet[6];
TEMP03_:=SHR(packet[7],8) OR packet[8];
TEMP04_:=SHR(packet[9],8) OR packet[10];
PZAD := packet[11];
KONTRIN := packet[12];
KONTROUT := packet[13];
ERRORS1 := packet[14];
ERRORS2 := packet[15];
ERRORS3 := packet[16];
TempZad := packet[17] / 10.0;
Pruch := packet[18];
Pogr := packet[19];
temp01 := packet[20] / 10.0;
ktemp01 := packet[21] / 128.0;
temp02 := packet[22] / 10.0;
ktemp02 := packet[23] / 128.0;
temp03 := packet[24] / 10.0;
ktemp03 := packet[25] / 128.0;
temp04 := packet[26] / 10.0;
ktemp04 := packet[27] / 128.0;
kdif := packet[28] / 10.0;
kpr := packet[29] / 10.0;
kint := packet[30] / 10.0;
deltaTi := packet[31] / 10.0;
BUS1I1 := SHR(packet[32],8) OR packet[33];
BUS1I2 := SHR(packet[34],8) OR packet[35];
BUS1SOST1 := packet[36];
BUS1SOST2 := packet[37];
BUS1ERROR := packet[38];
BUS2I1 := SHR(packet[39],8) OR packet[40];
BUS2I2 := SHR(packet[41],8) OR packet[42];
BUS2SOST1 := packet[43];
BUS2SOST2 := packet[44];
BUS2ERROR := packet[45];
BUS3I1 := SHR(packet[46],8) OR packet[47];
BUS3I2 := SHR(packet[48],8) OR packet[49];
BUS3SOST1 := packet[50];
BUS3SOST2 := packet[51];
BUS3ERROR := packet[52];
END_IF
METHOD Write : BOOL
VAR
size : UDINT;
calculatedCRC1 : WORD;
END_VAR
packet1[0]:=16#55;
packet1[1]:=16#AA;
packet1[2]:=16#02;
packet1[3]:=16#01;
packet1[4]:=16#32;
calculatedCRC1 := CRC16Modbus(packet1, 5);
packet1[5] := WORD_TO_BYTE(calculatedCRC1);
packet1[6] := WORD_TO_BYTE(SHR(calculatedCRC1, 8));
Size:=SIZEOF(packet1);
Write_Size:=SysComWrite(hCom, ADR(packet1),Size, SYS_INFINITE, ADR(rCom));
IF (rCom<>0) THEN
Write:=FALSE;
Write_Size:=0;
ELSE
Write:=TRUE;
END_IF
FUNCTION IsValidDate: BOOL;
VAR_INPUT
Year: UINT;
Month: USINT;
Day: USINT;
END_VAR
VAR
DaysInMonth: ARRAY[1..12] OF INT := [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
MaxDay: INT;
END_VAR
// Корректировка для високосного года
IF (Year MOD 4 = 0 AND Year MOD 100 <> 0) OR (Year MOD 400 = 0) THEN
DaysInMonth[2] := 29;
END_IF;
MaxDay := DaysInMonth[Month];
IsValidDate := (Day >= 1) AND (Day <= MaxDay);
FUNCTION_BLOCK SetRTC
VAR_INPUT
Execute: BOOL;
END_VAR
VAR_OUTPUT
WriteResult: BOOL;
Status: STRING(50);
END_VAR
VAR
// Локальные копии для проверки
LocalYear: UINT;
LocalMonth: USINT;
LocalDay: USINT;
LocalHour: USINT;
LocalMinute: USINT;
LocalSecond: USINT;
// Вспомогательные переменные
DateTimeStr: STRING(20);
TempDateTime: DATE_AND_TIME;
END_VAR
WriteResult := FALSE;
Status := 'Ожидание';
IF Execute THEN
// Копируем значения из глобальных рабочих переменных
LocalYear := g_RTC_Year;
LocalMonth := g_RTC_Month;
LocalDay := g_RTC_Day;
LocalHour := g_RTC_Hour;
LocalMinute := g_RTC_Minute;
LocalSecond := g_RTC_Second;
// Проверка корректности данных
IF (LocalYear >= 2000) AND (LocalYear <= 2099) AND
(LocalMonth >= 1) AND (LocalMonth <= 12) AND
IsValidDate(LocalYear, LocalMonth, LocalDay) AND
(LocalHour >= 0) AND (LocalHour <= 23) AND
(LocalMinute >= 0) AND (LocalMinute <= 59) AND
(LocalSecond >= 0) AND (LocalSecond <= 59) THEN
// Формируем строку в формате 'YYYY-MM-DD-HH:MM:SS'
// Формируем строку в формате 'YYYY-MM-DD-HH:MM:SS'
DateTimeStr := UINT_TO_STRING(LocalYear);
DateTimeStr := CONCAT(DateTimeStr, '.');
DateTimeStr := CONCAT(DateTimeStr, INT_TO_STRING(LocalMonth));
DateTimeStr := CONCAT(DateTimeStr, '.');
DateTimeStr := CONCAT(DateTimeStr, INT_TO_STRING(LocalDay));
DateTimeStr := CONCAT(DateTimeStr, '');
DateTimeStr := CONCAT(DateTimeStr, INT_TO_STRING(LocalHour));
DateTimeStr := CONCAT(DateTimeStr, ':');
DateTimeStr := CONCAT(DateTimeStr, INT_TO_STRING(LocalMinute));
DateTimeStr := CONCAT(DateTimeStr, ':');
DateTimeStr := CONCAT(DateTimeStr, INT_TO_STRING(LocalSecond));
// Преобразуем строку в DATE_AND_TIME
TempDateTime := STRING_TO_DT(DateTimeStr);
g_RTC_DateTime := TempDateTime;
// Активируем команду установки времени
g_SetSettingsDT := TRUE;
WriteResult := TRUE;
Status := 'Время успешно обновлено';
ELSE
WriteResult := FALSE;
Status := 'Ошибка: некорректные данные времени';
END_IF;
ELSE
Status := 'Ожидание команды';
END_IF;
PROGRAM vis
VAR
xSound: BOOL;
xSoundState: BOOL;
xFrequency:UINT;
TON1: TON;
BLINK1: BLINK;
END_VAR
CASE nom_vis OF
1:VisuElems.CurrentVisu :='Visualization';
11:VisuElems.CurrentVisu :='Visualization_1_1';
2:VisuElems.CurrentVisu :='Visualization_2';
3:VisuElems.CurrentVisu :='Visualization_3';
4:VisuElems.CurrentVisu :='Visualization_4';
END_CASE
IF nastroi AND NOT nastroiold THEN
nom_vis:=3;
ELSIF NOT nastroi AND nastroiold THEN
nom_vis:=1;
END_IF
nastroiold:=nastroi;
IF nom_vis=1 THEN
IF KONTRIN.2 THEN
regimrabot:="Настройка";
ELSIF KONTRIN.3 THEN
regimrabot:="Автоматический";
ELSIF KONTRIN.4 THEN
regimrabot:="Местный ручной";
ELSIF KONTRIN.5 THEN
regimrabot:="Дистанционный";
ELSE
regimrabot:="Не определен";
END_IF
(*BLINK1(ENABLE:=KONTROUT.0 AND NOT TON1.Q , TIMELOW:=T#500MS, TIMEHIGH:=T#500MS );
TON1(IN:=KONTROUT.0, PT:=T#10S );
IF KONTROUT.0 THEN
xSoundState:=TRUE;
xFrequency:=2000;
xSound:=BLINK1.OUT AND NOT TON1.Q;
ELSE
xSound:=FALSE;
xSoundState:=FALSE;
END_IF*)
IF (BUS1SOST1.7) AND (BUS1SOST2.7) THEN
regimrabotBUS1:="дистанционное";
ELSE
regimrabotBUS1:="местное";
END_IF
IF (BUS2SOST1.7) AND (BUS2SOST2.7) THEN
regimrabotBUS2:="дистанционное";
ELSE
regimrabotBUS2:="местное";
END_IF
IF (BUS3SOST1.7) AND (BUS3SOST2.7) THEN
regimrabotBUS3:="дистанционное";
ELSE
regimrabotBUS3:="местное";
END_IF
END_IF;
PROGRAM PLC_PRG
VAR
SetRTC_Instance: SetRTC; // Экземпляр программы настройки времени
Timer_1s: TON; // Таймер для периодического чтения времени
ReadRTC: BOOL := TRUE; // Флаг чтения времени
END_VAR
// Вызов FUNCTION_BLOCK для записи времени
SetRTC_Instance(Execute := g_RTC_Update);
// Копируем статус операции
g_RTC_Status := SetRTC_Instance.Status;
// Сбрасываем флаг после обработки
IF g_RTC_Update AND SetRTC_Instance.WriteResult THEN
g_RTC_Update := FALSE;
END_IF;
// Периодическое чтение текущего времени (каждую секунду)
Timer_1s(IN := NOT Timer_1s.Q, PT := T#1S);
IF Timer_1s.Q AND ReadRTC THEN
Rs232IN:=TRUE;
fbCom.Write();
// Чтение из канала DATE_AND_TIME OwenRTC
g_ReadDateTime := g_RTC_DateTime;
// Преобразуем DATE_AND_TIME в строку
DateTimeStr := DT_TO_STRING(g_ReadDateTime);
// Разбор строки: формат 'YYYY-MM-DD-HH:MM:SS'
// Год: первые 4 символа
g_RTC_Year := STRING_TO_UINT(MID(DateTimeStr, 1, 4));
// Месяц: символы 6–7
g_RTC_Month := STRING_TO_USINT(MID(DateTimeStr, 6, 2));
// День: символы 9–10
g_RTC_Day := STRING_TO_USINT(MID(DateTimeStr, 9, 2));
// Час: символы 12–13
g_RTC_Hour := STRING_TO_USINT(MID(DateTimeStr, 12, 2));
// Минуты: символы 15–16
g_RTC_Minute := STRING_TO_USINT(MID(DateTimeStr, 15, 2));
// Секунды: символы 18–19
g_RTC_Second := STRING_TO_USINT(MID(DateTimeStr, 18, 2));
END_IF;
IF Rs232 THEN
fbCom.Init(); // Initialize COM 4
Rs232 := FALSE;
ELSIF Rs232IN THEN //rsbuffer
rsOk:=FALSE;
rsOk:=fbCom.Write();
rsOk:=FALSE;
rsOk:=fbCom.Read();
Rs232IN:=FALSE;
IF rsOk THEN
rsOk := fbCom.ExtractAndVerifyPacket();
END_IF;
Rs232IN := FALSE;
END_IF
vis();




Ответить с цитированием
