Евгений Дружинин дата публикации 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)
Вот и всё. Описанным выше методом можно передавать модему АТ команды и смотреть, как он на них отвечает. Исходные коды примера и исполняемый файл находятся в прилагаемом архиве.
Евгений Дружинин.
http://www.compexp.ru
Скачать проект: Modem.zip (206 K)
[Работа с модемом] [COM-порт]
Обсуждение материала [ 22-02-2010 08:16 ] 23 сообщения |