Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Работа с COM-портом.


Автор: AndreySol 7.8.2011, 17:42
Что я хочу знать для начала: открыть выбранный порт, настроить его, послать АТ-команду в него, получить ответ, отобразить ответ.
Нашел поиском много всякого, начал разбираться, понял что для открытия порта и чтения\записи в\из него используются ф-ции CreateFile, WriteFile, ReadFile. Для настройки открытого порта используются ф-ции описанные в разделе MSDN - Communications Functions.
А вот чего не нашел пока - это как получить список доступных в системе COM-портов, дабы иметь возможность выбрать требуемый. Вариант "просто список из номеров по порядку" не подходит, у меня к примеру в системе 1 физический порт COM1 и 12 виртуальных, появившихся после установки Bluetooth-контроллера, которым программа установки присвоила номера от COM30 до СОМ42. Подскажите.

Автор: ama_kid 7.8.2011, 17:56
HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM

Автор: gromo 7.8.2011, 23:15
Я так понимаю, СОМ-порт нужен для работы с модемом или телефоном?!
Опиши конкретно задачу, какие функции нужны?

Автор: Dem_max 8.8.2011, 06:23
http://forum.sources.ru/index.php?showtopic=337903

Автор: AndreySol 9.8.2011, 21:49
Использовал вариант с QueryDosDevice, спасибо Всем.

Новый вопрос есть.
На виртуальном COM-порту - моб.телефон.
Пробую, для начала, открыть порт и послать в него AT-команду. Пример кода взял из статьи "Serial Communications in Win32" с MSDN. Приводить здесь код ф-ции открытия и настройки порта не буду, там ошибок не должно быть.
Ф-ция записи в порт:
Код
bool WriteBufferToPort(HANDLE hPortToWrite, char *lpBuffToWrite, DWORD dwToWrite)
{
    bool bResult = false;
    DWORD temp, dwRes, dwWritten;
/*
//очистить принимающий буфер порта
PurgeComm(hPortToWrite, PURGE_RXCLEAR);
*/
    //создать событие
    ovlapWrite.hEvent = CreateEvent(NULL, true, true, NULL);

    // записать буфер в порт
    if(!WriteFile(hPortToWrite, lpBuffToWrite, dwToWrite, &temp, &ovlapWrite))
    {
        if(GetLastError() != ERROR_IO_PENDING)
        {    // WriteFile failed, but isn't delayed. Report error and abort.
            bResult = false;
        }
        else
        {    // Write is pending.
            dwRes = WaitForSingleObject(ovlapWrite.hEvent, INFINITE);
            switch(dwRes)
            {    // OVERLAPPED structure's event has been signaled.
                case WAIT_OBJECT_0:
                    if(!GetOverlappedResult(hPortToWrite, &ovlapWrite, &dwWritten, FALSE))
                    {
                        bResult = false;
                    }
                    else
                    {    // Write operation completed successfully.
                        CString str;
                        str.Format("%u",dwWritten);
                        MessageBox(NULL,"WAIT_OBJECT_0",str,0);

                        bResult = true;
                    }
                break;
                
                default:
                    // An error has occurred in WaitForSingleObject.
                    // This usually indicates a problem with the
                    // OVERLAPPED structure's event handle.
                    bResult = false;
                break;
            }
        }
    }
    else
    { // WriteFile completed immediately.
        bResult = true;
    }

    return bResult;
}

вызов ф-ции:
Код
char szToWrite[] = "atdl"; // по этой команде МТ должен набирать посл. исходящий номер
if(WriteBufferToPort(hTestPort, szToWrite, strlen(szToWrite)) == true)
{

}

В результате получается так - вижу что порт открывается (МТ пишет на экране "SPP профиль подключен"), но команда не выполняется. Закрытие порта то-же нормально отрабатывается (МТ пишет на экране "SPP профиль отключен"). Где-то у меня ошибка, помогите.

Автор: AndreySol 9.8.2011, 23:27
Нашел ошибку. Оказывается к AT-команде надо добавлять "\r".

Автор: AndreySol 27.8.2011, 14:00
На виртуальном COM-порту - моб.телефон.
Посылаю команду, к примеру "at+egmr=0,0", ответ получаю в таком виде:
Цитата

a

t

+

e

g

m

r=0,0 +EGMR: "MT6223, E05"

OK

А HyperTerminal возвращает как положено, только
Цитата

+EGMR: "MT6223, E05"
OK

Уже и PurgeComm везде понаставил и пробовал порт открывать в синхронном и в асинхронном режиме - результат тот-же. В чем проблема может быть ?

