Всем привет, нужна помощь. Есть прибор пишет в com порт по адресу 0x3fe. Есть программа для Win98 под DOS для работы с этим пробором. Встала задача переписать программу на C/C++ для Win2000/XP. Написал драйвер для чтения данных(READ_PORT_UCHAR) из этого порта, проблема в том что данные всегда = 0xff, насколько я понимаю это из-за мапирования адреса Hal-ом. Вопрос№1 Насколько я прав и что мне делать? Заранее спасибо!
Я бы сначала попробовал прочитать через гипертерминал. А зачем вообще драйвер, если COM прекрасно читается через API?
Quantum Насколько мне известно стандартное com устройство пишет по определенному аддресу(например 0x3f8) и у него же 0x3fe - это байт который отвечает за MSR. А так как устройство не стандартное, то WinApi не поможет. Поправьте, если не прав.
Shtasik Что значит ? Устройство просто подключено к разьёму порта и посылает в него байты по протоколу RS232. Нестандартно это сделать никак нельзя. Запустите ГиперТерминал на этот порт и удостоверьтесь, что данные читаются.
Quantum Насколько мне известно у com port№1 есть диапозон ввода - 0x3f8-0x3ff - именно про эту адресацию я имел ввиду. По протоколу RS232 байт 0x3fe отвечает за MSR. - подскажите пожайлуста как это сделать?
Shtasik Открываете HyperTerminal (он обычно есть в любой винде), выбираете COM1 (или COM2/COM3/... в зависимости от того, к какому порту подключено устройство), настраиваете параметры порта и смотрите на экран. Чтобы продублировать эту функциональность на C достаточно использовать API-функции: CreateFile("COM1",...) + SetCommTimeouts + ReadFile + ... Верно, но использовать этот регистр напрямую не имеет смысла в среде Win32, IMHO.
Quantum использовать этот регистр напрямую не имеет смысла в среде Win32, IMHO. Имеет. Только надо или самостоятельно открыть порты в iomap, или использовать какой-нибудь универсальный драйвер типа twichw32. А проще всего использовать стандартные возможности win32api: Код (Text): /* ------ Тестирование портов при помощи "заглушки" ----- */ #include <windows.h> #include <stdio.h> #include <mem.h> HANDLE p; DCB d; COMMTIMEOUTS c; char ch, buf[]={"Test string"}; int q, i=0; unsigned long n; main() { /* --------------- Открыть устройство ------------------- */ p=CreateFile("COM2",GENERIC_READ|GENERIC_WRITE, 0,NULL,OPEN_EXISTING,0,NULL); /* ----------- Установить формат кадра ------------------ */ d.DCBlength=sizeof(DCB); d.fNull=TRUE; BuildCommDCB("baud=1200 parity=N data=8 stop=1",&d); SetCommState(p,&d); /* ------ Установить тайм-ауты (в миллисекундах) -------- */ setmem( &c, sizeof(c), 0); /* Обнуление остальных полей */ c.ReadIntervalTimeout=100; /* Тайм-аут для чтения */ SetCommTimeouts(p,&c); /* --------- Передать/принять строку данных ------------- */ while (buf[i]) { WriteFile(p, &(buf[i++]), 1, &n, NULL); q=ReadFile(p, &ch, 1, &n, NULL); putchar(ch); } /* -------------- Закрыть устройство -------------------- */ CloseHandle(p); }
Quantum - молчит как партизан =(( - пробовал и не раз, ваш и мой код виснит на ReadFile =(( - подкажите, пожайлуста как это сделать?
Shtasik ваш и мой код виснит на ReadFile =(( 1. Мой код рассчитан на COM2. Учтено? 2. Мой ReadFile не должен виснуть, даже если в порту пусто, а должен возвращать управление через тай-аут 0.1 сек. Зато он циклятся, пока не появится нулевой байт. Учтено?
drmad И всё? Может объясните несведущим каков тайный смысл обращения к регистру состояния линий напрямую в Win32? Зачем же всё усложнять? Человеку нужно прочитать 1 байт из порта, а Вы сюда ещё и запись делаете. Shtasik Чтоб пример drmad работал нужно сделать заглушку в порту, чтоб всё записанное в него сразу же возвращалось как эхо. Вам же из его цикла нужен только ReadFile. Попробуйте поменять настройки. Скорость (baud) не имеет значения, т.к. обычно UART умеет определять её автоматически, но все остальные параметры критичны. Собственно, HyperTerminal для того и нужен чтобы быстро подобрать настройки.
drmad все учтено. вы конечно не поверите, но он виснет всегда =(( что есть устройство, что его нет =(( и никакой тайм-аут не срабатывает, может у меня что-то с компьютером? Еще раз хотел спросить про Quantum полчаса маялся перебирая параметры, безуспешно. ------------------------------------------------ Коллеги, я понимаю, что использовать написанный код winapi гораздо лучше нежели писать свой драйвер (и ваш резонный вопрос - что же ты это не юзаешь? - мне очень понятен), но он уже написан, моя проблема скорее в том, что он не совсем то что нужно возвращает - я вот тут кое-что откопал, может это мой root cause? Если вам не сложно взгляните? http://www.osronline.com/custom.cfm?name=articlePrint.cfm&id=84
Quantum Может объясните несведущим каков тайный смысл обращения к регистру состояния линий напрямую в Win32? Э... гм... не понял. Если вам нужно обращаться к "регистру состояний линий", то обращайтесь на здоровьице. Если не нужно, то и не обращайтесь. Все зависит от задачи. Зачем же всё усложнять? Это просто старая рабочая программа. обычно UART умеет определять её автоматически Гм... Прежде чем делать такие заявления, на практике самому попробовать - слабо?
А статьи Four-F`а почитать не судьба ? Он даже пример приводит, как разрешить доступ ко всем портам разом.
drmad Зачем? В древнем досе имело смысл к нему обращаться, т.к. никаких высокоуровневых апи ещё не существовало и читать/писать в порт приходилось чуть ли не бит-поллингом, как тогда выражались. А ещё приходилось искать адрес портов COM/LPT весьма маразматическими методами. Но всё это в прошлом. Вопрос взаимный. значит, что на большинстве современных ПК установлены продвинутые контроллеры, которые умеют безошибочно угадывать скорость входящих данных. Могу даже объяснить как они это делают, но это бедет уже оффтоп, да и лениво что-то описывать теорию. На 3х моих компах утверждение совершенно справедливо. Shtasik Я упустил из виду, что есть готовый код работающий в досе. Если этот код реализует какой-то сложный протокол, вроде рекопожатия через линии состояния, то его, конечно, проще не трогать. Всё-таки использовать АПИ имеет свои плюсы: переносимость на 9x/NT/XP, автоопределение адреса порта по символическим ссылкам, вроде "COM1", поддержка всяких переходников на USB/LPT и т.д. Теперь по делу: ReadFile виснет, видимо, по одной простой причине. Устройство не посылает в порт байты по протоколу RS232. Скорее всего, оно просто замыкает основные и контрольные линии порта CTS, DSR, ... В таком случае нужно мониторить отдельные события. В принципе, для этого можно использовать SetCommMask / WaitCommEvent, но это сильно усложнит и без того громоздкий код. Использовать хакерские драйверы вроде GiveIO для открытия адресов портов для пользовательского кода я не советую, т.к. на практике доказана их нестабильность. Тут можно почитать про IOMAP: Direct Port I/O and Windows NT by Dale Roberts Так что использовать это безопасно только в драйвере, но раз он у Вас уже есть, то дело за малым. ЗЫ: Статьи Four-F лежат на сайте wasm.ru
Quantum если вы знакомы с pascal (а скорее всего так и есть), то там это выглядит след образом - b = port[0x3fe]; - вот и весь код чтения данных из порта =)) - спасибо! - ну это как сказать...с учетом того что я программирую обычно на Java=))
Shtasik Тогда я уважаю вашу решительность С помошью статей Four-F, конечно, не так сложно разобраться, но всё-таки...