Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Повтороное открытие COM-порта 
:(
    Опции темы
programmaker
Дата 25.3.2010, 17:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Есть задача и я никак не могу ее решить.
исходные данные:
Есть один ком порт. К нему подключен ЖПС модем.
Есть удаленное устройство. К непу подключен такой же модем.
Задача с моим алгоритмом решения:
1. Открываем порт
2. Пишем в него команду соединения модемов
3. Ждем пока модем ответит "коннект"
4. Закрываем порт
5. Открываем его же, но с другими параметрами
6. Программа работает в штатном режиме
(до появления модемов все работало отлично - при прямом подключении компа и девайса).
вот код (сверху вниз)
а) Поток в котором происходит анализ работы порта до соединения модемов
Код

bool connectedd = false;
bool modCr = false;
bool modWr = false;

/////////////////////////////////////////////////////////////////////
//поток для работы порта (коннект, чтение, запись, инит КПпорт)
/////////////////////////////////////////////////////////////////////

UINT ComThread(LPVOID param)
{
    CCommModemDevice::CCommModemDevice* mod = (CCommModemDevice::CCommModemDevice*)param;

    char sReceivedChar[128];
    DWORD err = NULL;
    DWORD dwnumber_to_read_bytes = 200;
    DWORD dwnumber_read_bytes = 1;
    int itotal_read_bytes = 0;
    
    while (true)//(dwnumber_read_bytes!=20)
    {
        if (!connectedd)
        {
            if (!modCr)
                mod->Connect();
            if (!modWr)
                mod->WriteModem();
        }
        else
        {
            mod->CloseModem();
            Sleep (1000);
            mod->CreateDevice();
            return connectedd;
        }
        if (modWr)
        {
            ReadFile(mod->m_hModCom,&sReceivedChar,dwnumber_to_read_bytes,&dwnumber_read_bytes,0);
            if (dwnumber_read_bytes == 20) //connectedd
                {
                    MessageBox (NULL, "CON", NULL, NULL);
                    connectedd = true;
                }
        }
    }
    
    return    connectedd;
}




б)инит 
Код

void CCommModemDevice::InitDevice() 
{
    if(!m_Flags_State.test(STOP))return;
    {
        char n_port[16];    // для ASCII номера портаLPCTSTR(str1+str2)
        static    CString    str1="\\\\.\\COM";
        CString str2=_itoa(m_N_Port,n_port,10);
        strr = str1+str2;
        m_hComm = INVALID_HANDLE_VALUE;
        m_hModCom = INVALID_HANDLE_VALUE;
        AfxBeginThread(ComThread,this);
    }
}


в)работа порта в режиме "пока соединение не установлено"
Код

void CCommModemDevice::Connect()
{
//    TerminateThread(ComThread, NULL);
    m_hModCom=CreateFile(
            LPCTSTR(strr), 
                GENERIC_READ | GENERIC_WRITE,
            0, // экслюзивно занимаем порт
            NULL, // no security
            OPEN_EXISTING,
            0, // no overlapped I/O
            NULL); // null template

    if (m_hModCom == INVALID_HANDLE_VALUE)
        AfxMessageBox ((LPCTSTR)"Error opening port");
    else
    {
        AfxMessageBox ((LPCTSTR)"Port successfully opened");
        GetCommState (m_hModCom, &m_dcbb);                // Считываем существующий DCB
        BuildCommDCB(LPCTSTR(m_Descript),&m_dcbb); // Считываем строку типа 96,т,8,2

        m_dcbb.fOutxCtsFlow=FALSE; 
        m_dcbb.fOutxDsrFlow=FALSE; 
        m_dcbb.fDtrControl = DTR_CONTROL_DISABLE ;
        m_dcbb.fRtsControl = RTS_CONTROL_DISABLE;

            SetCommState (m_hModCom, &m_dcbb);                // Инициируем Comm с новым DCB
            
            if (!(GetCommTimeouts(m_hModCom, &m_CommTimeOutss)))
                AfxMessageBox ((LPCTSTR)"Port not timeouts taken");
        
            m_CommTimeOutss.ReadIntervalTimeout = 0;
            m_CommTimeOutss.ReadTotalTimeoutMultiplier = 0;
            m_CommTimeOutss.ReadTotalTimeoutConstant = 70;
            m_CommTimeOutss.WriteTotalTimeoutMultiplier = 10;
            m_CommTimeOutss.WriteTotalTimeoutConstant = 100;

            if (!(SetCommTimeouts(m_hModCom, &m_CommTimeOutss)))
                AfxMessageBox ((LPCTSTR)"Port timeouts not configured");
            modCr = true;
            WriteModem();
    
    }
}