Автор: AndreySol 27.8.2011, 15:32
Разобрался, был включен режим "Эхо", помогло ATE0 - и все стало приходить как надо.  

Автор: AndreySol 28.8.2011, 17:06
Посылаю команду AT+CPBR=2.
В своей программе ответ сохраняю в переменную типа CString, затем вывожу на RichEdit. Получается так
+CPBR: 2, "09xxxx6453", 129, ""
в последних кавычках должно быть имя абонента русскими буквами, с английским текстом все ОК. Проверял стандартным виндовым HyperTerminal'ом - в нем то-же "".
Подскажите, что можно сделать ?

P.S. смотрел команду +CSCS, но не очень понял что там за кодировки, кроме "PCCP437".

Автор: bass 1.9.2011, 14:38
так создай мемо и туда побайтно выводи что приходит от телефона..... Либо телефон не чего не выдает либо софтина некорректно воспринимает (твоя).... 

Автор: AndreySol 3.9.2011, 13:32
Цитата

либо софтина некорректно воспринимает (твоя)....  

дак я не спорю. Вы подскажите, как корректно принять ?

Автор: Dem_max 4.9.2011, 05:53
не вижу функции приема данных

Автор: AndreySol 4.9.2011, 12:46
Цитата

не вижу функции приема данных 

Вы это имели ввиду ?
Код

#define BUFFSIZE 1024
unsigned char buffRead[BUFFSIZE];
...........

ReadFile(hCurrPort, buffRead, dwInQue, &temp, &ovlapRead);
CString strPrint = _T("");
strPrint.Format(_T("%s"), buffRead);

...........

m_Rich.SetWindowText(strPrint);

Автор: Dem_max 4.9.2011, 18:42
Ну наверное тебе лучше знать как ты данные пытаешься принять.

Автор: GremlinProg 5.9.2011, 06:15
Цитата(AndreySol @  4.9.2011,  14:46 Найти цитируемый пост)

Вы это имели ввиду ?
Код

#define BUFFSIZE 1024
unsigned char buffRead[BUFFSIZE];
...........

ReadFile(hCurrPort, buffRead, dwInQue, &temp, &ovlapRead);
CString strPrint = _T("");
strPrint.Format(_T("%s"), buffRead);

...........

m_Rich.SetWindowText(strPrint);


есть 3 варианта:
1. смотреть надо на результат, возвращаемый функцией ReadFile, только при значении TRUE buffRead будет содержать что-то вменяемое
2. hCurrPort открыт в режиме оверлаппед? тогда см. пункт 1., в таком случае чтение не обязано завершиться немедленно, т.е. нужен во первых, динамический (или статический) буфер, а во вторых - реализация какого-либо ожидания завершения операции чтения, в котором этот буфер можно использовать
3. если поставить на 6-й стоке брейкпойнт и посмотреть на содержимое buffRead, то если buffRead будет содержать данные, а на 8-й strPrint - уже нет, значит проблема в кодировке (ее нужно локализовать для России)

Автор: AndreySol 11.9.2011, 16:09
Цитата

то если buffRead будет содержать данные, а на 8-й strPrint - уже нет, значит проблема в кодировке (ее нужно локализовать для России)

так оно и есть, вот только как локализовать ?
У моего китайца список кодировок: "IRA", "GSM", "HEX", "PCCP437", "8859-1", "UCS2", "UCS2_0X81". 
Насчет "PCCP437" понятно сразу, об остальных ничего не понял - пытался читать описания в стандартах, но увы...
Может подскажете чего ?

Автор: xvr 11.9.2011, 19:46
Цитата(AndreySol @  11.9.2011,  16:09 Найти цитируемый пост)
У моего китайца список кодировок: "IRA", "GSM", "HEX", "PCCP437", "8859-1", "UCS2", "UCS2_0X81". 

IMHO UCS2 - это Unicode (16ти битовый). Попробуй его включить.

Автор: GremlinProg 12.9.2011, 06:13
Цитата(AndreySol @  11.9.2011,  18:09 Найти цитируемый пост)
так оно и есть, вот только как локализовать ?

можно для начала так:
Код

setlocale(LC_ALL, ".1251");

или
Код

setlocale(LC_ALL, ".866")

или
Код

setlocale( LC_ALL, ".OCP" );

т.е. выполнить эту команду вначале программы, либо где-нить перед 7-й строкой,
не получится - подбирать еще и правильную кодировку в железе, например, как советует xvr

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)