
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.3] |
![]() |
|
Сообщ.
#1
,
|
|
|
Помогите!!! начал разбираться с работой с ком портами попал в руки прибор который работает по протоколу ModBus RTU. настряпал вот такую програмку но она не работает!!!
Я так и не могу прочитать данных с порта помогите плиз!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! исходник на билдере здесь: vortekc.narod.ru/MyModBus.zip или может кто знает фриварный компонент для работы с ModBus |
Сообщ.
#2
,
|
|
|
В чем его(ModBus'а) основные особенности?
|
![]() |
|
|
Пример команды чтения 4 канала второй страницы (10 канал, 9 адрес) побайтно:
адрес устр,4,0,9,0,1,CRCL,CRCH . адрес устр,команд чтения, колличество байт2, DATAH,DATAL,CRCL,CRCH Чтение ведётся не более 6 регыстров за 1 раз Всё это в RTU формате. Помогите разобратся. Заранее признателен Александр |
Сообщ.
#4
,
|
|
|
Я не об этом. В чем сложность реализации?
Сколько регистров и каков порядок байтов в слове - значения не имеет. |
Сообщ.
#5
,
|
|
|
trainer
Исходник на билдере здесь: vortekc.narod.ru/MyModBus.zip Sori, архив был повреждён (исправлен) Может есть компоненты ModBus под Делфи или Билдер Не могу записать в порт . Если есть пример буду признателен. Александр. |
Сообщ.
#6
,
|
|
|
Сегодня или завтра подготовлю публичную версию своей DLL для работы с COM-портом и выложу гле-нибудь.
|
Сообщ.
#7
,
|
|
|
Буду очень признателен.
Сообщи мне где выложиш. Удачи. Александр |
Сообщ.
#8
,
|
|
|
Да прямо здесь и выложу.
Архив WinRAR 2.90 ----------------- Пардоньте, забыл вписать коды ошибок. Вложен новый файл. Прикреплённый файл ![]() |
Сообщ.
#9
,
|
|
|
ОК. Скачал, огромное спасибо.
Коментарии принимаются? Если да то немножко попозже. Удачи. Александр. |
Сообщ.
#10
,
|
|||
|
Непременно
![]() |
Сообщ.
#11
,
|
|
|
Спасибо всё работает. Замечаний оссобых нет кроме нескольких опечаток в ReadMe.txt в примерах на С++ там пару констант немножко не так обозвал
![]() ![]() ![]() Да, ты случайно не знаешь как мне быть с такой проблемкой: я вот получаю массив с ответом от прибора, но нужнные данные только два элемента скажем 3 и 4. Тоесть 3 это младший байт слова а 4 соответственно старший. Вот как мне их склеить и получить число записанное этими двумя байтами? Зарание спасибо!!!! |
Сообщ.
#12
,
|
|||
|
Ну это вариантов много, например: BYTE buffer[n]; WORD value = *((WORD *)(buffer+2));// это если считать как все нормальные люди(3-ий - это смещение 2) Добавлено в
Я его на скорую руку писАл.
![]() |
![]() |
|
|
Может это и ламерский вопрос но всё же: почему в результате ниже следующей операции компилятор мне выдаёт значение value = 58369 вместо нужных 484?
buff[0]=0x1; buff[1]=0xE4; WORD value =*((WORD *) (buff)); |
Сообщ.
#14
,
|
|||||
|
Потому, что порядок не тот. Не:
А наоборот: 3 - старший, 4-младший
![]() Тогда:WORD value = ((byte[2]<<8)|byte[3])&0xffff; |
![]() |
|
|
Спасибо, но я тут сам немножко подумал и решил зделать с помошью асма
![]() mov ah,rd_buffer[3]; mov al,rd_buffer[4; mov Chislo,ax; Ну вот теперь у меня вроде всё работает, но есть проблемка я же всёравно не понимаю как оно доконца работает. Поделись пожалуйста исходниками своей библиотеки. Уж очень разобраться охота. Зарание благодарен Саша! |
Сообщ.
#16
,
|
|||
|
Вот этого я сделать не могу.
![]() Коммерческая разработка. ![]() |
![]() |
|
|
Могу подкинуть сорс класса реализующего работу с СОМ-портом. Класс правда для Visual С, но думаю идею он раскрыть сможет.
Я его юзаю постоянно. Буду вопросы - пиши. Прикреплённый файл ![]() |
Сообщ.
#18
,
|
|
|
Как быть если требуется пользовать MODBUS-ASCII. Я вот смотрю обучно строчку побайтово передают и радуются :-) а мне-то нужно передать именно что строчку из шестнадцатиричных чисел. Как быть? Да и к тому же, 16-ти ричные числа двух-символьные... или это никак не влияет?
Благодарю. |
Сообщ.
#19
,
|
|
|
Цитата Cergiy @ А у этой строчки посчитать количество потребных для передачи байтов нельзя?а мне-то нужно передать именно что строчку из шестнадцатиричных чисел. Как быть? Цитата Cergiy @ см. выше Да и к тому же, 16-ти ричные числа двух-символьные... или это никак не влияет? |
Сообщ.
#20
,
|
|
|
trainer я сейчас спрошу нечто глупое, а я должен переводить эту строчку в какой-то иной формат(из строкового) чтобы передавать? то есть как осуществить передачу символов, а не чисел? Или я уже слишком вечером туплю?
|
Сообщ.
#21
,
|
|
|
Цитата Cergiy @ Очень похоже, что да.Или я уже слишком вечером туплю? Цитата Cergiy @ По этому поводу ничего сказать не могу. Спецификации Modbus под рукой нет.а я должен переводить эту строчку в какой-то иной формат(из строкового) чтобы передавать? Цитата Cergiy @ Так или иначе, а передается набор байтов. то есть как осуществить передачу символов, а не чисел? |
Сообщ.
#22
,
|
|
|
To trainer
Спасибо за библиотеку TrComPort ![]() Работает существенно быстрее, чем ComPortLib. Вы писали, что можете выложить более свежую версию.(Я скачал от 2003г) Если не затруднит, буду весьма признателен. Вопрос для общего развития. Если я просто подключаю Вашу библиотеку к проекту, все замечательно. Решил сам сделать библиотеку из Вашей DLL. ![]() ![]() impdef.exe -h TrComPort.def TrComPort.dll implib.exe -c -f TrComPort_BCB.lib TrComPort.def Библиотека получается меньше, почти вся заполнена нулями и ,естественно, ничего не работает. В чем я неправ? Поиск обшарил почти весь, включая FAQ |
Сообщ.
#23
,
|
|
|
Здравствуйте coach.
![]() У меня возникли вопросы по вашей программе TrComPort. У меня в распоряжении прибор МВУ-8, который работает по протоколу ModBus RTU, адрес 16. Я передаю в функцию TrComPortWriteArray следующее сообщение: 0x10 - адрес, 0x10 - команда, 0x00, 0x00 - нач. адрес регистра, 0x00, 0x01 - количество регистров, 0x02 - количество байт, 0x10, 0x00 - значение, CRC_Low, CRC_High. У меня оно отрабатывает, т.е. result=0, но состояние выхода прибора не изменяет. В чем может быть проблема? И мне интересен следующий вопрос: Чтение с прибора, как я понял, тоже выполняется функцией TrComPortWriteArray. Но куда записываются прочитанные значения? Буду очень признателен, С уважением, Павел. ![]() |
Сообщ.
#24
,
|
|
|
там вообще-то в комментариях написано, что делает каждая функция. Чтение массива байт выполняет TrComPortReadArray
Цитата Pauly @ А прибор не должен квитировать команду? Если должен - надо прочитать его ответ, наверняка он должен возвращать код ошибки в случае отказа выполнять команду. У меня оно отрабатывает, т.е. result=0, но состояние выхода прибора не изменяет. В чем может быть проблема? |
Сообщ.
#25
,
|
|
|
Для чтения у меня есть сообщение в котором задается команда 0x03 вместо 0x10. Это сообщение нужно подавать параметром rd_buffer в TrComPortReadArray?
Когда я читаю ответ прибора функцией TrComPortWriteAndRead, то result=-10, а rd_buffer пустой. |
Сообщ.
#26
,
|
|
|
-10 - это значит прочитать запрошенное количество байт не удалось, истек тайм-аут. Либо размер ответа меньше, чем затребовано к прочтению, либо прибор вовсе не ответил.
Цитата Pauly @ Надо передать команду функцией TrComPortWriteArray и прочитать ответ функцией TrComPortReadArray. Или воспользоваться функцией 2-в-1 TrComPortWriteAndRead Для чтения у меня есть сообщение в котором задается команда 0x03 вместо 0x10. Это сообщение нужно подавать параметром rd_buffer в TrComPortReadArray? |
Сообщ.
#27
,
|
|
|
Я не уверен, что он этот прибор должен слать ответ, по крайней мере у меня нет формата приема данных. Я выставлял всякие размеры ответа, ошибка остается. Связь с прибором устанавливается и по другому протоколу обмен удается.
У другого прибора есть и посылка, и прием, для него я использую TrComPortWriteAndRead, но у меня нет его на руках, поэтому я решил проверить работоспособность на МВУ. |
Сообщ.
#28
,
|
|
|
Здравствуйте trainer. Помогите пожалуйста в следующем вопросе: Я считываю параметры прибора в потоке(Thread). В главной программе я останавливаю поток(Terminate), закрываю COM-порт и потом заново пытаюсь открыть COM-порт, а у меня выдается ошибка -2. Как я понимаю, в процесс остановки потока у меня может происходить обращение к COM-порту и он закрывается некорректно. Для решения этого я использую функцию TrComPortBreak, однако она ничего не дает. Не могли бы вы подсказать, что нужно сделать для корректного закрытия порта?
|
Сообщ.
#29
,
|
|
|
Terminate вообще-то не останавливает поток, а просит его завершиться.
TrComPortBreak надо вызывать из основного потока. Цитата Pauly @ Это сильно вряд ли. Порт либо закроется, либо нет. Как я понимаю, в процесс остановки потока у меня может происходить обращение к COM-порту и он закрывается некорректно. |
Сообщ.
#30
,
|
|
|
При закрытии формы выполняется следующий код:
result = TrComPortBreak(PortId); FirstProcess->Terminate(); //поток, где выполняется чтение/запись по ModBus result = TrComPortClose(PortId); PortId = TrComPortOpen(5); При закрытии порта ошибки действительно нет, а вот при открытии возникает -2, причем не всегда. Если я запускаю программу еще раз, то порт открывается нормально. Может быть порт не открывается из-за того, что дочерний поток закрывается, а TrComPortWriteAndRead еще до конца не сработал? В чем ошибка в моих действиях? Заранее благодарен, Павел. |
Сообщ.
#31
,
|
|
|
ну попробуй после TrComPortBreak добавить TrComPortPurge
Можно еще попробовать добавить небольшие паузы. |
Сообщ.
#32
,
|
|
|
А чему должен быть равен второй параметр TrComPortPurge?
Перед закрытием порта я делаю Sleep(1000); - вроде бы COM-порт стал открываться, но это теперь тяжело оттестить. Не могли бы вы сказать, что дают такие паузы? (вроде бы поток должен закрываться без пауз) А то теперь увеличилось время выполнения программы, и уверенность в правильности ее работы поубавилась. |
Сообщ.
#33
,
|
|
|
Цитата Pauly @ Комбинация значений TrComPortFlushFlagsА чему должен быть равен второй параметр TrComPortPurge? Цитата Pauly @ Они дают системе дополнительное время на выполнение необходимых действий по закрытию порта. Напрмер на то, чтобы выплюнуть остатки в буфере передачи. Не могли бы вы сказать, что дают такие паузы? |
Сообщ.
#34
,
|
|
|
Не пойму,где в примере ошибки, поменял здесь TPpbComPortParameters params =... на PTrComPortParameters, при компиляции выдает первую ошибку здесь-
![]() ![]() CBR_9600, // 9600 бод Вот код полностью: ![]() ![]() #include "TrComPort.h" INT PortId; INT result; BYTE wr_data[] = {1,2,3,4,5,6}; BYTE rd_buffer[16]; PortId = TrComPortOpen(0);// COM1 if( TRCOM_SUCCEEDED(PortId) ) { // порт открыт - устанавливаем параметры соединения PTrComPortParameters params = {tcpmpBaudRate|tcpmpDefaultTimeout|tcpmpByteSize|tcpmpStopBits|tcpmpCheckParity|tcpmpParity|tcpmpEnableRtsControl|tcpmpEnableDtrControl, CBR_9600, // 9600 бод 5000, // по умолчанию тайм-аут 5 с. 8, // 8 бит ONESTOPBIT, // 1 стоп-бит 0, // без проверки четности NOPARITY, // без бита четности RTS_CONTROL_DISABLE,// изначально RTS-off DTR_CONTROL_ENABLE};// изначально DTR-on result = TrComPortSetConfig(PortId,¶ms); if( TRCOM_SUCCEEDED(result) ) { // параметры заданы - устанавливаем управляющие сигналы(DTR-on, RTS-off) result = TrComPortSetControl(PortId, pcpscfSetDtr|pcpscfClearRts); if( TRCOM_SUCCEEDED(result) ) { // управляющие согналы установлены - передаем и принимаем данные // передаем 6 байт, принимаем 1 байт, тайм-аут - 1 с. result = TrComPortWriteAndRead(PortId, wr_data, 6, rd_buffer, 1, 1000); if( TRCOM_SUCCEEDED(result) ) { // что-нибудь делаем далее } } } // т.к. порт больше не нужен, закрываем его result = TrComPortClose(PortId); } |
Сообщ.
#35
,
|
|
|
Должно быть не PTrComPortParameters, а TrComPortParameters
|
Сообщ.
#36
,
|
|
|
Еще была ошибка здесь- result = TrComPortSetControl(PortId, pcpscfSetDtr|pcpscfClearRts); , нужно- tcpscfSetDtr|tcpscfClearRts...
Но все равно ошибки выдает-такие: [Linker Error] Unresolved external 'TrComPortOpen' referenced from D:\COMPORT\COMPORT.OBJ [Linker Error] Unresolved external 'TrComPortSetConfig' referenced from D:\COMPORT\COMPORT.OBJ [Linker Error] Unresolved external 'TrComPortSetControl' referenced from D:\COMPORT\COMPORT.OBJ [Linker Error] Unresolved external 'TrComPortWriteAndRead' referenced from D:\COMPORT\COMPORT.OBJ [Linker Error] Unresolved external 'TrComPortClose' referenced from D:\COMPORT\COMPORT.OBJ Не подскажете, в чем дело ? |
Сообщ.
#37
,
|
|
|
Библиотеку надо к проекту подключить
|
Сообщ.
#38
,
|
|
|
Подскажите, как подключить dll к проекту-я совсем начинающий, пробовал через add to proekt - такие же ошибки, пробовал добавлять lib файлы- тоже ошибка,но другая.
|
Сообщ.
#39
,
|
|
|
Add to project -> расширение ".LIB", выбрать TrComPort_BCB.lib, нажать Ok
P.S. Интересно, я один такой устаревший - сначала читаю литературу, потом делаю. |
Сообщ.
#40
,
|
|
|
Вот спасибо,заработало, я пробовал подключать оба lib-а, а надо оказывается только этот.
|
Сообщ.
#41
,
|
|
|
С этим компонентом разобрался, сейчас мучаю модем Моторолы, который по USB соединен к компу, драйвером создается виртуальный порт СОМ3. По АТ командам все работает нормально, когда вот так-
![]() ![]() #include <vcl.h> #pragma hdrstop #include "COMPORT.h" #include "TrComPort.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { int PortId; int result; char end[] = {"at+ckpd=\"e\"\r"}; // завершить вызов char nabor_nomera[] = {"at+ckpd=\"89123456789\"|at+ckpd=\"s\"\r"}; // набрать номер и звонить char zvonit[] = {"at+ckpd=\"s\"\r"}; // звонить(зеленая кнопка телефона) PortId = TrComPortOpen(2); // COM3 if( TRCOM_SUCCEEDED(PortId) ) { // порт открыт - устанавливаем параметры соединения TrComPortParameters params = {tcpmpBaudRate|tcpmpDefaultTimeout|tcpmpByteSize|tcpmpStopBits|tcpmpCheckParity|tcpmpParity|tcpmpEnableRtsControl|tcpmpEnableDtrControl, CBR_9600, // 9600 бод 5000, // по умолчанию тайм-аут 5 с. 8, // 8 бит ONESTOPBIT, // 1 стоп-бит 0, // без проверки четности NOPARITY, // без бита четности RTS_CONTROL_DISABLE,// изначально RTS-off DTR_CONTROL_ENABLE};// изначально DTR-on result = TrComPortSetConfig(PortId,¶ms); result = TrComPortSetControl(PortId, tcpscfSetDtr|tcpscfClearRts); TrComPortWriteArray(PortId, end, 20, 1000); // Прервать вызов TrComPortWriteArray(PortId, nabor_nomera, 35, 1000); // Набрать номер Sleep(1000); // пробовал с паузой и без TrComPortWriteArray(PortId, zvonit, 15, 1000); Sleep(3000); // пауза TrComPortWriteArray(PortId, end, 20, 1000); // Прервать вызов } } } Когда устанавливаю на форму таймер, чтобы пробовать делать дозвон через определенное время, и переменные выношу за кавычки формы и кусок кода вставляю в обработчик таймера, то уже все работает неправильно- уже набор номера не работает. Знаю это к этой теме не относится, скорее к азам программирования, но т.к. вопрос связан с этим компонентом-задаю здесь. Вот нерабочий код- ![]() ![]() #pragma hdrstop #include "COMPORT.h" #include "TrComPort.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; int PortId; int result; char end[] = {"at+ckpd=\"e\"\r"}; // завершить вызов char nabor_nomera[] = {"at+ckpd=\"89123456789\"|at+ckpd=\"s\"\r"}; // набрать номер и звонить char zvonit[] = {"at+ckpd=\"s\"\r"}; // звонить(зеленая кнопка телефона) //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { PortId = TrComPortOpen(2); // COM3 if( TRCOM_SUCCEEDED(PortId) ) { // порт открыт - устанавливаем параметры соединения TrComPortParameters params = {tcpmpBaudRate|tcpmpDefaultTimeout| tcpmpByteSize|tcpmpStopBits|tcpmpCheckParity|tcpmpParity|tcpmpEnableRtsControl|tcpmpEnableDtrControl, CBR_9600, // 9600 бод 5000, // по умолчанию тайм-аут 5 с. 8, // 8 бит ONESTOPBIT, // 1 стоп-бит 0, // без проверки четности NOPARITY, // без бита четности RTS_CONTROL_DISABLE,// изначально RTS-off DTR_CONTROL_ENABLE};// изначально DTR-on result = TrComPortSetConfig(PortId,¶ms); result = TrComPortSetControl(PortId, tcpscfSetDtr|tcpscfClearRts); Timer1->Interval=10000; Timer1->Enabled=true; } void __fastcall TForm1::Timer1Timer(TObject *Sender) { TrComPortWriteArray(PortId, end, 20, 1000); // Прервать вызов TrComPortWriteArray(PortId, nabor_nomera, 35, 1000); // Набрать номер Sleep(1000); // пауза TrComPortWriteArray(PortId, zvonit, 15, 1000); Sleep(3000); // пауза TrComPortWriteArray(PortId, end, 20, 1000); // Прервать вызов } Прошу обьяснить, что здесь не так. |
Сообщ.
#42
,
|
|
|
к проблеме это скорее всего не относится, но правильнее писать
TrComPortWriteArray(PortId, end, sizeof(end)-1, 1000); Добавлено А вообще - модем вообще-то должен отвечать на команды. Вот ответы и надо смотреть. |
Сообщ.
#43
,
|
|
|
Да нет,относится,сделал так-и заработало,еще раз огромное спасибо!
|
Сообщ.
#44
,
|
|
|
В моем примере выше,где char nabor nomera, как можно внутрь кавычек АТ команды, вместо номера телефона поставить переменную?
|
Сообщ.
#45
,
|
|
|
sprintf юный падован использовать должен.
|
Сообщ.
#46
,
|
|
|
trainer
![]() ![]() procedure TForm1.Button7Click(Sender: TObject); var PortId: Integer; res: Integer; wr_data: array[1..8] of Byte; rd_buffer: array[1..8] of Byte; begin PortId := TrComPortOpen(0); (* COM1 *) if TRCOM_SUCCEEDED(PortId) then // порт открыт - устанавливаем параметры соединения TrComPortParameters(tcpmpBaudRate or tcpmpDefaultTimeout or tcpmpByteSize or tcpmpStopBits or tcpmpCheckParity or tcpmpParity or tcpmpEnableRtsControl or tcpmpEnableDtrControl, //[B]на этой строчке выдаёт ошибку((( натолкните плз на мысль...[/B] CBR_9600, (* 9600 бод *) 5000, (* по умолчанию тайм-аут 5 с. *) 8, (* 8 бит *) ONESTOPBIT, (* 1 стоп-бит *) 0, (* без проверки четности *) NOPARITY, (* без бита четности *) RTS_CONTROL_DISABLE,(* изначально RTS-off *) DTR_CONTROL_ENABLE);(* изначально DTR-on *) res := TrComPortSetConfig(PortId,params); if TRCOM_SUCCEEDED(res) then begin (* параметры заданы - устанавливаем управляющие сигналы(DTR-on, RTS-off) *) res := TrComPortSetControl(PortId, TRCOM_CTRL(tcpccSet,tcpccClear)); if TRCOM_SUCCEEDED(result) then begin (* управляющие согналы установлены - передаем и принимаем данные передаем 6 байт, принимаем 1 байт, тайм-аут - 1 с. *) res := TrComPortWriteAndRead(PortId, wr_data, 6, rd_buffer, 1, 1000); if TRCOM_SUCCEEDED(result) then begin (* что-нибудь делаем далее *) end; end; end; (* т.к. порт больше не нужен, закрываем его *) result = TrComPortClose(PortId); end; |
Сообщ.
#47
,
|
|
|
Не паскалист я. Неправильно там вроде написано.
Либо ![]() ![]() const params : TrComPortParameters = (DesiredParams: tcpmpBaudRate or tcpmpDefaultTimeout or tcpmpByteSize or tcpmpStopBits or tcpmpCheckParity or tcpmpParity or tcpmpEnableRtsControl or tcpmpEnableDtrControl, BaudRate: CBR_9600, (* 9600 бод *) DefaultTimeout: 5000, (* по умолчанию тайм-аут 5 с. *) ByteSize: 8, (* 8 бит *) StopBits: ONESTOPBIT, (* 1 стоп-бит *) CheckParity: 0, (* без проверки четности *) Parity: NOPARITY, (* без бита четности *) RtsControl: RTS_CONTROL_DISABLE,(* изначально RTS-off *) DtrControl: DTR_CONTROL_ENABLE);(* изначально DTR-on *) var PortId: Integer; res: Integer; wr_data: array[1..8] of Byte; rd_buffer: array[1..8] of Byte; begin PortId := TrComPortOpen(0); (* COM1 *) if TRCOM_SUCCEEDED(PortId) then // порт открыт - устанавливаем параметры соединения res := TrComPortSetConfig(PortId,params); if TRCOM_SUCCEEDED(res) then begin (* параметры заданы - устанавливаем управляющие сигналы(DTR-on, RTS-off) *) res := TrComPortSetControl(PortId, TRCOM_CTRL(tcpccSet,tcpccClear)); if TRCOM_SUCCEEDED(result) then begin (* управляющие согналы установлены - передаем и принимаем данные передаем 6 байт, принимаем 1 байт, тайм-аут - 1 с. *) res := TrComPortWriteAndRead(PortId, wr_data, 6, rd_buffer, 1, 1000); if TRCOM_SUCCEEDED(result) then begin (* что-нибудь делаем далее *) end; end; end; (* т.к. порт больше не нужен, закрываем его *) result = TrComPortClose(PortId); end; ![]() ![]() var PortId: Integer; res: Integer; wr_data: array[1..8] of Byte; rd_buffer: array[1..8] of Byte; params : TrComPortParameters; begin PortId := TrComPortOpen(0); (* COM1 *) if TRCOM_SUCCEEDED(PortId) then // порт открыт - устанавливаем параметры соединения with params do begin DesiredParams := tcpmpBaudRate or tcpmpDefaultTimeout or tcpmpByteSize or tcpmpStopBits or tcpmpCheckParity or tcpmpParity or tcpmpEnableRtsControl or tcpmpEnableDtrControl, BaudRate := CBR_9600, (* 9600 бод *) DefaultTimeout := 5000, (* по умолчанию тайм-аут 5 с. *) ByteSize := 8, (* 8 бит *) StopBits := ONESTOPBIT, (* 1 стоп-бит *) CheckParity := 0, (* без проверки четности *) Parity := NOPARITY, (* без бита четности *) RtsControl := RTS_CONTROL_DISABLE,(* изначально RTS-off *) DtrControl := DTR_CONTROL_ENABLE);(* изначально DTR-on *) end; res := TrComPortSetConfig(PortId,params); if TRCOM_SUCCEEDED(res) then begin (* параметры заданы - устанавливаем управляющие сигналы(DTR-on, RTS-off) *) res := TrComPortSetControl(PortId, TRCOM_CTRL(tcpccSet,tcpccClear)); if TRCOM_SUCCEEDED(result) then begin (* управляющие согналы установлены - передаем и принимаем данные передаем 6 байт, принимаем 1 байт, тайм-аут - 1 с. *) res := TrComPortWriteAndRead(PortId, wr_data, 6, rd_buffer, 1, 1000); if TRCOM_SUCCEEDED(result) then begin (* что-нибудь делаем далее *) end; end; end; (* т.к. порт больше не нужен, закрываем его *) result = TrComPortClose(PortId); end; |
Сообщ.
#48
,
|
|
|
trainer.
Очень прошу помочь. Получаю данные с СОМ порта моей терминальной программой (делфи, компонент соmm32) вот в таком виде: яяя/00016661<0 >6==;83<<49;:8 3><0;1>?4388>< 2:000000003; Что нужно мне сделать, может нужна функция или процедура, чтобы конвертировать в читабельный формат. После обработки должно быть Temp=-7.21, PD=0.024, Davl=0.376, Rasx=273.845; |
Сообщ.
#49
,
|
|
|
"Я не волшебник, я только учусь..." (c) не-помню-откуда.
Бери описание протокола обмена и смотри. |
Сообщ.
#50
,
|
|
|
Trainer, подскажите, если вместо обыкновенного компонента соmm32 я буду использовать modbus компонент, чтонибуть изменит.
|
Сообщ.
#51
,
|
|
|
Если ты будешь при чтении использовать очки, поможет это тебе читать китайские тексты?
|
Сообщ.
#52
,
|
|
|
Помогите новичку! Использую TrComPort, взял пример из ReadMe.txt. Как я понял он считывает 1 байт и на этом завершает работу. А как считать все данные, поступившие на порт? Я пишу программу для работы со сканером штрих-кодов и мне нужно, чтобы каждый раз, когда сканером читают штрих-код, он целиком попадал в программу, а там дальше с ним велась дальнейшая работа. Подскажите пожалуйста как это сделать.
|
Сообщ.
#53
,
|
|
|
Цитата Ex0RCi$t @ Воспользоваться функцией чтения. Логично? А как считать все данные, поступившие на порт? |
Сообщ.
#54
,
|
|
|
Логично
![]() Видимо TrComPortReadArray(INT portid, LPVOID buffer, DWORD length, LONG timeout) ? А параметр length у неё должен быть равен тому, что вернёт TrComPortGetQueue()? |
Сообщ.
#55
,
|
|
|
да.
Добавлено Можно просто читать побайтно, пока не появится заданный символ |
Сообщ.
#56
,
|
|
|
Есть отличная библиотека на C для modbus мастера: www.modbus.org. Может быть скомпилированна под Windows и Linux. Здесь читал её небольшое описание по-русски с примерами: http://robot-develop.org/archives/1042.
|
Сообщ.
#57
,
|
|
|
Цитата dmitry90 @ Есть отличная библиотека на C для modbus мастера: www.modbus.org. Может быть скомпилированна под Windows и Linux. Здесь читал её небольшое описание по-русски с примерами: http://robot-develop.org/archives/1042. Помогите, пожалуйста, новичку! Необходимо по протоколу Модбас через ком-порт считывать и записывать данные в приборы ОВЕН. Не могу понять, что нужно делать с этим http://www.libmodbus.org/download/. Если можно по пунктам. Большое спасибо Добавлено Всё это делаю в Borland C++ Builder 6 |
Сообщ.
#58
,
|
|
|
Цитата dmitry90 @ Есть отличная библиотека на C для modbus мастера: www.modbus.org. Может быть скомпилированна под Windows и Linux. Здесь читал её небольшое описание по-русски с примерами: http://robot-develop.org/archives/1042. Спасибо за ссылку, посмотрел собрал LIB из библиотеки, подключил к проекту примера, собрал, все нормально. Но при работе не открывается порт. Правда коробочки с ModBus и устройств у меня пока нет, учусь плавать на сухую. Может поэтому проблемы? Вообщк е хотелось бы поюзать готовый рабочий проект с использованием библиотеки. Может вы могли бы дать ссылочку, или код? Работаю под VS 2010, C++. |
Сообщ.
#59
,
|
|
|
Цитата Но при работе не открывается порт. Правда коробочки с ModBus и устройств у меня пока нет НУ если нет железа то и не откроется порт, так как его нету. |
Сообщ.
#60
,
|
|
|
Цитата Dem_max @ Цитата Но при работе не открывается порт. Правда коробочки с ModBus и устройств у меня пока нет НУ если нет железа то и не откроется порт, так как его нету. Есть проблема с компиляцией библиотеки ModBus. Не находится описание типа ssize_t. Я покопался в MSDN и нашел LONG_PTR. В хедере добавил typedef LONG_PTR ssize_t И все откомпилировалось и запустилось. Вопрос, правильно ли я сделал? Вообще то такого в проверенных библиотеках не должно быть. Может я скачал кривую библиотеку из инета? Если у кого то такого не было, кинте ссылочку на правльные исходники библиотеки. Буду очень признателен. |
Сообщ.
#61
,
|
|
|
может быть все таки не ssize_t, а size_t ????
Цитата typedef LONG_PTR ssize_t Вопрос, правильно ли я сделал? Я думаю не очень |
Сообщ.
#62
,
|
|
|
насколько я помню size_t это unsigned long, а ssize_t это long.
|
Сообщ.
#63
,
|
|
|
Сообщ.
#64
,
|
|
|
Цитата popsa @ насколько я помню size_t это unsigned long, а ssize_t это long. Я скачал файлик libmodbus-3.0.1.tar.gz, в нем хедер modbus-private.h, в строке 90 следующее: ssize_t (*send) (modbus_t *ctx, const uint8_t *req, int req_length); ssize_t (*recv) (modbus_t *ctx, uint8_t *rsp, int rsp_length); В MSDN на странице типов следующее: typedef LONG_PTR SSIZE_T typedef ULONG_PTR SIZE_T название переменных большими буквами, в хедере модбаса маленькими бюуквами. Вот я и добавил определение типа. Вроде скачивал библиотеку с родного сайта. Компилил, как понятно под виндовсом 7 в среде VS2010 C++. |
Сообщ.
#65
,
|
|
|
Да будет тебе известно, что в язике программирования Си и Си++, все регистро зависимо.
но у меня тип описан как typedef int ssize_t; |
Сообщ.
#66
,
|
|
|
у меня в солярисе
![]() ![]() #ifndef _SSIZE_T #define _SSIZE_T #if defined(_LP64) || defined(_I32LPx) typedef long ssize_t; /* size of something in bytes or -1 */ #else typedef int ssize_t; /* (historical version) */ #endif #endif /* !_SSIZE_T */ |
Сообщ.
#67
,
|
|
|
Цитата popsa @ у меня в солярисе ![]() ![]() #ifndef _SSIZE_T #define _SSIZE_T #if defined(_LP64) || defined(_I32LPx) typedef long ssize_t; /* size of something in bytes or -1 */ #else typedef int ssize_t; /* (historical version) */ #endif #endif /* !_SSIZE_T */ Эта библиотека заточена под линукс, я же кодю в WIN32. В ридми к этой библиотеке написано следующее: If you want to compile with Microsoft Visual Studio, you need to install http://code.google.com/p/msinttypes/ to fill the absence of stdint.h. Я скачал этот файлик и сохранил. Может в нем как раз и должен был быть описан этот тип? Кто кодит по WIN32, отзовитесь. |
Сообщ.
#68
,
|
|
|
Цитата Эта библиотека заточена под линукс, я же кодю в WIN32. В ридми к этой библиотеке написано следующее: If you want to compile with Microsoft Visual Studio, you need to install http://code.google.com/p/msinttypes/ to fill the absence of stdint.h. Я скачал этот файлик и сохранил. Может в нем как раз и должен был быть описан этот тип? Кто кодит по WIN32, отзовитесь. Раз написано делай, только stdint.h включи первым |
Сообщ.
#69
,
|
|
|
Обсуждение ModBus подтолкнуло меня к тому, что бы задать более общий вопрос. Часто приходится писать маленькие программы для опроса какого-либо устройства по ModBus (в основном для проверки устройств в процессе их наладки). Поскольку они заточены под конкретное устройство с фиксированным набором регистров, особых сложностей при опросе не возникает. Сейчас же стоит более сложная задача. Нужно делать что-то вроде системы визуализации, причем набор устройств может быть различным, устройства будут подключаться к шине RS-485, к которой подключен и компьютер(т.е. через один COM порт будут опрашиваться сразу несколько устройств). Опрос по протоколу ModBus. Хочу спросить, есть ли какие-нибудь статьи (или книги) по поводу разработки систем такого типа (получается что-то вроде куска SCADA, занимающегося только визуализацией)? Просто пока мои жалкие попытки приводят к каким-то разрозненным кускам кода, никак не связанным друг с другом. Параллельно пытаюсь разобраться в исходниках OpenScada. Если этот вопрос - сильный оффтоп, скажите, создам новую тему.
|
Сообщ.
#70
,
|
|
|
Цитата Dem_max @ Цитата Эта библиотека заточена под линукс, я же кодю в WIN32. В ридми к этой библиотеке написано следующее: If you want to compile with Microsoft Visual Studio, you need to install http://code.google.com/p/msinttypes/ to fill the absence of stdint.h. Я скачал этот файлик и сохранил. Может в нем как раз и должен был быть описан этот тип? Кто кодит по WIN32, отзовитесь. Раз написано делай, только stdint.h включи первым Я так и делаю. Только в том файлике, который я скачал с гугла нет типа о котором мы говорим. Отсюда вопрос, если этот файл не из библиотеки, а из гугла, то не вкралась ли в него какая либо неточность? Есть кто нибудь, кто работает с библиотекой под WIN32? Если есть такие, ответьте, есть в вашем файлике stdint.h тип ssize_t? |
Сообщ.
#71
,
|
|
|
Цитата Если есть такие, ответьте, есть в вашем файлике stdint.h тип ssize_t? смотри выше. |
Сообщ.
#72
,
|
|
|
Цитата Dem_max @ Да будет тебе известно, что в язике программирования Си и Си++, все регистро зависимо. но у меня тип описан как typedef int ssize_t; Ты кодиш под WIN32 для ModBus? Если да, можешь поделиться примерчиком использования библиотеки ModBus? |
Сообщ.
#73
,
|
|
|
trainer помоги плиз.
Разбираюсь с твоей библиотекой. Строка в примере PortId := TrComPortOpen(0); (* COM1 *) Я так понимаю, что PortId - это хендл порта? И по нумерации портов 0 - COM1 1 - COM2 и т.д.? Почему спрашиваю, при выполнении PortId := TrComPortOpen(0); возвращается "0" D2010, Win7 |
Сообщ.
#74
,
|
|
|
Цитата сколько устройств будет? Чито мешает взять сразу готовую SCADA? На 32 точки большинство бесплатно, TraceMode например. MasterSCADAполучается что-то вроде куска SCADA, занимающегося только визуализацией)? Просто пока мои жалкие попытки приводят к каким-то разрозненным кускам кода например, сама по себе бесплатна. PascalSCADA под Лазарус. |
Сообщ.
#75
,
|
|
|
Всем привет.
Прикрутил к своей разработки компоненту для rs232 из этого проекта https://github.com/tarasii/1c_rs232 Кто может помочь прикрутить ModBus для rs485 ? команды имеют вот такой вид "CC0500051800EE" есть исходники от другой компоненты(работает через ком) где есть рабочий код. |
Сообщ.
#76
,
|
|
|
Цитата unduty @ Кто может помочь прикрутить ModBus для rs485 ? А проблема-то в чем? Поддержка ModBus-подобных протоколов реализуется прекрасно без всяких левых компонент, и обычно довольно быстро. Делать за вас всю работу никто просто так не будет. Добавлено На прикладном уровне работа с RS485/232 обычно мало чем отличается. |
Сообщ.
#77
,
|
|
|
Цитата shm @ А проблема-то в чем? Поддержка ModBus-подобных протоколов реализуется прекрасно без всяких левых компонент, и обычно довольно быстро. Делать за вас всю работу никто просто так не будет. [QUOTE] По оплате в личке давайте обсудим. Тому кто этим занимается работы на час. Участок который нужно перенести подписан разработчиком. |
Сообщ.
#78
,
|
|
|
Подниму старую тему. Но для меня новую.
Чтобы прояснить. В сети один мастер, например ноутбук, общается через переходник, например с 20-тью устройствами типа слейв, с соответствующими адресами. Устройства, слейв, типа реле. Включено, выключено... Слейв ничего не шлют в сеть? Мастер их постоянно дёргает? Я один раз в сеть кинул сообщение, "давай реле#18, включись". Слейв.id 18, включилось нет? Никто не знает. Мастер, спрашивает, включено или нет... Проясните в голове |
Сообщ.
#79
,
|
|
|
Цитата Serega_mexanik @ Слейв ничего не шлют в сеть? Мастер их постоянно дёргает? Я один раз в сеть кинул сообщение, "давай реле#18, включись". Слейв.id 18, включилось нет? Может зависеть от реализации. Нужно читать доки на конкретные устройства. --- Но если реализация хорошая, то конечно, слэйвы должны отвечать. Данными, если из него читаются данные. Или статусом, если выполняется запись. Сам факт ответа - уже статус. Что дивайс включен и работоспособен. Ответ не высылается на широковещательное сообщение - сообщение по адресу 0. --- Например, даётся команда "включить реле", а такой команды у конкретного дивайса нет. Или команда не выполнена по причине неисправности. Или выполнена успешно. Надо ответить кодом возврата операции. Всё это должно быть подробно описано в доках на дивайсы. хороший вариант описания |
Сообщ.
#80
,
|
|
|
Про формат посылки.
Это массив. Без знаковое, целое. 8 или 16. Почему, например не _int64 ? uint8 mas[7]; При передаче mas[0]=10; //0x10 сетевой адрес устройства mas[1]=0x00;//код функции запроса(это чтение, запись и ещё что-то)? mas[2]=100;//общая длина пакета. Где берецца? Из мануала к устройству? mas[3]=0x0*; mas[4]=0x0*; mas[5]=0x0*;// входные данные запроса. Берём из мануала к девайсу. (длина определяется mas[2] mas[6]=0x0*//идентификатор запроса. Тоже не ясно mas[7]= func_CRC16();// контрольная сумма (uint16_t) которая рассчитана хитро-функцией... Дальше, просто в порт кидаем данные. ComPort->send(mas[7]); И ждём ComPort->read(mas_otvet[7);//? Младший байт/старший. Пока непонятно что и зачем. Но в двух словах, Я спрашиваю девайсу, "какая температура", он отвечает в виде, например 25.5град, но виде кракозябр, которые расшифровываются своей функцией? |
Сообщ.
#81
,
|
|
|
Цитата Serega_mexanik @ Описаний Modbus в сети вагон и маленькая тележка. Начиная от википедии на русском и заканчивая полным описанием от авторов этого стандарта на английском. Вы хотите, чтобы вам их здесь пересказали? Зачем? Про формат посылки. |
Сообщ.
#82
,
|
|
|
Цитата Serega_mexanik @ Про формат посылки. Это массив. Без знаковое, целое. 8 или 16. Почему, например не _int64 ? Потому, что стандартный (широко распространённый) UART использует для приёма/передачи байты. Добавлено Цитата Serega_mexanik @ mas[2]=100;//общая длина пакета. Где берецца? Из мануала к устройству? В том числе. Но вообще-то у классического модбаса нет такой переменной. У многочисленных типа-его реализаций может быть. Для удобства. Переменная должна быть рассчитана при формировании конкретного пакета. Добавлено Цитата Serega_mexanik @ mas[6]=0x0*//идентификатор запроса. Тоже не ясно Дополнительная переменная, идентифицирующая конкретный пакет. Должна содержаться в ответе. Показывает, что полученный ответ на тот самый конкретный запрос. Добавлено Цитата Serega_mexanik @ И ждём ComPort->read(mas_otvet[7);//? Младший байт/старший. Пока непонятно что и зачем. Но в двух словах, Я спрашиваю девайсу, "какая температура", он отвечает в виде, например 25.5град, но виде кракозябр, которые расшифровываются своей функцией? Это всё читаем в доках на дивайс. Какой будет ответ, в каком формате данные, статусы итд. |
Сообщ.
#83
,
|
|
|
Ничего не понятно. Но, оч интересно.
Тыкните носом, что курить. Буду благодарен за кусочек кода |
Сообщ.
#84
,
|
|
|
Цитата Serega_mexanik @ Тыкните носом, что курить. Цитата Dushevny @ Начиная от википедии на русском и заканчивая полным описанием от авторов этого стандарта на английском. "Чтение документации из интернета вслух- 100 евро в час." |
Сообщ.
#85
,
|
|
|
Проблема свелась к преобразованию string to byte или byte[]
|