Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Работа с COM-портом, алгоритм(+) 
:(
    Опции темы
takedo
Дата 29.12.2005, 08:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 501
Регистрация: 1.6.2005

Репутация: нет
Всего: 3



Бугемот
Цитата
Хм, тогда я не понимаю, откуда брать настройки (четность, биты и т.д.) - из мануала к модему?
Определя, что модем отвечает "_\r\n - начало кадра, а _\r\n_ _OK_ - конец" ты и определил настройки, такие как четность, стоповые биты. Вернее сказать, что ты удачно подобрал параметры Com порта, так как если они бы не совпадали с телефонными, ты би ничего не определил так точно. А Com порт настраивать надо тому, кто с ним работает. Ты со своего компьютера настраиваешь порт на компьютере, телефон - порт на телефоне.


--------------------
я не гольфист - я хоккеист
PM MAIL   Вверх
Dreamer_0x01
Дата 29.12.2005, 18:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Это ноутбук?


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Бугемот
Дата 30.12.2005, 06:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 27.12.2005

Репутация: 1
Всего: 1



Цитата(Dreamer_0x01 @ 29.12.2005, 18:36)
Это ноутбук?

Нет, обычный компьютер. Сотовый телефон подключен через USB-порт. COM-порт виртульаный. Формат вывода я определил терминальной программой - шлю AT-команду и смотрю ответ smile
PM MAIL   Вверх
Бугемот
Дата 1.1.2006, 09:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 27.12.2005

Репутация: 1
Всего: 1



Поздравляю всех с Новым Годом!
Год прошел, но вопросы остались smile
Цитата(Dreamer_0x01 @ 27.12.2005, 22:09)
Я бы поместил функцию чтения в отдельный поток, в котором все время считывал бы по несколько символов (например, по 128, зависит от скорости порта, если болшая и стабильная, то можно и поболее) с небольшим таймаутом, и считанные символы помещал бы в специальный буфер-очередь, который сдвигал бы по мере забора из него символов уже твоим рабочим потоком

Т.е. все же читать кусками, но выставить небольшой таймаут. Т.к. если, например, взял я буфер 128 байт, а пришло данных меньше - все равно функция чтения завершится по таймауту?

Цитата(takedo @ 29.12.2005, 08:14)
А Com порт настраивать надо тому, кто с ним работает. Ты со своего компьютера настраиваешь порт на компьютере, телефон - порт на телефоне.

Где можно взять настройки для COM-порта? Он у меня виртуальный smile Открыл device manager, посмотрел какие там настройки, корректно ли их будет выставить и в моей программе через SetCommState?
Ну и остался вопрос по таймаутам - где их взять? Нашел доку к модему на AT-команды, про таймауты там ни слова smile
PM MAIL   Вверх
Бугемот
Дата 1.1.2006, 11:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 27.12.2005

Репутация: 1
Всего: 1



Вот открываю порт:
Код

BOOL CMyCOMPort::OpenPort(LPCSTR strPortName)
{
    m_handlePort = CreateFile(strPortName, GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, 
            NULL, NULL);
    ClearPort();
    GetCommState(m_handlePort, &dcb);
    dcb.DCBlength = sizeof(dcb);
    dcb.StopBits = 1;
    dcb.BaudRate = 57600;
    dcb.Parity = 0;
    dcb.ByteSize = 8;
    SetCommState(m_handlePort, &dcb);

    GetCommTimeouts(m_handlePort, &ct);
    ct.ReadIntervalTimeout = MAXDWORD;
    SetCommTimeouts(m_handlePort, &ct);

    return m_handlePort != INVALID_HANDLE_VALUE;
}


Вот пытаюсь прочитать данные:
Код

void ReadData()
{
        CServCOMPort::Instance()->OpenPort("COM3");
        CString cscommand;
        cscommand = "ATE0V0Q1\r";
        DWORD dwlength = cscommand.GetLength(), dwwrite = 0;
        BOOL bresult = CServCOMPort::Instance()->WritePort(cscommand, dwlength, dwwrite);
        if(!bresult)
            return;

        cscommand = "ATI0\r"; //Информация о модеме
        dwlength = cscommand.GetLength();
        dwwrite = 0;
        bresult = CServCOMPort::Instance()->WritePort(cscommand, dwlength, dwwrite);
        if(!bresult)
            return;

        CServCOMPort::Instance()->ClearPort();
        DWORD dwread = 0;
        dwlength = 127;
        char cData[128];
        memset(cData, 0, sizeof(cData));
        bresult = CServCOMPort::Instance()->ReadPort(cData, dwlength, dwread);
        CString gg;
        gg.Format("Прочитано байт: %d\r\nДанные: %s", dwread, cData);
        AfxMessageBox(gg);
}

В результате программа виснет, т.е. по таймауту чтение не завершается smile
Если прочитать 5-10 байт, то читается последняя записанная в порт команда, хотя ATE0, ATQ1 - выполнил. В терминальной программе все нормально работает, у меня - нет.
Подскажите, пожалуйста, что не так?
PM MAIL   Вверх
JoyEx
Дата 1.1.2006, 12:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



Попробуй
ReadIntervalTimeout = MAXDWORD
ReadTotalTimeoutConstant = 0
ReadTotalTimeoutMultiplier = 0


--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Бугемот
Дата 1.1.2006, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 27.12.2005

Репутация: 1
Всего: 1



Цитата(JoyEx @ 1.1.2006, 12:29)
ReadTotalTimeoutConstant = 0
  ReadTotalTimeoutMultiplier = 0

Посмотрел в отладчике - значения 0.
Поставил вручную - ничего не изменилось smile
Как-то странно и непонятно все работает smile
В принципе, рассчитал значения:
На чтение 80 байт (хочу в такой буфер читать) при скорости 57600 б/с надо ~14мс. Межсимвольный интервал 0.0875мс
Пробовал выставить вручную - тот же эффет, программа виснет надолго smile
PM MAIL   Вверх
Бугемот
Дата 1.1.2006, 13:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 27.12.2005

Репутация: 1
Всего: 1



Если читать заведомо меньшее количество байт (меньше чем придет), то все читается. Если выставить буфер больше - виснет smile
Вроде и таймауты выставлены smile что еще делать, не пойму smile
Добавлено @ 13:16
Если читать заведомо меньшее количество байт (меньше чем придет), то все читается. Если выставить буфер больше - виснет smile
О! Виснет не намертво, но таймаут - минуты три smile
PM MAIL   Вверх
JoyEx
Дата 1.1.2006, 14:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



Тогда ReadIntervalTimeout ~= 0


--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Бугемот
Дата 1.1.2006, 15:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 27.12.2005

Репутация: 1
Всего: 1



Да, сделал:
Код

ct.ReadIntervalTimeout = 0;
ct.ReadTotalTimeoutMultiplier = 1;
ct.ReadTotalTimeoutConstant = 21;

и вроде нормально работает.
Большое спасибо! smile
Добавлено @ 15:12
Вот только иногда после открытия посылаю команду, а выбираю оттуда всякий мусор, хотя вроде
PurgeComm(m_handlePort, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT|PURGE_RXABORT);
Делаю.
PM MAIL   Вверх
JoyEx
Дата 1.1.2006, 15:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



А что PurgeComm() возвращает? Если FALSE, то тогда поможет GetLastError.



--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Бугемот
Дата 1.1.2006, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 27.12.2005

Репутация: 1
Всего: 1



GetLastError рекомендуется делать после любой операции с портом?
PM MAIL   Вверх
Бугемот
Дата 1.1.2006, 16:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 27.12.2005

Репутация: 1
Всего: 1



Так, с таймаутами разобрался.
Стандартный для большинства модемов AT-команды нормально проходят. Ответ получаю.
Но как только посылаю команду для своего модема (например, получить производителя), в ответ - пусто smile
PM MAIL   Вверх
JoyEx
Дата 1.1.2006, 20:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



Цитата
Но как только посылаю команду для своего модема (например, получить производителя), в ответ - пусто smile


У тебя OEM? smile

Новый Год к нам мчится, скоро всё случится, сбудется, что снится, что опять нас обманут - ничего не дадут...

- это про твой модем smile

C Новым 2006 Годом!


--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Dreamer_0x01
Дата 2.1.2006, 23:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



JoyEx

Да вы я тоже вижу фанатеете от текстов, произносимых Жуковым ;)

