
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.207] |
![]() |
|
Сообщ.
#1
,
|
|
|
Здравствуйте. Не знаю, как правильно организовать передачу АТ-команд и приём ответов от модема. Как с этими СОМ-портами работать правильно?
Открываю порт через СreateFile. Отправляю команду ATH через writefile. В ответ (readfie) вместо Ok получаю только один байт - $13. В общем, кто разобрался с СОМ и с модемами, отзовитесь. |
Сообщ.
#2
,
|
|
|
19 Connect 38400 Установлена связь на скорости 38400бит/с
С модемом не работал, но игрался с ком мышью. Собственно ошибок не вижу. Решил поработать с модемом. Тав возращается не один байт, а несколько. |
Сообщ.
#3
,
|
|
|
Цитата Открываю порт через СreateFile. Отправляю команду ATH через writefile. В ответ (readfie) вместо Ok получаю только один байт - $13. Попробуй отправлять просто команду 'AT#13#10', не помню точно, но вроде на ATH модем ответ не дает. Также можешь воспользоваться моим компонентом KlientServComConnect - он как раз предназначен для работы с модемом и COM-портом. |
Сообщ.
#4
,
|
|
|
zubr прав, все AT команды должны заканчиваться парой CR/LF.
Сразу предупрежу, что желательно использовать апаратный контроль потока данных. И перед каждым чтением проверять наличие байта в приемном буфере. Иначе функции чтения будут виснуть, и даже с использованием оверлеев, пока функция чтения не вернется, писать в порт нельзя. Добавлено Конкретно с модемом я не работал, зато много работал с собственными устройствами по RS232 (COM). |
Сообщ.
#5
,
|
|
|
Цитата Попробуй отправлять просто команду 'AT#13#10', не помню точно, но вроде на ATH модем ответ не дает. Также можешь воспользоваться моим компонентом KlientServComConnect - он как раз предназначен для работы с модемом и COM-портом. Цитата zubr прав, все AT команды должны заканчиваться парой CR/LF. Сразу предупрежу, что желательно использовать апаратный контроль потока данных. И перед каждым чтением проверять наличие байта в приемном буфере. Иначе функции чтения будут виснуть, и даже с использованием оверлеев, пока функция чтения не вернется, писать в порт нельзя. Так и передаю, вместе с #13#10. В ответ модем должен выдавать строку #13#10 OK #13#10, а я получаю только #13. А что такое аппаратный контроль данных. Как это реализовывается? Про оверлеи я почитал(на англ.), но не очень понял, куда их тулить. Пока понял так, что если оверлеи не используются, то команды чтения не "заканчиваются" до тех пор, пока не будет принят хотя-бы один символ. Это правильно? У меня так и происходит, то Wait, то Read виснут. В общем, нет у меня чёткого представления, как должен быть реализован обмен, что-то не учитываю. Я делаю так: write - команда wait - в буфер принят символ read - ответ. Ненадёжно работает. Первую команду отправляю, получаю один байт #13, на последующие вроде нормальную строку получаю. Чувствую, чего-то я не догоняю, как обмен происходит, там ведь еще всякие сигнал есть: DSR,CTS... Я могу и код представить. Только позориться не хочется. Пока только эксперименты. Конечная цель - дозвониться до абонента и передать голосовое сообщение(голосовой модем). zubr, а где взять KlientServComConnect? Поддерживает ли он голосовые функции? Если не получится ручками, придется, конечно, готовыми компонентами пользоваться. |
Сообщ.
#6
,
|
|
|
Взять можно здесь: Klientservcomconnect. Голосовые функции не поддерживает, есть полный Help + примеры работы с ним.
|
Сообщ.
#7
,
|
|
|
Вот результаты "исследований".
Для обмена с модемом используется вот такая функция ![]() ![]() function SendCommand(const command:string):string; var writed,readed:dword; buffer:array[1..64]of byte; i:byte; c:string; evtmask,mask:dword; begin result:=''; c:=command+char($0d)+char($0a); for i:=1 to length(c) do buffer[i]:=byte(c[i]); PurgeComm(COMPort,PURGE_TXCLEAR or PURGE_RXCLEAR); if s<>'' then if not writefile(COMPort,buffer,length(c),writed,nil) then begin exit; end; mask:=EV_RXCHAR; setcommmask(COMPort,mask); if not WaitCommEvent(COMPort,mask,nil) then begin exit end; sleep(100); if not readfile(COMPort,buffer,64,readed,nil) then begin exit; end; if readed=0 then begin exit; end; for i:=1 to readed do result:=result+char(buffer[i]); end; Дальше передаю команды ![]() ![]() s:='AT#CLS=8 #VSR=8000 #VBS=4'; r:=sendcommand(s); form1.memo1.Lines.Add(s); form1.memo1.Lines.Add(r); s:='ATD80973595377'; r:=sendcommand(s); form1.memo1.Lines.Add(s); form1.memo1.Lines.Add(r); sleep(5000); s:='AT#VTX'; r:=sendcommand(s); form1.memo1.Lines.Add(s); form1.memo1.Lines.Add(r); for i:=1 to 5 do begin s:=''; r:=sendcommand(s); form1.memo1.Lines.Add(s); form1.memo1.Lines.Add(r); end; s:=char($10)+char($18); r:=sendcommand(s); form1.memo1.Lines.Add(s); form1.memo1.Lines.Add(r); s:='ATH0'; r:=sendcommand(s); form1.memo1.Lines.Add(s); form1.memo1.Lines.Add(r); в результате имею вот такой диалог ![]() ![]() AT#CLS=8 #VSR=8000 #VBS=4 OK ATD80973595377 VCON AT#VTX CONNECT d d d d d d VCON ATH0 OK Квадратики - это $10. Т.е., модем дозванивается, переключается в режим передачи данных. А вот дальше какая-то загадка. Если ничего не передавать, то модем через некоторое время выдает вот эти самые строки - $10d$10, что-то в этом роде. Если передаю небольшой буфер, модем вроде "квакает" что-то. Если передаю большой буфер, например 10000 байт, функция writefile виснет. В общем, буду благодарен, если кто-нибудь знает, как передавать голосовые данные модему. |
Сообщ.
#8
,
|
|
|
Prince
Вопрос:"А голосовые данные откуда берешь???" Цитата Prince @ Если передаю небольшой буфер, модем вроде "квакает" что-то. Если передаю большой буфер, например 10000 байт, функция writefile виснет. А чтобы не было зависаний перейди на асинхронный режим работы с портом и периодически проверяй Overlap.Event,которая привязана к writefile, только Event с ручным сбросом. После того как модем выдаст тебе CONNECT проверяй событие порта EV_RLSD (связь модемов установлена), и только при наступлении этого события можно начинать работу с данными, ну а какой будет протокол решать тебе. ![]() |
Сообщ.
#9
,
|
|
|
Так у меня ведь связь не с модемом, а с телефоном устанавливается. Или без разницы? С асинхронным режимом я пока не разобрался. Мне бы пока хоть с синхронным. А данные пытаюсь передавать из wav файла. Протокол(формат) 8000 Гц 4 бита ADPCM(вроде бы). Но как их передавать, эти данные. Есть там, видимо, какой-то секрет, а какой?
|
Сообщ.
#10
,
|
|
|
Prince
Цитата Prince @ Так у меня ведь связь не с модемом, а с телефоном устанавливается. Или без разницы? Так бы и сказал. Разница есть, даже очень. Большая проблема узнать момент снятия трубки на том конце. И сразу вопрос Цитата Prince @ А данные пытаюсь передавать из wav файла. А на том конце у человека звуковуха в ухе, что ли???? Или ты пытаешьсяпроиграть данные в линию со звуковухи. Это вообще то совсем другой коленкор |
Сообщ.
#11
,
|
|
|
Цитата Или ты пытаешьсяпроиграть данные в линию со звуковухи. Это вообще то совсем другой коленкор Ну да, пытаюсь. Только не со звуковухи, а из файла. А как по другому это сделать? |
Сообщ.
#12
,
|
|
|
Цитата Prince @ Ну да, пытаюсь. Только не со звуковухи, а из файла Поясни как ты файл звука превратишь в аналог ![]() |
Сообщ.
#13
,
|
|
|
Это модем занимается переводом в аналог. Я ему передаю команду AT#VTX, и он переходит в режим передачи голосовых данных, возвращая СONNECT. Дальше, по идее, я ему сливаю звуковой поток, а кодек модема(модем голосовой) переводит этот поток в аналог. Вот с этим и проблема. В конце звукового потока я передаю модему 2 байта - $10 $18. Модем снова переходит в командный режим и в ответ выдаёт VCON(см. лог выше). Вот примерно так. Ну а дальше снова можно испоьлзовать обычные AT-команды.
|
Сообщ.
#14
,
|
|
|
PrinceИзвини уж неугомонного, но:
Цитата Prince @ я ему сливаю звуковой поток, а кодек модема(модем голосовой) переводит этот поток в аналог. Вот с этим и проблема. Сливаешь ему просто Wav файл???Или же чистые данные??? Цитата Prince @ Протокол(формат) 8000 Гц 4 бита ADPCM(вроде бы). Но как их передавать, эти данные Вроде бы тут не прокатит А ты пробовал Wav файл проиграть на чем нибудь с таким форматом??? ![]() ![]() ![]() сжатие ADPCM: (Частота выборки) предлагаются следующие значения: 5 кГц - приемлем только для речи; 11 кГц - самое низкое рекомендуемое качество для короткого музыкального фрагмента; четверть стандартного значения качества CD (компакт-диска); Что то непонятка какая-то с протоколами сжатия:wacko: ![]() |
Сообщ.
#15
,
|
|
|
Сливаю чистые данные формата ADPCM, моно, 8000 Гц, 4 бита без заголовка, естественно.
Этот формат поддерживается модемом. Кроие того, он поддерживает частоты 7200Гц и 11025 Гц. И еще 2 и 8 бит. Вообще модемы могут поддерживать PCM, ADPCM, и GSM6.10 в зависимости от производителя и модели. Проиграть файл можно хотя бы универсальным проигрывателем или медиа-плеером. У меня проблема с передачей звуковых данных. Есть много ньюансов. Оказывается, есть там всякие управляющие коды и нужен аппаратный контроль данных, чтобы не было переполнения буфера(вот только-только прочитал). Как организовать аппаратный контроль данных? А, вот ещё какая штука. Оказывается, строки $10 d , которые модем возвращал, это признак обнаружения сигнала КПВ(контроль посылки вызова). Видел несколько тем, люди справшивали, как определить, когда на удаленном конце сняли трубку. Ну вот видимо, таким способом можно. |
Сообщ.
#16
,
|
|
|
Цитата Prince @ Как организовать аппаратный контроль данных? Ты работаешь с Сом портом через TDCВ???Если да, то в DCB.Flags проверь биты установки режима HandShake для fDTRControl,FDsrSensitivity,fRTSControl.И обязательно должен быть включен fOutCTSFlow. Какие биты я не помню,но в нете по Flags полно инфы. Да кстати по поводу снятия трубки на другом конце. Года 2 назад я эту проблему решил путем подключения дополнительного девайса на МК51 к компу. Если интересно, могу поподробнее. |
Сообщ.
#17
,
|
|
|
Что такое TDCВ? Я пример приводил, как я с портом работаю.
|
Сообщ.
#18
,
|
|
|
Аппаратный контроль данных - работа с линиями RTS/CTS. Они включаются модемом или компом, когда их буфер приема заполнен полностью.
Есть еще DTR/DSR. Они устанавливаются когда приемный буфер заполнен на 3/4. (тоно насчет доли не уверен) Добавлено Это нужно в первую очередь для модема, иначе он может не успеть обработать твои данные и освободить буфер. Добавлено Цитата medved_68 @ Года 2 назад я эту проблему решил путем подключения дополнительного девайса на МК51 к компу. Если интересно, могу поподробнее. Интересно. Особенно схематика подключения к линии. |
Сообщ.
#19
,
|
|
|
Prince
Цитата Prince @ Что такое TDCВ? Я пример приводил, как я с портом работаю. Ты с портом работаешь через WriteFile, readFile. Это я понял. Но как ты его настраиваешь перед работой, после того как открыл CreateFile???? Откуда он у тебя знает с какой скоростью работать, какие таймауты и т.д. Поэтому я и спрашиваю: Цитата medved_68 @ Ты работаешь с Сом портом через TDCВ??? Цитата Prince @ Что такое TDCВ? Обволакивающий класс для структуры DCВ, в которой должны быть прописаны настройки компорта при его открытии. После открытия порта выполняется команда SetCommState (Handle,lpDCB)(за синтаксис не ручаюсь),которая настроит порт согласно тем данным, которые ты занес в структуру DCВ, а если в дельфях то TDCВ.Flags. И после этого только можно с ним работать. ![]() ![]() Testudo Цитата Testudo @ Интересно. Особенно схематика подключения к линии. Сегодня пороюсь в архивах.Там только был небольшой нюанс - вероятность определения 50-70%, а на блокированных линиях вообще грустно где то 10-20%, но у нас сейчас почти их не осталось, хотя кто его знает. Помню только, что сама линия заводилась на устройство через обычный диодный мост на КЦ407. Тогда меня порадовало одно-отсутствие ложных срабатываний, типа когда никто трубку не снял, а датчик сработал. И еще не сделал в свое время усреднение в зависимости от АТС к кому подключаешься, там несильно, но были различия во времени ответа станции. Но шел путем АОНа на ВМ80 + АОНа на Z80 это я точно помню. |
Сообщ.
#20
,
|
|
|
Цитата Аппаратный контроль данных - работа с линиями RTS/CTS. Они включаются модемом или компом, когда их буфер приема заполнен полностью. Есть еще DTR/DSR. Они устанавливаются когда приемный буфер заполнен на 3/4. (тоно насчет доли не уверен) А как именно с ними работать? Вот я отправляю какой-то буфер командой writefile. Как узнать, какой размер данных можно отправить за раз? И когда можно отправлять новую порцию данных? Добавлено Цитата После открытия порта выполняется команда SetCommState (Handle,lpDCB)(за синтаксис не ручаюсь),которая настроит порт согласно тем данным, которые ты занес в структуру DCВ, а если в дельфях то TDCВ.Flags. И после этого только можно с ним работать. Может у тебя все в норме в проге и просто порт не настроен, судя по твоему последнему письму??? А, понял. Да, через DCB. Ну я посмотрел вначале настройки через GetCommState, а что именно и как нужно настроить для передачи голосовых данных, не знаю. Работает - и работает. Хотя вот уже знаю, что должен быть включён аппаратный контроль данных. Буду пробовать. |
Сообщ.
#21
,
|
|
|
Цитата Prince @ А как именно с ними работать? Вот я отправляю какой-то буфер командой writefile. Как узнать, какой размер данных можно отправить за раз? И когда можно отправлять новую порцию данных? ты можешь отправить сразу хоть все данные только при работе в синхроне writefile тебе не вернет управление пока все не отправит. А если в этот момент случится авария на линии то все зависнет, причем наглухо. Я же тебе говорю: "переходи на асинхрон". Тогда структура Overlap тебе вернет количество реально переданных в линию байт, даже если случится внезапный Break. А момент когда можно отправить очередную порцию отслеживается наблюдением за событием EV_TXEMPTY (из буфера передачи послан последний символ). В это же время и произойдет установка события Overlap.Event, привязанного к записи. |
Сообщ.
#22
,
|
|
|
Если в синхроне, то отправлять данные модему желательно по одному байту, при этом проверяя сигнал CTS. Если он установлен - писать можно. Если нет - нужно подождать.
|
Сообщ.
#23
,
|
|
|
Testudo
Цитата Testudo @ Если в синхроне, то отправлять данные модему желательно по одному байту, при этом проверяя сигнал CTS Почему??? Если настроен аппаратный контроль, то драйвер сам будет приостанавливать передачу по сбросу CTS и ждать пока пока модем его выставит. |
Сообщ.
#24
,
|
|
|
Другими словами, нужно просто включить аппаратный контроль и забыть про этот самый контроль? Драйвер всё сделает сам? А мне остаётся только написать команду writefile и ждать, пока она не выполнится?
Цитата ты можешь отправить сразу хоть все данные только при работе в синхроне writefile тебе не вернет управление пока все не отправит. А если в этот момент случится авария на линии то все зависнет, причем наглухо. А можно ли избежать зависания, выставив таймауты? |
Сообщ.
#25
,
|
|
|
Цитата medved_68 @ За модем не отвечаю. Если настроен аппаратный контроль, то драйвер сам будет приостанавливать передачу по сбросу CTS и ждать пока пока модем его выставит. Я же сказал, что работал с самодельными устройствами. У них делал все как положено, но аппаратный контроль ничего не проперал. |
Сообщ.
#26
,
|
|
|
Цитата Prince @ Другими словами, нужно просто включить аппаратный контроль и забыть про этот самый контроль? Драйвер всё сделает сам? А мне остаётся только написать команду writefile и ждать, пока она не выполнится? Да,если ты правильно настроишь TDCB.Flags. Надо ожидать завершения writefile и анализировать сколько байт передано, хотя она все равно не вернет управление пока все заявленное не передаст,если не выставлен таймаут по времени записи. Но его надо устанавливать при каждой операции, если передаешь блоки разной длинны, или на время передачи самого длинного блока, тогда нужен анализ, сколько байт передано, если меньше чем нужно, то повторить writefile с передачей того что не допередал. Цитата Prince @ А можно ли избежать зависания, выставив таймауты? Именно для этого они и придуманы!!!! Testudo Цитата Testudo @ Я же сказал, что работал с самодельными устройствами. У них делал все как положено, но аппаратный контроль ничего не проперал. Значит неправильно настроил порт на аппаратный контроль. По умолчанию плевать он хотел на все управляющие сигналы. ![]() ![]() А по самопалу могу сказать, что я по прерыванию от порта на микроконтроллере сразу выставляю CTS, затем считываю байт из регистра приемника, обрабатываю его, и только потом снимаю CTS. Т.е. делаю как ты говорил, но только со стороны самопала, со стороны компа это все уже продумали за меня. |
Сообщ.
#27
,
|
|
|
Цитата medved_68 @ И плохо, что думать не хочешь. Значит неправильно настроил порт на аппаратный контроль. По умолчанию плевать он хотел на все управляющие сигналы. А по самопалу могу сказать, что я по прерыванию от порта на микроконтроллере сразу выставляю CTS, затем считываю байт из регистра приемника, обрабатываю его, и только потом снимаю CTS. Т.е. делаю как ты говорил, но только со стороны самопала, со стороны компа это все уже продумали за меня. |
Сообщ.
#28
,
|
|
|
Testudo
Цитата Testudo @ И плохо, что думать не хочешь. Изобретать велосипед конечно полезно, но зачем??? ![]() |
Сообщ.
#29
,
|
|
|
Цитата Да,если ты правильно настроишь TDCB.Flags А как правильно настроить? |
Сообщ.
#30
,
|
|
|
![]() ![]() А как правильно настроить? Просто обнули DCB.Flags и хлопни нужные маски Or. Файл в аттаче. ![]() Прикреплённый файл ![]() |
Сообщ.
#31
,
|
|
|
чё-то файл не скачивается
|
Сообщ.
#32
,
|
|
|
Цитата medved_68 @ Просто обнули DCB.Flags и хлопни нужные маски Or. flags dword fbinary: // режим проверки символа eof - включение данного режима windows // не поддерживает ( по крайней мере сейчас). Маска $01 dword fparity: //Контроль четности Маска $02 - включение контроля четности dword foutxctsflow: // Маска $04 - Включение контроля сигнала cts при выводе байтов. dword foutxdsrflow: // Маска $08 - Включение контроля сигнала dsr при выводе байтов. dword fdtrcontrol: // Маска $30 - Тип контроля сигнала dtr: значения dtr_control_disable деактивация сигнала. dtr_control_enable конкретное значение сигнала можно задавать через вызов escapecommfunction. dtr_control_handshake Автоматическое управление сигналом. dword fdsrsensitivity: // Маска $40 - Включение контроля сигнала dsr. dword ftxcontinueonxoff:1; // xoff continues tx dword foutx: // Маска $100. Включение режима работы по xon xoff при передаче dword finx: // Маска $200 -//- при приеме dword ferrorchar: // Маска $400. Разрешение замещения при ошибочном приеме // (несовпадение четности) принятого байта на член структуры errorchar. dword fnull: // Маска $800 enable null stripping - пропускать при приеме символы null dword frtscontrol: // Маска $3000. Тип контроля: rts_control_disable rts_control_enable rts_control_handshake Аналогично сигналу dtr rts_control_toggle - Высокий уровень пока, есть данные для передачи. dword fabortonerror // Маска $4000. Прекращение операций // чтения - записи при возникновении ошибок dword fdummy2:17; // Не используются Это все что он содержит, не знаю почему у тебя не качает ![]() ![]() Важные моменты: ![]() ![]() dword foutxctsflow: // Маска $04 - Включение контроля сигнала cts при выводе байтов. dword foutxdsrflow: // Маска $08 - Включение контроля сигнала dsr при выводе байтов. dword fdtrcontrol: // Маска $30 - Тип контроля сигнала dtr: значения dtr_control_handshake Автоматическое управление сигналом. dword frtscontrol: // Маска $3000. Тип контроля: rts_control_handshake Аналогично сигналу dtr dword fabortonerror // Маска $4000. Прекращение операций // чтения - записи при возникновении ошибок |