Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.11.2013, 18:51   #1
Desperadoes
 
Регистрация: 16.11.2013
Сообщений: 7
По умолчанию Запрос и ответ из COM порта

Здравструйте Уважаемые! Помогите советом.
Есть у меня задача получать данные через GSM модем в SCADA систему по протоколу MODBUS RTU. По сути задача состоит в отправке запросов в COM порт и считывание ответов. Непонятная мне штука происходит при работе с COM портом в SCADA. Выполняю следующие действия
1) PORT OPEN
2)COM_WRITE
3) COM_REED
Собственно проблема: в программе PortMon видно что после запроса ответ встает впереди запроса.На екране это отражается так:Считываю данные сейчас а отображение идет за прошлое считывание. Объясните в чем тут тайна.
При этом имеется родная программа (Она не подходит) в которой все по человечески, запрос потом ответ.
В чем может быть причина?
Вот логи COM порта при работе со скодой и с родной программой "терминал"
Вложения
Тип файла: txt запрос ответ от скады.txt (12.9 Кб, 159 просмотров)
Тип файла: txt Запрос ответ от терминала.txt (4.1 Кб, 167 просмотров)

Последний раз редактировалось Desperadoes; 16.11.2013 в 18:56. Причина: дополнение
Desperadoes вне форума Ответить с цитированием
Старый 16.11.2013, 23:22   #2
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,742
По умолчанию

Цитата:
Считываю данные сейчас а отображение идет за прошлое считывание
нет тайны, усе по порядку.

в родной:
Цитата:
IRP_MJ_WRITE Length 8: 01 03 B3 C0 00 04 62 B1
IRP_MJ_READ Length 13: 01 03 08 67 EF F8 00 00 00 3F E2 48 D
в вашей:
Цитата:
IRP_MJ_WRITE USBSER001 SUCCESS Length 1: 01
IRP_MJ_WRITE USBSER001 SUCCESS Length 1: 03
IRP_MJ_WRITE USBSER001 SUCCESS Length 1: B3
IRP_MJ_WRITE USBSER001 SUCCESS Length 1: 0C
IRP_MJ_WRITE USBSER001 SUCCESS Length 1: 00
IRP_MJ_WRITE USBSER001 SUCCESS Length 1: 04
IRP_MJ_WRITE USBSER001 SUCCESS Length 1: A2
IRP_MJ_WRITE USBSER001 SUCCESS Length 1: 8E
и т.д.
IRP_MJ_READ Length 13: 01 03 08 43 78 4B 39 42 D9 58 B9 85 BA
В вашей не пакет данных отправляется, а одиночными байтами. Вы буфер на можете записать?

p.s.: и набор номера ATD должен оканчиваться ";"
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 17.11.2013, 00:09   #3
Desperadoes
 
Регистрация: 16.11.2013
Сообщений: 7
По умолчанию

Спасибо за ответ. Команда "АТ" должна заканчиваться ";" в режиме голосового дозвона в режиме "CSD"соеденения без ";". Пробовал одним пакетов тоже самое. Даже без команда Com_Reed. Смущает то что в конце после записи в COM порт, устанавливается "IRP_MJ_READ"?
Вложения
Тип файла: txt запрос одим пакетом.TXT (2.1 Кб, 157 просмотров)
Desperadoes вне форума Ответить с цитированием
Старый 17.11.2013, 12:21   #4
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,742
По умолчанию

В том, что вы приложили 'запрос одим пакетом.TXT' нет вашей пробы, там просто настройка порта, ни запроса, ни ответа. Показывайте как формируете пакет. Впрочем, по предыдущим логам видно что неправильно формируете.
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 17.11.2013, 23:40   #5
Desperadoes
 
Регистрация: 16.11.2013
Сообщений: 7
По умолчанию

