Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.142.174.55] |
|
Сообщ.
#1
,
|
|
|
Необходимо считывать данные с контроллера по протоколу TCP IP порт 502.
В С++Builder6 установил Indy v 10.6.2.0 Раньше данные с подобных конртоллеров считывались па СОМ порту. Производители в последующих разработках предусмотрели работу по TCP IP. В описании TCP сказано, что по этому протоколу не надо передавать адрес устройства и контрольную сумму. Разработчики не стали заморачиваться, а просто свой разработанный протокол запихнули в TCP. На форму поместил IdTCPClient, Memo, несколько Button и Label. Настроил порт = 502, ConnectTimeout =500 , ReadTimeout=-1 , Hoct на единичку больше чем па ПЭВМ, подключился кабелем с косым обжатием к контроллеру. В контроллере соответсвенные настройки адреса и порта. Для анализа работы протокола запускаю программу CommView. Код программы void __fastcall TForm_TCP::Write_Button1Click(TObject *Sender) { int i, j, k; short QS = 0; short kol_b = 0; float Buf_INR7; Byte Komanda[] = { 1, 0x00, 0x09,0x00, 0x00,0x01, 0x01, 21, 0x00, 3, 0xAA,0xAB, 0xAA,0xAB, 0xCC}; // Запись входа через СОМ порт short S_Komanda[] = {0x0000, 0x0100, 0x0900, 0x0001, 0x0121, 0x0003, 0xAAAB, 0xAAAB, 0xCC00}; // Запись входа по TCP В Сом порт массив байт передается без искажений. При передаче по TCP как бы я не объявлял массив перед байтом добавляются 00. Причем первые 16 бит оказываются оторванными в пакете.Посылка минимум 16 бит. Пришлось передавать сначала пустые 16 бит (0000) и к контрольной сумме добавлять пустые 00 Lab1-> Caption = "Отправил команду" ; Komanda_1_Vx_N = Komanda[0]; KS = 0; QS = StrToInt(Ed1 -> Text); Komanda[7] = QS; // № алгоблока QS = StrToInt(Ed2 -> Text); Komanda[9] = QS; //№ входа float QW = StrToFloat(Ed3 -> Text); Komanda[10] = ((Byte*)&QW)[0]; Komanda[11] = ((Byte*)&QW)[1]; Komanda[12] = ((Byte*)&QW)[2]; Komanda[13] = ((Byte*)&QW)[3]; kol_b = 5 + (short)Komanda[2]; KS = GetCtrSum_P131(Komanda, kol_b); // подсчет контрольной суммы Komanda[kol_b] = KS; S_Komanda[1] = Komanda[1] + (Komanda[0]<<8); S_Komanda[2] = Komanda[3] + (Komanda[2]<<8); S_Komanda[3] = Komanda[5] + (Komanda[4]<<8); S_Komanda[4] = Komanda[7] + (Komanda[6]<<8); S_Komanda[5] = Komanda[9] + (Komanda[8]<<8); S_Komanda[6] = Komanda[11] + (Komanda[10]<<8); S_Komanda[7] = Komanda[13] + (Komanda[12]<<8); S_Komanda[8] = 0x00 + (Komanda[14]<<8); IdTCPClient1->Connect(); IdTCPClient1 -> IOHandler-> BeginWork(wmWrite, 1); try { for( i=0; i<(sizeof(S_Komanda)/2); i++) { IdTCPClient1 -> IOHandler-> Write(S_Komanda[i], 1); } IdTCPClient1 -> IOHandler-> EndWork(wmWrite); } catch( ... ) { IdTCPClient1 -> IOHandler-> EndWork(wmWrite); Application -> MessageBox("Команда прервана", "Повторите попытку", MB_OK+MB_ICONERROR); } Memo1->Lines->Add("Ушла команда изменить вход"); Memo1->Lines->Add(IntToHex(S_Komanda[0], 4) + IntToHex(S_Komanda[1], 4) + IntToHex(S_Komanda[2], 4) + IntToHex(S_Komanda[3], 4) + IntToHex(S_Komanda[4], 4) + IntToHex(S_Komanda[5], 4) + IntToHex(S_Komanda[6], 4) + IntToHex(S_Komanda[8], 4) + IntToHex(S_Komanda[8], 4)); //подтверждение на изменить коэффициент на входе контроллера int f_size=10; TByteDynArray Otvet_TByteD; IdTCPClient1 -> IOHandler-> BeginWork(wmRead, 1); try { IdTCPClient1 -> IOHandler->ReadBytes(Otvet_TByteD, -1, false); IdTCPClient1 -> IOHandler-> EndWork(wmRead); } catch( ... ) { IdTCPClient1 -> IOHandler-> EndWork(wmRead); IdTCPClient1->Disconnect(); Application -> MessageBox("Ответ на команду кривой", "Большой выделенный буфер", MB_OK+MB_ICONERROR); } IdTCPClient1 -> IOHandler-> EndWork(wmRead); IdTCPClient1->Disconnect(); for(i=0; i<f_size ; i++) Buf_Otv_Zapr[i] = Otvet_TByteD[i]; Label21 -> Caption = IntToHex(Buf_Otv_Zapr[0],2); Label22 -> Caption = IntToHex(Buf_Otv_Zapr[1],2); Label23 -> Caption = IntToHex(Buf_Otv_Zapr[2],2); Label24 -> Caption = IntToHex(Buf_Otv_Zapr[3],2); Label25 -> Caption = IntToHex(Buf_Otv_Zapr[4],2); Label26 -> Caption = IntToHex(Buf_Otv_Zapr[5],2); Label27 -> Caption = IntToHex(Buf_Otv_Zapr[6],2); Label28 -> Caption = IntToHex(Buf_Otv_Zapr[7],2); Label29 -> Caption = IntToHex(Buf_Otv_Zapr[8],2); Label30 -> Caption = IntToHex(Buf_Otv_Zapr[9],2); Label31 -> Caption = IntToHex(Buf_Otv_Zapr[10],2); Label32 -> Caption = IntToHex(Buf_Otv_Zapr[11],2); Nastrojka(Sender); // сортировка полученных данных } //--------------------------------------------------------------------------- Команды уходят в контроллер, входа меня.тся, но иногда происходят сбои и программа останавливается на сообщениях. Если программа запущена из Buildera? То сообщения такие: Рис.1 Нажимаю ОК Компилятор подсвечивает строку ……….. int f_size=10; TByteDynArray Otvet_TByteD; IdTCPClient1 -> IOHandler-> BeginWork(wmRead, 1); try { IdTCPClient1 -> IOHandler->ReadBytes(Otvet_TByteD, -1, false); IdTCPClient1 -> IOHandler-> EndWork(wmRead); // подсвеченная строка } catch( ... ) { ……. Нажимаю Run Появляется мое сообщение (Большой выделенный буфер - Ответ на команду кривой) Рис.2 Нажимаю ОК , появляется сообщение Рис.3 Нажимаю ОК компилятор подсвечивает строчку template <class T> T& DynamicArray<T>::operator[](int index) { if (index < 0 || index >= this->Length) throw DynArrayOutOfRange(index, this->Length); // подсвеченная строка if (!Data) throw DynArrayNullData(); return *(Data + index); } В файле Sysdyn.h Нажимаю Run появляется сообщение Рис.4 Нажимаю ОК Программа продолжает нормально работать. Анализирую обмен в CommView. Пакеты обмена передаются несколько раз. При передачи через СОМ порт единажды. Если в очередном пакете на запрос нет ответа, происходит подвисание программы. В приемный буфер на ПЭВМ ничего не записывается. Index в DynamicArray у меня объявлен больше чем полученный пакет по факту ( ничего нет) index >= this->Length Если программа работает без компилятора, то при останове только такие сообщения: Рис.2 Нажимаю ОК , появляется сообщение Рис.4 Нажимаю ОК. Программа продолжает работать дальше. Свое сообщение я могу убрать. Сообщение Рис.3 Прикреплённая картинка
Больше не появляется. Как заблокировать сообщение об External exception EEFFACE? Программа не должна останавливаться и ждать нажатия кнопки ОК.Поискал в магазинах диски с более поздней версией C++Builder. Ничего не продается. Посоветовали скачивать с торентов. Подскажите ссылочку с программой без вирусятины. Если Indy глючная, то какой другой компонент можно поставить в Билдер? Мне надо затем программу переделать в DLL или OPC сервер для подключения к иностранной СКАДА. |
Сообщ.
#2
,
|
|
|
А при вычитке данных из TCP-стрима делается преобразование из сетевого порядка байт в машинный? Т.е. операции htons/ntohs со товарищи http://pubs.opengroup.org/onlinepubs/96999...ions/htonl.html
|