"Ты едешь туда, где закат такой малиновый, ты видел его дома лишь наполовину..." smile




Цитата
Т.е. все же читать кусками, но выставить небольшой таймаут. Т.к. если, например, взял я буфер 128 байт, а пришло данных меньше - все равно функция чтения завершится по таймауту?


Именно. Причем, как я уже говорил, лучше выставлять не междусимвольный таймаут, а общий.
Прочем, вижу, ты уже и сам это понял.

Цитата
GetLastError рекомендуется делать после любой операции с портом


Нет. Как правило, операции типа ReadFile, SetCommTimeOut. PurgeComm имеют какой-то возвращаемый результат, это либо BOOL, либо UINT,либо int, либо DWORD, ну либо там еще что-то. Так вот во всех инх в случае успеха возвращаются отличные от нуля значения, в случае неуспеха - 0.
То есть все подобные операции желательно заключать в следующие конструкции:

Код


if(Твоя_операция1(....))
{
//продолжаем работу
if(Твоя_операция2(....))
{
//продолжаем работу
//////
//..........
//и т.д.
}
else
{
int err=GetLastError(....);
//выдать сообщение об err;
return 0;//либо другой код ошибки для твоей функции
}

}
else
{
int err=GetLastError(....);
//выдать сообщение об err;
return 0;//либо другой код ошибки для твоей функции
}



В таком коде ты увидишь сообщение о возникающих ошибках, и программа будет работать правильно, не подвешивая систему и не предлагая отправить отчет в майкрософт ;)

Это сообщение отредактировал(а) Dreamer_0x01 - 2.1.2006, 23:40


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Страницы: (4) Все 1 [2] 3 4 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




[ Время генерации скрипта: 0.0694 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.