Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.191.88.249] |
|
Сообщ.
#1
,
|
|
|
Помогите!!! начал разбираться с работой с ком портами попал в руки прибор который работает по протоколу ModBus RTU. настряпал вот такую програмку но она не работает!!!
Я так и не могу прочитать данных с порта помогите плиз!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! исходник на билдере здесь: vortekc.narod.ru/MyModBus.zip или может кто знает фриварный компонент для работы с ModBus |
Сообщ.
#2
,
|
|
|
В чем его(ModBus'а) основные особенности?
|
Сообщ.
#3
,
|
|
|
Пример команды чтения 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 ----------------- Пардоньте, забыл вписать коды ошибок. Вложен новый файл. Прикреплённый файлTrComPort.rar (28.46 Кбайт, скачиваний: 8195) |
Сообщ.
#9
,
|
|
|
ОК. Скачал, огромное спасибо.
Коментарии принимаются? Если да то немножко попозже. Удачи. Александр. |
Сообщ.
#10
,
|
|||
|
Непременно
|
Сообщ.
#11
,
|
|
|
Спасибо всё работает. Замечаний оссобых нет кроме нескольких опечаток в ReadMe.txt в примерах на С++ там пару констант немножко не так обозвал Но это не очень важно А так всё работает!!! Может что поже вылезет тогда сообщу
Да, ты случайно не знаешь как мне быть с такой проблемкой: я вот получаю массив с ответом от прибора, но нужнные данные только два элемента скажем 3 и 4. Тоесть 3 это младший байт слова а 4 соответственно старший. Вот как мне их склеить и получить число записанное этими двумя байтами? Зарание спасибо!!!! |
Сообщ.
#12
,
|
|||
|
Ну это вариантов много, например: BYTE buffer[n]; WORD value = *((WORD *)(buffer+2));// это если считать как все нормальные люди(3-ий - это смещение 2) Добавлено в
Я его на скорую руку писАл.
|
Сообщ.
#13
,
|
|
|
Может это и ламерский вопрос но всё же: почему в результате ниже следующей операции компилятор мне выдаёт значение value = 58369 вместо нужных 484?
buff[0]=0x1; buff[1]=0xE4; WORD value =*((WORD *) (buff)); |
Сообщ.
#14
,
|
|||||
|
Потому, что порядок не тот. Не:
А наоборот: 3 - старший, 4-младший .
Тогда:WORD value = ((byte[2]<<8)|byte[3])&0xffff; |
Сообщ.
#15
,
|
|
|
Спасибо, но я тут сам немножко подумал и решил зделать с помошью асма
mov ah,rd_buffer[3]; mov al,rd_buffer[4; mov Chislo,ax; Ну вот теперь у меня вроде всё работает, но есть проблемка я же всёравно не понимаю как оно доконца работает. Поделись пожалуйста исходниками своей библиотеки. Уж очень разобраться охота. Зарание благодарен Саша! |
Сообщ.
#16
,
|
|||
|
Вот этого я сделать не могу.
Коммерческая разработка. |
Сообщ.
#17
,
|
|
|
Могу подкинуть сорс класса реализующего работу с СОМ-портом. Класс правда для Visual С, но думаю идею он раскрыть сможет.
Я его юзаю постоянно. Буду вопросы - пиши. Прикреплённый файлSerialPort.zip (6.67 Кбайт, скачиваний: 1595) |
Сообщ.
#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[]
|