void CCommModemDevice::WriteModem()
{
    char sReceivedChar[128];
    DWORD err = NULL;
    DWORD dwnumber_to_read_bytes = 200;
    DWORD dwnumber_read_bytes = 1;
    int itotal_read_bytes = 0;

        DWORD iSize;
        char q =toascii(13);
        char* TXbuff = new TCHAR;
        sprintf(TXbuff, "%s", "atd 89151711565");

        if (WriteFile(m_hModCom, TXbuff, strlen(TXbuff), &iSize,0) && WriteFile(m_hModCom, &q, strlen(&q), &iSize,0))
        {
            modWr = true;
        
        while (!connectedd)
        {
            ReadFile(m_hModCom,&sReceivedChar,dwnumber_to_read_bytes,&dwnumber_read_bytes,0);
            if (dwnumber_read_bytes == 20) //connectedd
                {
                    MessageBox (NULL, "CON", NULL, NULL);
                    //CloseModem();
                    connectedd = true;
                }
        }
        }
}

void CCommModemDevice::CloseModem()
{
    PurgeComm(m_hModCom,PURGE_TXCLEAR|PURGE_RXCLEAR|
PURGE_TXABORT|PURGE_RXABORT);
    CloseHandle(m_hModCom);
//    CreateDevice();
}



г) новое открытие порта с новыми параметрами
Код

void CCommModemDevice::CreateDevice() 
{
    TerminateThread(ComThread, NULL);
    m_hComm=CreateFile(
                LPCTSTR(strr), 
                GENERIC_READ | GENERIC_WRITE,
                0,                    // exclusive access
                NULL,                 // no security attrs
                OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // overlapped I/O
                NULL );
    if (m_hComm == INVALID_HANDLE_VALUE)
    {
// Вывести диагностику
        m_hComm = NULL;
    }
    else
    {
        GetCommState (m_hComm, &m_dcbb);                // Считываем существующий DCB
        BuildCommDCB(LPCTSTR(m_Descript),&m_dcbb); // Считываем строку типа 96,т,8,2

        m_dcbb.fOutxCtsFlow=FALSE; 
        m_dcbb.fOutxDsrFlow=FALSE; 
        m_dcbb.fDtrControl = DTR_CONTROL_DISABLE ;
        m_dcbb.fRtsControl = /*RTS_CONTROL_TOGGLE;*/RTS_CONTROL_DISABLE;
/*
#ifdef  SYSTEL_RS485
        m_dcbb.fDtrControl = DTR_CONTROL_DISABLE ;
#endif
*/
        SetCommState (m_hComm, &m_dcbb);                // Инициируем Comm с новым DCB
        PurgeComm( m_hComm, 
                   PURGE_TXABORT | PURGE_RXABORT |
                   PURGE_TXCLEAR | PURGE_RXCLEAR );
      // set up for overlapped I/O
        GetCommTimeouts(m_hComm, &m_CommTimeOutss );

        m_CommTimeOutss.ReadIntervalTimeout            = 0;
        m_CommTimeOutss.ReadTotalTimeoutMultiplier    = 0;
        m_CommTimeOutss.ReadTotalTimeoutConstant        = 0;
        m_CommTimeOutss.WriteTotalTimeoutMultiplier    = 0;
        m_CommTimeOutss.WriteTotalTimeoutConstant    = 0;

        SetCommTimeouts( m_hComm, &m_CommTimeOutss ); 
    }
    // Создание событий для СОМ порта
 // create I/O event used for overlapped reads / writes
    if ( m_hEvent_Handles[ON_READ_DEVICE_EVENT] && m_hEvent_Handles[ON_WRITE_DEVICE_EVENT])
    {
        m_osRead.hEvent = m_hEvent_Handles[ON_READ_DEVICE_EVENT];//.h_on_read
        m_osWrite.hEvent = m_hEvent_Handles[ON_WRITE_DEVICE_EVENT];//.h_on_write
    }
    else
    {
        AfxMessageBox("Cannot create device events!");    
    }
}