Спасибо raxp Вам за помощь! посмотрите пожалуйста новый лог. Мне удалось сформировать запрос одним пакетом. но считывание порта после запроса не происходит. почему то.
Вложения
Тип файла: txt Запрос.txt (2.4 Кб, 143 просмотров)
Desperadoes вне форума Ответить с цитированием
Старый 18.11.2013, 08:34   #6
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,742
По умолчанию

Так может воссоздадите одинаковые условия с терминалом? В последнем логе у вас запрос модбас-пакетом сразу после настройки порта:
Цитата:
0.00000168 Citect32.exe IOCTL_SERIAL_SET_LINE_CONTROL Serial0 SUCCESS StopBits: 1 Parity: NONE WordLength: 8
267 0.00000050 Citect32.exe IOCTL_SERIAL_SET_CHAR Serial0 SUCCESS EOF:0 ERR:0 BRK:0 EVT:0 XON:11 XOFF:13
268 0.00000175 Citect32.exe IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Shake:1 Replace:40 XonLimit:2048 XoffLimit:512
269 0.00000291 Citect32.exe IOCTL_SERIAL_SET_DTR Serial0 SUCCESS
270 111.59232309 Citect32.exe IRP_MJ_READ Serial0 CANCELLED Length 1024
271 0.00000327 Citect32.exe IOCTL_SERIAL_SET_WAIT_MASK Serial0 SUCCESS Mask: CTS DSR RLSD RING
272 111.59038530 Citect32.exe IOCTL_SERIAL_WAIT_ON_MASK Serial0 SUCCESS
273 0.00002770 Citect32.exe IRP_MJ_WRITE Serial0 SUCCESS Length 8: 01 03 B3 0C 00 04 A2 8E
Терминал же сначала дозванивается:
Цитата:
8 0.00798174 Terminal.exe IOCTL_SERIAL_SET_LINE_CONTROL USBSER001 SUCCESS StopBits: 1 Parity: NONE WordLength: 8
9 0.00000102 Terminal.exe IOCTL_SERIAL_SET_CHAR USBSER001 SUCCESS EOF:0 ERR:0 BRK:0 EVT:0 XON:11 XOFF:13
10 0.00000076 Terminal.exe IOCTL_SERIAL_SET_HANDFLOW USBSER001 SUCCESS Shake:1 Replace:40 XonLimit:1024 XoffLimit:1024
11 0.00000068 Terminal.exe IOCTL_SERIAL_SET_QUEUE_SIZE USBSER001 SUCCESS InSize: 4096 OutSize: 2048
12 0.00000077 Terminal.exe IOCTL_SERIAL_SET_TIMEOUTS USBSER001 SUCCESS RI:-1 RM:0 RC:0 WM:0 WC:0
13 0.00000232 Terminal.exe IOCTL_SERIAL_SET_WAIT_MASK USBSER001 SUCCESS Mask: RXCHAR RLSD
14 7.52967472 Terminal.exe IOCTL_SERIAL_WAIT_ON_MASK USBSER001 SUCCESS
15 0.00077602 Terminal.exe IRP_MJ_WRITE USBSER001 SUCCESS Length 15: ATD0504287933..
16 0.00000197 Terminal.exe IOCTL_SERIAL_GET_COMMSTATUS USBSER001 SUCCESS
17 0.00000121 Terminal.exe IRP_MJ_READ USBSER001 SUCCESS Length 15: ATD0504287933..
18 7.95287196 Terminal.exe IOCTL_SERIAL_WAIT_ON_MASK USBSER001 SUCCESS
19 0.00000165 Terminal.exe IOCTL_SERIAL_GET_COMMSTATUS USBSER001 SUCCESS
20 0.00000159 Terminal.exe IRP_MJ_READ USBSER001 SUCCESS Length 14: ..NO CARRIER..
21 10.26963453 Terminal.exe IOCTL_SERIAL_WAIT_ON_MASK USBSER001 SUCCESS
22 0.00027212 Terminal.exe IRP_MJ_WRITE USBSER001 SUCCESS Length 15: ATD0504287933..
23 0.00000216 Terminal.exe IOCTL_SERIAL_GET_COMMSTATUS USBSER001 SUCCESS
24 0.00000155 Terminal.exe IRP_MJ_READ USBSER001 SUCCESS Length 15: ATD0504287933..
25 24.44635949 Terminal.exe IOCTL_SERIAL_WAIT_ON_MASK USBSER001 SUCCESS
26 0.00000308 Terminal.exe IOCTL_SERIAL_WAIT_ON_MASK USBSER001 SUCCESS
27 0.00000109 Terminal.exe IOCTL_SERIAL_GET_COMMSTATUS USBSER001 SUCCESS
28 0.00000157 Terminal.exe IRP_MJ_READ USBSER001 SUCCESS Length 16: ..CONNECT 9600..
29 21.75519736 Terminal.exe IOCTL_SERIAL_WAIT_ON_MASK USBSER001 SUCCESS
30 0.00061812 Terminal.exe IRP_MJ_WRITE USBSER001 SUCCESS Length 8: 01 03 B3 C0 00 04 62 B1
31 0.00000177 Terminal.exe IOCTL_SERIAL_GET_COMMSTATUS USBSER001 SUCCESS
32 0.00000166 Terminal.exe IRP_MJ_READ USBSER001 SUCCESS Length 13: 01 03 08 67 EF F8 00 00 00 3F E2 48 D6
Да и несмотря на одинаковые функции и адрес запроса, содержимое запроса разное, хотя это уже вторично.
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 19.11.2013, 19:36   #7
Desperadoes
 
