Версия для печати
Обмен информацией с модемом
http://www.delphikingdom.com/asp/viewitem.asp?catalogID=1030Евгений Дружинин
дата публикации 10-08-2004 14:20Обмен информацией с модемом Столкнувшись с необходимостью написания функции обмена данными с модемом, я был крайне удивлен практическим отсутствием информации по этому поводу. Мне было нужно организовать обмен данными с модемом так, как это происходит в "Свойствах Модема" на закладке "Диагностика" при нажатии на кнопку "Опросить модем". Порывшись в Интернете, подняв несколько раз этот вопрос на программистских форумах, я так и не нашел ответа на вопрос "как послать AT команду в модем и получить от него ответ". Стандартные отписки CreateFile, а потом WriteFile и ReadFile, ясности не вносили - модем все равно отказывался отвечать на команды. Пришлось вникнуть в особенности обмена данными с модемом и самому решить поставленную задачу.
Итак, исходные данные: модем подключен к порту COM3.
Сначала, как и описано во всех источниках, открываем COM порт, к которому подключен модем:hCommFile := CreateFile(PChar('\\.\COM3'), GENERIC_WRITE+GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);Далее, если hCommFile<> INVALID_HANDLE_VALUE, то считываем свойства COM порта функцией GetCommProperties(hCommFile,CommProp) и убеждаемся, что устройство, подключенное к порту COM3, действительно является модемом. Если CommProp.dwProvSubType = PST_MODEM, то к порту на самом деле подключен модем.
Теперь наступает первый ключевой момент, почти нигде не описанный. Надо установить размеры входного и выходного буферов, в которых будут размещаться данные, передаваемые в модем и принимаемые от него:
SetupComm(hCommFile,SizeOf(inBuffer),SizeOf(OutBuffer))Установив размеры буферов, считываем структуру DCB COM порта.GetCommState(hCommFile,DCB)В считанной структуре необходимо установить количество битов данных - 8. И, при желании, скорость COM порта (я задаю максимальное значение - 115200). Записываем новые значения:
SetCommState(hCommFile,DCB)Считываем информацию о таймаутах:GetCommTimeouts(hCommFile,CommTOuts)устанавливаем свои значения:CommTOuts.ReadIntervalTimeout:=1800; CommTOuts.ReadTotalTimeoutMultiplier:=30; CommTOuts.ReadTotalTimeoutConstant:=6000; CommTOuts.WriteTotalTimeoutMultiplier:=30; CommTOuts.WriteTotalTimeoutConstant:=6000;и записываем их:SetCommTimeouts(hCommFile,CommTOuts)Всё! COM порт полностью подготовлен к работе. А как же передавать команды модему и получать от него ответы? Оказывается достаточно просто!
Записываем команду в выходной буфер, не забыв завершить строку #13#10, и вызываем функцию:
WriteFile(hCommFile, OutBuffer, Length(PhoneCommand), NumberWritten, nil)Ну, пока всё так, как и пишется во всех форумах и статьях. Однако если теперь выполнить функцию ReadFile, то во входном буфере будет та же самая строка, что и в выходном буфере. Так что же делать? А вот здесь вторая и главная особенность описываемого мной метода общения с модемом. Этого я не нашел ни в каких источниках. После выполнения функции WriteFile нужно очистить буферы:
PurgeComm(hCommFile,PURGE_TXCLEAR + PURGE_RXCLEAR)И дальше читать:ReadFile(hCommFile,InBuffer,SizeOf(InBuffer),BytesRead,nil)Вот и всё. Описанным выше методом можно передавать модему АТ команды и смотреть, как он на них отвечает. Исходные коды примера и исполняемый файл находятся в прилагаемом архиве.
Евгений Дружинин.
Скачать проект: Modem.zip (206 K)
http://www.compexp.ru