Модераторы: Daevaorn
  

Поиск:

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


Опытный
**


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

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



Всем привет.

Тут такая тема. Надо мне получить список рабочих COM-портов. Для этого я написал прогу на Qt. На морде компонент (виджет) для вывода списка строк (listWidget) и кнопка, обработчик которой приводится под заголовком on_pushButton_2_clicked(). Вот сей не хитрый текст:


Код

bool COMportIsPresent(char portName[10])
{
    HANDLE hPort = CreateFileA(portName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
    return (hPort != INVALID_HANDLE_VALUE);
}


void ComGetList::on_pushButton_2_clicked()
{
    char sPort[10];
    sscanf("COM2", "%s", sPort); if (COMportIsPresent(sPort)) ui.listWidget->addItem("COM2");
    sscanf("COM1", "%s", sPort); if (COMportIsPresent(sPort)) ui.listWidget->addItem("COM1");
    sscanf("COM3", "%s", sPort); if (COMportIsPresent(sPort)) ui.listWidget->addItem("COM3");
    sscanf("COM4", "%s", sPort); if (COMportIsPresent(sPort)) ui.listWidget->addItem("COM4");
    sscanf("COM5", "%s", sPort); if (COMportIsPresent(sPort)) ui.listWidget->addItem("COM5");
    sscanf("COM6", "%s", sPort); if (COMportIsPresent(sPort)) ui.listWidget->addItem("COM6");
    sscanf("COM7", "%s", sPort); if (COMportIsPresent(sPort)) ui.listWidget->addItem("COM7");
    sscanf("COM8", "%s", sPort); if (COMportIsPresent(sPort)) ui.listWidget->addItem("COM8");
    sscanf("COM9", "%s", sPort); if (COMportIsPresent(sPort)) ui.listWidget->addItem("COM9");
    sscanf("COM10", "%s", sPort); if (COMportIsPresent(sPort)) ui.listWidget->addItem("COM10");

}


Вот. В моём случае я получаю следующий список:
COM1
COM5
COM6
COM7
COM8
COM9

А, например, дельфовый компонент по работе с COM-портами в диалоге настройки параметров предлагает вот такой список:
COM1
COM2
COM5
COM6
COM7
COM8
COM9
COM10

В диспетчере устройств выводятся только первый и второй (если я правильно смотрю). Ну и буквально на днях я точно работал с первым и вторым, а так же с пятым и шесты (два последних - виртуальные).

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

Это сообщение отредактировал(а) EKoshelev - 3.12.2012, 13:28


--------------------
Вежливым и адекватным предлагаю общаться на "ты".
PM MAIL   Вверх
xvr
Дата 3.12.2012, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Жуть  smile 

Откройте для себя циклы (в С), а так же содержимое ветки 
HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM в реестре.

Кроме того - открыть COM10 как "COM10" не получится -  все порты больше 9 должны открываться как \\.\COM10 (для 10го)

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


Опытный
**


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

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



Цитата

Откройте для себя циклы


"Мы не ищем легких путей" (цэ)

Может тогда дашь ссылочку, где написано как реестр читать. А то мне гуглить лень.


--------------------
Вежливым и адекватным предлагаю общаться на "ты".
PM MAIL   Вверх
xvr
Дата 3.12.2012, 14:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(EKoshelev @  3.12.2012,  14:00 Найти цитируемый пост)
Может тогда дашь ссылочку, где написано как реестр читать. А то мне гуглить лень. 

Тут нужен не Гугл а MSDN  smile 
RegOpenKeyEx
RegEnumValue
RegCloseKey

http://msdn.microsoft.com/en-us/library/wi...6(v=vs.85).aspx
 

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


Эксперт
****


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

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



PM   Вверх
1oid
Дата 3.12.2012, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Лови. Алаптировано к использованию с wxWidgets.
Думаю не маленький, на STL (например) сам перетащишь  smile 

Код

#include <windows.h>
#include "dataio_com.h"
#include <iostream>
//#include <Winspool.h>

DataIO_Com::DataIO_Com()
{
    this->state     = false;
    ComBaudRate     = 115200;   // Скорость
    ComByteSize     = 8;        // Бит в байте: 4-8
    ComParity       = 0;        // 0-4=no,odd,even,mark,space
    ComStopBits     = 0;        // 0,1,2 = 1, 1.5, 2
    ComStreamCtrl   = 0;        // 0,1 = NONE, CTS/RTS
}


DataIO_Com::~DataIO_Com()
{
    this->Close();
}


bool DataIO_Com::Open( int port, int baud )
{
    DCB dcb;
    char COM_string[20];
    sprintf( COM_string,"\\\\.\\COM%d", port );

    m_hFile = CreateFile( COM_string,
                          GENERIC_READ | GENERIC_WRITE,
                          0,
                          NULL,
                          OPEN_EXISTING,
                          FILE_ATTRIBUTE_NORMAL,
                          NULL );

    if( m_hFile == INVALID_HANDLE_VALUE )
        return false;

    GetCommState( m_hFile, &dcb );

    COMMTIMEOUTS CommTimeOuts;
    //CommTimeOuts.ReadIntervalTimeout         = MAXDWORD;
    CommTimeOuts.ReadIntervalTimeout         = 0;
    CommTimeOuts.ReadTotalTimeoutMultiplier  = 0;
    CommTimeOuts.ReadTotalTimeoutConstant    = 200;
    CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
    CommTimeOuts.WriteTotalTimeoutConstant   = 0;



    SetCommTimeouts( m_hFile, &CommTimeOuts );

    /*
     * Boilerplate.
     */
    dcb.fBinary = TRUE;
    dcb.fDtrControl = DTR_CONTROL_ENABLE;
    dcb.fDsrSensitivity = FALSE;
    dcb.fTXContinueOnXoff = FALSE;
    dcb.fOutX = FALSE;
    dcb.fInX = FALSE;
    dcb.fErrorChar = FALSE;
    dcb.fNull = FALSE;
    dcb.fRtsControl = RTS_CONTROL_ENABLE;
    dcb.fAbortOnError = FALSE;
    dcb.fOutxCtsFlow = FALSE;
    dcb.fOutxDsrFlow = FALSE;

    dcb.fOutX = FALSE;

    dcb.ByteSize = 8;
    dcb.Parity   = NOPARITY;
    dcb.StopBits = ONESTOPBIT;
    dcb.BaudRate = baud;

    //dcb.fDtrControl = DTR_CONTROL_ENABLE;
    //dcb.fRtsControl = RTS_CONTROL_ENABLE;

    //dcb.fBinary = TRUE;
    dcb.DCBlength = sizeof( DCB );

    SetCommState( m_hFile, &dcb );

    this->state = true;
    return true;
}


void DataIO_Com::Close()
{
    this->state = false;
    CloseHandle( m_hFile );
}


void DataIO_Com::Clean()
{
    if( !state )
        return;

    PurgeComm( m_hFile, PURGE_TXCLEAR | PURGE_RXCLEAR );
}


int DataIO_Com::Send( char* buff, int szBuff )
{
    if( !state )
        return 0;

    if( buff == NULL || szBuff <= 0)
        return 0;

    DWORD lpdwBytesWrittens = 0;
    WriteFile( m_hFile, buff, szBuff, &lpdwBytesWrittens, NULL );

    return lpdwBytesWrittens;
}


int DataIO_Com::Recv( char* buff, int szBuff )
{
    if( !state )
        return 0;

    if( ( buff == NULL ) || ( szBuff <= 0 ) )
        return 0;

    DWORD dwBytesRead = 0;
    ReadFile( m_hFile, buff, szBuff, &dwBytesRead, NULL );

    return dwBytesRead;
}


void DataIO_Com::SetLine( OUT_LINES_NAME ln, bool state )
{
    unsigned char value = 0;

    if( !state )
        return ;

    if( ln == DTR )
        {
        if( state )
            value = 6;
        else
            value = 5;
        }

    if( ln == RTS )
        {
        if( state )
            value = 4;
        else
            value = 3;
        }

    EscapeCommFunction( m_hFile, value );
}


bool DataIO_Com::GetLine( IN_LINES_NAME ln )
{
    if( !state  )
        return 0;

    unsigned long ul = 0;

    GetCommModemStatus( m_hFile, &ul );

    if( ul == 0x10 && ln == CTS )
    {
        return true;
    }

    if( ul == 0x20 && ln == DSR )
    {
        return true;
    }

    if( ul == 0x40 && ln == RING )
    {
        return true;
    }

    if( ul == 0x80 && ln == RLSD )
    {
        return true;
    }

    return false;
}


void DataIO_Com::GetPortList( wxArrayString *port_list )
{
    int             i, j, k, l, n;
    int             nLen;
    long            li;
    OSVERSIONINFO   osvi;
    wxString        s, ws;
    wxArrayString   port_l;

    port_list->Clear();
    port_l.Clear();

    osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
    BOOL bGetVer = GetVersionEx( &osvi );

    // В какой системе работаем? ( Только Nt, Xp, Vista, Win7 )
    // используем API QueryDosDevice
    if( bGetVer && ( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT ) )
    {
        // Используем QueryDosDevice для просмотра всех устройств похожих на COMx.
        // Это наилучшее решение, так как порты не требуется открывать
        TCHAR szDevices[65535];
        DWORD dwChars = QueryDosDevice( NULL, szDevices, 65535 );
        if( dwChars )
        {
            i = 0;
            for ( ;; )
            {
                // Получаем текущее имя устройства
                TCHAR* pszCurrentDevice = &szDevices[i];

                // Если похоже на "COMX" добавляем в список
                nLen = _tcslen( pszCurrentDevice );

                s = pszCurrentDevice;
                ws = s.Mid( 0, 3 ); // первые 3 символа
                if( ( ws.Upper() == "COM" ) && ( s.Length() < 7 ) )
                    port_l.Add( s );

                // Переходим к следующему символу терминатору
                while( szDevices[i] != wxT( '\0' ) )
                    i++;

                // Перескакиваем на следующую строку
                i++;

                // Список завершается двойным симмволом терминатором, так что если символ
                // NULL, мы дошли до конца
                if( szDevices[i] == wxT( '\0' ) )
                    break;
            }
        }
    }

    // Отсортируем список портов
    n = port_l.Count();
    for( i = 0; i < n - 1; i++ )
        for( j = i + 1; j < n; j++ )
        {
            s = port_l[i].Mid( 3 );
            s.ToLong( &li );
            k = li;
            s = port_l[j].Mid( 3 );
            s.ToLong( &li );
            l = li;
            if( l < k )
            {
                s = port_l[j];
                port_l[j] = port_l[i];
                port_l[i] = s;
            }
        }
    for( i = 0; i < n; i++ )
        port_list->Add( port_l[i] );
}


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


Опытный
**


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

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



xvr, Чё-то я так и не смог заставить работать эти функции.


1oid, С твоей долбаниной разбираться не хотелось, но в результате именно из неё я и сделал всё, что мне нужно


bsa, До твоего предложения руки так и не дошли. Хотя я с помощью четвертой версии QtSerialPort'а работаю сейчас с COM портами (отправка и приём).

Короче, всем спасибо.


--------------------
Вежливым и адекватным предлагаю общаться на "ты".
PM MAIL   Вверх
bsa
Дата 6.12.2012, 01:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(EKoshelev @  5.12.2012,  16:32 Найти цитируемый пост)
Хотя я с помощью четвертой версии QtSerialPort'а работаю сейчас с COM портами (отправка и приём).

ты о чем? QtSerialPort имеет только версию 2. Ссылку на нее я дал.
PM   Вверх
EKoshelev
Дата 6.12.2012, 09:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



bsa, Да. Спутал. Надо будет её поковырять вообще-то.


--------------------
Вежливым и адекватным предлагаю общаться на "ты".
PM MAIL   Вверх
kuzulis
Дата 6.12.2012, 10:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Подконкретизирую: пока не имеет никакой версии, но после стабилизации она должна быть 1.0.0 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

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


 




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


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

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