если я избавляюсь от потока, то все работает, но программа висит до установления коннекта, а это недопустимо
в той последовательности, которая поисана выше (код) при закрытии порта и новом открытии хендл открытого порта меняется
я так понимаю, что проблемма именно в этом, но как ни бьюсь - не выходит у меня каменный цветок.
подскажите что я не так делаю
ато надоело оправдываться и говорить, что вот вот все будет готово
PM MAIL   Вверх
xvr
Дата 26.3.2010, 12:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Хэндл конечно меняется, но непонятно, почему это должно мешать?
Еще непонятно зачем надо переоткрывать порт? Если только для включения OVERLAPPED режима, то это лишнее - можно его включить сразу.
И самое главное, непонятно что именно не работает?

PM MAIL   Вверх
programmaker
Дата 26.3.2010, 15:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(xvr @ 26.3.2010,  12:11)
Хэндл конечно меняется, но непонятно, почему это должно мешать?
Еще непонятно зачем надо переоткрывать порт? Если только для включения OVERLAPPED режима, то это лишнее - можно его включить сразу.
И самое главное, непонятно что именно не работает?

именно для включения оверлапед режима.
я делаю:
1. открытие порта
2. запись в порт (atd*******)
3. чтение из порта пока не прийдет ответ о подключении
4. закрытие порта
5. открытие порта в штатном режиме (с оверлаппедом)
если в потоке - не срабатывает ивент на чтение-запись
если без потока, то срабатывает
как поток на это повлиял?
PM MAIL   Вверх
xvr
Дата 26.3.2010, 15:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(programmaker @ 26.3.2010,  15:30)
именно для включения оверлапед режима.

Включите OVERLAPPED сразу, и не надо ничего переоткрывать

Цитата

если в потоке - не срабатывает ивент на чтение-запись
если без потока, то срабатывает
как поток на это повлиял?
Сложно сказать - код чтения вы не привели

PM MAIL   Вверх
programmaker
Дата 26.3.2010, 16:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Вот полный код именно этого девайса.
(без модемов)

Добавлено через 6 минут и 54 секунды
С этим кодом при прямом подключении девайса к компу обмен идет автоматически (там в ядре программы черт ногу сломит, но работает).
Если добавляю модемную часть без потока - тоже идет, но программа висит до коннекта модемов. Если добавляю модемную часть в потоке - не идет обмен между девайсом и компом (открытый второй раз порт не реагирует на ивенты).
Если пытаюсь просто открыть порт и записать в него что-то - выдает ошибку (какую уже и не помню).
Слишком долго я с этим бьюсь.

Присоединённый файл ( Кол-во скачиваний: 7 )
Присоединённый файл  DevComm.cpp 6,87 Kb
PM MAIL   Вверх
xvr
Дата 26.3.2010, 19:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



В сорце не нашел собственно ожидания на m_osRead.hEvent, где то оно спрятанно. Вот видимо там и отвалилось

И еще - если на момент вызова ReadFile в буфере будут данные, то они могут быть немедленно возвращены из ReadFile'а, и евент вообще не взведется. Так что вот тут -
Код

        if ( ReadFile( m_hCom, m_ReadBuf, m_ByteToRead, &m_dwNumberRead, &m_osRead ) == NULL)
        {
            DWORD dw=GetLastError();//Вставить IO_PENDING!!!
            dw=dw;
            return;        
        } 
надо анализировать код возврата, может вернуться не только с ошибкой, а если ошибка - то не только IO_PENDING!

Добавлено через 1 минуту и 31 секунду
Кстати, обнулять timeout'ы тоже не стоит - будет немедленно возвращаться с пустым буфером

PM MAIL   Вверх
programmaker
Дата 29.3.2010, 11:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



как поток мог повлиять на работу с портом?
без потока ведь все работает...
PM MAIL   Вверх
xvr
Дата 29.3.2010, 11:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(programmaker @ 29.3.2010,  11:11)
как поток мог повлиять на работу с портом?

Введением дополнительной задержки перед ReadFile (на время создания потока и его запуск). От порта уже успело что то придти, и ReadFile завершился немедленно (и успешно). На что ваша программа не расчитанна
Цитата