Регистрация: 16.11.2013
Сообщений: 7
По умолчанию

После долгих испытаний и проверок проведенных мной. Я пришел к выводу что управление портом происходит автоматически. При отключенном оборудовании, комнда СomReed устанавливает SET_DTR. А при включенном оборудовании, после любой посілки в порт автоматически устанавливвается IRP_MJ_READ, и порт переходит на чтение. и при последующей посылке в порт, данные автоматом передаются в буфер чтения. Поэтому я в буфере и вижу на одну строку позже. Но к сожалению я пока не разобрался, возможно как управлять сигналами DTR. чтобы устанавливать сигнал к приему данных после записи в порт. Пока выход такой: я двараза делаю СomReed чтобы буфер затерся новой инфой. Далее буду разбираться. Спасибо raxp за помощь!
Desperadoes вне форума Ответить с цитированием
Старый 19.11.2013, 21:13   #8
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,742
По умолчанию

Если надо управлять сигналом DTR, то им элементарно рулить через EscapeCommFunction() / см. MSDN. Если у вас обертка какая для работы с COM-портом (скажем BComPort или COMM32), то наверняка там есть такое, а нет, сами добавьте одну WinAPI функу после открытия порта.

Наглядный пример руления COM-портом (DTR/RTS) из скрипта VBS, можно даже прямо из батника (я мог бы написать и сразу в Delphi:
Код:
EscapeCommFunction(hFile, 5)
но VBS тем удобнее что не нужно ничего дополнительно устанавливать и код для других нагляден):



Описание API вызова RunGetKeyboardSetcom.VBS:
Код:
' RunGetKeyboardSetcom.VBS
' Пример простейшего скрипта определения RUS-LAT раскладки 
' + контроля DTR or RTS порта COM (or virtual COM over USB) на VBS
' + голосового сопровождения при переключении раскладки
' через COM-сервер DynWrapx.dll
' Разработчик: Бадло Сергей Григорьевич
' H-page: http://raxp.radioliga.com
' Ограничения: Win OS


' подключаем голосовое сопровождение
Dim Speak
Set Speak = CreateObject("sapi.spvoice")
' регистрируем COM объект DynamicWrapperX в тихом режиме
Dim WshShell 
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run ("regsvr32.exe dynwrapx.dll /s"),3, true
' создаем объект DynamicWrapperX
Set Wrap = CreateObject("DynamicWrapperX")
Wrap.Register "user32.dll", "GetKeyboardLayout", "i=l", "f=s", "r=l"
Wrap.Register "user32.dll", "GetForegroundWindow", "f=s", "r=l"
Wrap.Register "user32.dll", "GetWindowThreadProcessId", "i=ll", "f=s", "r=l"
' регистрируем функи для работы с портом
Wrap.Register "KERNEL32.DLL", "CreateFile", "i=sllllll", "r=l"
Wrap.Register "KERNEL32.DLL", "WriteFile", "i=lllll", "r=l"
Wrap.Register "KERNEL32.DLL", "CloseHandle", "i=l", "r=l"
Wrap.Register "KERNEL32.DLL", "EscapeCommFunction", "i=hu", "r=l"
' забиваем аттрибуты
GENERIC_WRITE = 1073741824
FILE_SHARE_READ = 1
FILE_SHARE_WRITE = 2
OPEN_EXISTING = 3
FILE_ATTRIBUTE_NORMAL = 128
' пин 7
SETRTS = 3 ' Set RTS high
CLRRTS = 4 ' Set RTS low
' пин 4
SETDTR = 5 ' Set DTR high
CLRDTR = 6 ' Set DTR low
' открываем нужный нам порт COM1
hFile = Wrap.CreateFile("COM1", GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
' отключаем сигналы
s = Wrap.EscapeCommFunction(hFile, 4)
s = Wrap.EscapeCommFunction(hFile, 6)
' определяем для активной нити
hWindow = Wrap.GetForegroundWindow()
idProcess = Wrap.GetWindowThreadProcessId(hWindow, 0)
res = Wrap.GetKeyboardLayout(idProcess)

' активируем нужный сигнал до цикла
if (res = "67699721") then 
 s = Wrap.EscapeCommFunction(hFile, SETRTS)
 s = Wrap.EscapeCommFunction(hFile, CLRDTR)
 Speak.Speak "Установлена английская раскладка клавиатуры."
End if
if (res = "68748313") then 
 s = Wrap.EscapeCommFunction(hFile, SETDTR)
 s = Wrap.EscapeCommFunction(hFile, CLRRTS)
 Speak.Speak "Установлена русская раскладка клавиатуры."
End if

' запускаем бесконечный цикл с задержкой
Do
WScript.Sleep 1000 'кол-во миллисекунд
hWindow = Wrap.GetForegroundWindow()
idProcess = Wrap.GetWindowThreadProcessId(hWindow, 0)
res2 = Wrap.GetKeyboardLayout(idProcess)
if (res2 <> res) and (res2 = "67699721") then 
 s = Wrap.EscapeCommFunction(hFile, SETRTS)
 s = Wrap.EscapeCommFunction(hFile, CLRDTR)
 ' при надоедливости голоса комментируем его
 Speak.Speak "English."
End if
if (res2 <> res) and (res2 = "68748313") then 
 s = Wrap.EscapeCommFunction(hFile, SETDTR)
 s = Wrap.EscapeCommFunction(hFile, CLRRTS)
 ' при надоедливости голоса комментируем его
 Speak.Speak "Rus."
End if
res = res2
Loop
Wrap.CloseHandle(hFile)
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 19.11.2013, 21:13   #9
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,742
По умолчанию

Описание (не влезло):
Цитата:
Данный VBS-скрипт предназначен для определения раскладки клавиатуры (по-умолчанию RUS/LAT) активного окна и автоматического управления внешней подсветкой (светодиодами, светодиодной лентой или иной нагрузкой через умощняющие ключи с соответствующей развязкой) путем контроля сигналов DTR (пин 4)/RTS (пин 7) последовательного физического или виртуального COM-порта over USB (на основе USB/UART конверторов типа CP21xx/FTDI/PL2303 и прочих), c голосовым сопровождением при переключении раскладки.

Сам VBScript умеет работать только с COM-объектами, для работы с WinAPI функциями используется внешний COM-сервер (библиотека) 'dynwrap.dll' или 'dynwrapX.dll'. Данная библиотека распространяется свободно. COM-сервер (ActiveX) позволяет вызвать любую экспортируемую функцию любой DLL. Cвоего рода, обертка. Как и любой COM - объект, 'dynwrap.dll' тоже требует регистрации в системе. В скрипте осуществлена его авторегистрация при запуске в скрытом режиме.

ПОРЯДОК ИСПОЛЬЗОВАНИЯ

1. Подключите контролируемую нагрузку к COM-порту или USB-конвертор (считаем, что драйвера уже установлены).
2. Запуститите скрипт 'rungetkeyboardsetcom.vbs' или инструкцию 'ЗАПУСТИТЬ инструкцию в голосовом режиме!.vbs'.
3. При запуске будет осуществлено управление сигналами RTS/DTR и озвучена текущая раскладка.
4. При необходимости озвучивание можно деактивировать закомментировав метод Speak объекта 'sapi.spvoice'.
====================
Цитата:
Я пришел к выводу что управление портом происходит автоматически. При отключенном оборудовании
так у вас что, конвертор со стороны COM-порта, вроде RS-485/RS-232 и он не автоматический? Обычно в таких конверторах RTS-ом управляют для контроля направления приема-передачи. Давайте-ка подробнее в виде схемы подключений, что у вас там за COM порт к Скаде?
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation

Последний раз редактировалось raxp; 19.11.2013 в 21:23.
raxp вне форума Ответить с цитированием
Старый 20.11.2013, 20:26   #10
Desperadoes
 
Регистрация: 16.11.2013
Сообщений: 7
По умолчанию

Имеется SCADA Citect 7.10 и GSM модем Cinterion MC52i Terminal подключенный к COM порту компютера по RS232. Необходимо считывать данные с удаленного расходомера UVR-011. Обмен данными происходит по протоколу MODBUS RTU. После того как модем дозвонился, и установилась связь модем переходит в режим передачи данных и я ему даю запросы в формате MODBUS RTU.
В самой скаде я конфигурирую порт рис1. В самой скаде есть свой язык програмирования Cicode (Паскалеподобный) там я и пишу свой код используя ихние функции ComOpen, ComWrite, ComReed.
Когда к COM порту ничего не подключено, команда ComReed устанавливает (IOCTL_SERIAL_SET_DTR это вижу в PortMon),команда ComWrite отправляет в порт данные и устанавливает IOCTL_SERIAL_GET_COMMSTATUS и ничего не происходит.Но когда к порту подключен модем, команда ComWrite отправляет в порт данные и устанавливает IRP_MJ_READ. не зависимо послал я команду ComReed или нет. А уже если я пошлю команду ComReed, то она мне вычитает данные которые уже есть в буфере. Вот я думаю что после посылки в порт он сам переключает сигналы DTR и переходит в режим приема данных. А в родной программе там в ручную сначала отправляют команду потом принимают данные. Вот я и пытаюсь отделить мух от котлет.
Изображения
Тип файла: jpg COM.JPG (91.8 Кб, 135 просмотров)

Последний раз редактировалось Desperadoes; 20.11.2013 в 20:32.
Desperadoes вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
В ответ на DDE запрос приходит идентификатор данных Sauber Общие вопросы Delphi 1 13.11.2013 12:12
Посылаем запрос на программу и получаем ответ vlastelin PHP 3 22.03.2012 19:48
Idhttp ответ на post запрос andrejjka Работа с сетью в Delphi 1 30.01.2011 13:41
POST Запрос/Ответ IvanBegin Работа с сетью в Delphi 3 02.11.2010 16:50
скрипт для смс запрос-ответ elias_p PHP 1 16.06.2010 16:22