без потока ведь все работает...
Повезло  smile 
PM MAIL   Вверх
programmaker
Дата 29.3.2010, 12:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(xvr @ 29.3.2010,  11:58)
Цитата(programmaker @ 29.3.2010,  11:11)
как поток мог повлиять на работу с портом?

Введением дополнительной задержки перед ReadFile (на время создания потока и его запуск). От порта уже успело что то придти, и ReadFile завершился немедленно (и успешно). На что ваша программа не расчитанна
Цитата

без потока ведь все работает...
Повезло  smile

Перед ReadFile от порта ничего не приходит. К порту подключен модем, который первый ответ дает секунд через 7-10 после WriteFile.
После ReadFile порт закрывается и открывается заново с OVERLAPPED режимом.
PM MAIL   Вверх
xvr
Дата 29.3.2010, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(programmaker @  29.3.2010,  12:02 Найти цитируемый пост)
Перед ReadFile от порта ничего не приходит. К порту подключен модем, который первый ответ дает секунд через 7-10 после WriteFile.
После ReadFile порт закрывается и открывается заново с OVERLAPPED режимом. 
Бесы!  smile 
Попробуй все же проверять, что возвращает ReadFile. Других дыр пока не вижу  smile 

PM MAIL   Вверх
programmaker
Дата 29.3.2010, 15:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(xvr @ 26.3.2010,  19:04)
Код

        if ( ReadFile( m_hCom, m_ReadBuf, m_ByteToRead, &m_dwNumberRead, &m_osRead ) == NULL)
        {
            DWORD dw=GetLastError();//Вставить IO_PENDING!!!
            dw=dw;
            return;        
        } 

dw= 1, что означает "Неверная функция"
как это может быть и что с этим сделать надо?
PM MAIL   Вверх
xvr
Дата 29.3.2010, 16:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(programmaker @  29.3.2010,  15:51 Найти цитируемый пост)
dw= 1, что означает "Неверная функция"
О как!   smile  Проверь передаваемые в ReadFile параметры, в частности валидны ли буфера для чтения и правильно ли заполнен m_osRead (в отладчике)


PM MAIL   Вверх
programmaker
Дата 29.3.2010, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



извиняюсь за грубость, но В РОТ МНЕ НОГИ!!!
изменил инит девайс на 
Код

void CCommModemDevice::InitDevice() 
{
    if(!m_Flags_State.test(STOP))return;
    {
        char n_port[16];    // для ASCII номера портаLPCTSTR(str1+str2)
        static    CString    str1="\\\\.\\COM";
        CString str2=_itoa(m_N_Port,n_port,10);
        strr = str1+str2;
        m_hCom = INVALID_HANDLE_VALUE;
        m_hModCom = INVALID_HANDLE_VALUE;
        DWORD er=GetLastError();
//        CreateDevice();    // Создание самого СОМ порта
//        m_Flags_State.set(WORK);
//        m_Flags_State.reset(STOP);
        CWinThread* MyThread=  AfxBeginThread(ComThread,this);
//        Sleep(1000);
        DWORD rezzz=WaitForSingleObject(MyThread->m_hThread, 30000);
        er=GetLastError();
        if(rezzz == WAIT_OBJECT_0){
          CreateDevice(); //и ниипет
        }

//        Connect();
//        RasHangUp();
    }
}


и все заработало

но 
Код

WaitForSingleObject(MyThread->m_hThread, 30000);


вешает программу до появления события.
можно ли как-нибудь от этого избавиться?
PM MAIL   Вверх
xvr
Дата 29.3.2010, 16:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(programmaker @  29.3.2010,  16:32 Найти цитируемый пост)
можно ли как-нибудь от этого избавиться? 
Угу, убрать WaitFor...  smile Он по сути превращает multithread программу в обычную, однопоточную.
Так что это все проблемы с синхронизацией потоков (похоже)


PM MAIL   Вверх
programmaker
Дата 29.3.2010, 17:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(xvr @ 29.3.2010,  16:50)
Цитата(programmaker @  29.3.2010,  16:32 Найти цитируемый пост)
можно ли как-нибудь от этого избавиться? 
Угу, убрать WaitFor...  smile Он по сути превращает multithread программу в обычную, однопоточную.
Так что это все проблемы с синхронизацией потоков (похоже)

А если я избавлюсь от wait..., то как мне отследить приход по readfile?
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




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


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

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