Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: COM порт, можно ле решить лимитирование времени  (Прочитано 10988 раз)
0 Пользователей и 7 Гостей смотрят эту тему.
Федя
Гость
« : 13-10-2004 07:54 » new

Постановка задачи
---------------------------------
   Нужно написать программу под ОС Windows 2000, которая реализует взаимодействие с устройством через последовательный порт (RS-232) на скорости 4800 бод. Компьютер должен принимать поток байт, если в потоке приходят 2 определенных байта, то нужно за 65 миллисекунд от момента их приема послать заранее подготовленных 20 байт. Управление потоком и т.п. не используется, устройство никак не контролирует приём байт компьютером, компьютер никак не контролирует устройство.
   Проблема заключается в том, чтобы уложиться в эти 65 миллисекунд (это предельное значение), а желательно меньше 20-40 миллисекунд.
   По моей оценке* на основе тестового приложения это невозможно сделать в рамках пользовательского Win32 приложения.

Вопросы
---------------------------------
   Возможно ли решить эту задачу путём написания драйвера последовательного порта (или внесением модификации в существующий драйвер serial.sys, если я правильно понял пример из DDK под Windows 2000 и есть этот драйвер)?
   По моей оценке на основе исходников serial.sys проанализировать получение 2 байт  можно непосредственно в обработчике прерывания (функция SerialISR()), остается инициировать из обработчика прерываний запись 20 байт в порт. Возможно ли сделать это в указанных временных рамках и если да, то по какой схеме это сделать?
   Можно реализовать задачу не через собственный драйвер, а обращаясь к существующему драйверу** из режима ядра используя Irp запросы?
   Может быть такое, что задачу можно реализовать из пользовательского приложения?
   Какую информацию и где можно посмотреть по данным вопросам?

Примечания
---------------------------------
*   Оценка времени получена следующим образом. Время измерялось функцией GetTickCount(). Написано 2 тестовые программы (используются вызовы WinAPI), которые взаимодействуют с друг другом через последовательный порт (2 компьютера соединены через нуль-модемный кабель). Первая (программа А) посылает 2 байта и принимает 20 байт,  вторая (программа B) ждет приёма 2 байт и посылает 20 байт. Если в программе А сделать задержку (Sleep()) меньше 120 мс, то будет приходить меньше 20 байт в рамках одной операции чтения FileRead(). В программе B временной интервал от наступления выполнения потока после задержки функцией WaitCommEvent() до завершения операции WriteFile() время скачет, т.е. может быть 0 мс, а может быть 30-40 мс. Из всего этого я сделал вывод, что гарантированно реализовать указанную задачу в рамках пользовательского приложения (с учетом того, что нужен запас времени) невозможно.
**   Как я понял, одна из проблем это буферизация порта. Если я правильно понял из пользовательского приложения можно только рекомендовать функцией SetupComm() размеры буферов (кажется драйвера, а не порта), но отключить её нельзя. Если я правильно понял драйвер анализирует микросхему и включает буферизацию вроде как особо никого не справшивая.
Записан
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #1 : 13-10-2004 08:06 » 

Ну я не спец в дровах, но думаю что можно реализовать это посредством драйвера-фильтра над ком портом. Данные пойдут сначала через фильтр, а потом фильтр отправит их вниз драйверу ком порта, но это моё ИМХО.  Есть на сайте нашем в разделе "файлы" книга по дровам Вальтера Оней.
Записан

MCP, MCAD, MCTS:Win, MCTS:Web
Серж
Гость
« Ответ #2 : 13-10-2004 10:03 » 

Федя, по-моему, никакой драйвер не нужен. Читать данные из порта нужно асинхронно, сколько придет, столько и считывать и анализировать получение необходимых двух, а на отсылку 20 байт при скорости 4800 бод у тебя есть запас ~25 мс (40 мс отнимает железо), это же очень много. Если машина быстродействующая, то его за глаза хватит для переключения потоков и прочих системных дел. Если же его не хватит, в конце концов задай максимальный приоритет своему процессу перед вызовом WriteFile, а потом после записи верни нормальный.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #3 : 13-10-2004 11:18 » 

Вообще то есть функция SetCommTimeouts где можно очень четко выставить все задержки которые будут идти в драйвере. Сам по себе драйвер тебе писать ИМХО совершенно не нужно...

Кроме того, из задания не ясно какие 20 байт тебе надо отправить...

Ведь они могут быть подготовлены заранее.
Если я правильно понял можно сделать такую структуру.

Например:

1. Создается окно аппликации.

2. Инициализируются ВСЕ возможные наборы данных в виде 20-байтных буферов. (В качестве вопроса, как они зависят от 2 принятых байт и зависят ли вообще. Или они всегда одни и теже???)

3. ЗАпускается отдельный поток (_beginthreadex() ) который получает повышенный приоритет и ставится в суспенд. (спящий режим).

4. ЗАпускается еще оджин поток (читающий данные асинхронно и ждущий приходящие байты на функции WaitCommEvent).
(Примеры кода как его организовать тут на форуме есть).

5. Как только читающий поток принял 2 нужных байта он выставляет сообщение на отсылку для первого потока, который сидит в спящем режиме.
При нужном приоритете (или/и вообще при отмене переключения контекста с одного процесса на другой в момент передачи 20 байт буфера) отправляются нужные данные и все восстанавливается в исходную позицию на ожидание очередных 2 байт инфы...



Маленькое пояснение.
В коде на С++ для винды можно выставить блок кода в процессе(потоке), когда пока он выполняется не будет винда обращать внимание на остальные процессы и потоки которые могли бы помешать текущему, запросив время у процессора на обслуживание.
Т.е. пока нужный код не выполнется и не отключит блокировку, будет выполнятся только этот поток и сисемные процессы, без которых невозможно обойтись...

Как это сделать я счас навскидку не помню, но этот метод описан у Рихтера в книге, которая лежит у нас на сайте на русском в двух видах...

Удачи...
Записан

А птичку нашу прошу не обижать!!!
Федя
Гость
« Ответ #4 : 14-10-2004 05:55 » 

Спасибо за ответы,
думаю если кого заинтересует данная тема, то интересно будет
почитать достаточно исчерпывающий ответ от Leo
(создать драйвера последовательного порта SerialXP)
http://www.bugtraq.ru/cgi-bin/forum.mcgi?type=sb&b=2&m=113315
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 14-10-2004 16:28 » 

Цитата

В коде на С++ для винды можно выставить блок кода в процессе(потоке), когда пока он выполняется не будет винда обращать внимание на остальные процессы и потоки которые могли бы помешать текущему, запросив время у процессора на обслуживание.


так это критическая секция -

делаем

#include "Afxmt.h"

CCriticalSection m_crisec;

f()
{
...
...
    m_crisec.Lock();
//сюда больше никто не пролезет Улыбаюсь
    m_crisec.Unlock();
...
...
}
Записан

Серж
Гость
« Ответ #6 : 15-10-2004 06:34 » 

Федя, не со всем могу согласиться в исчерпывающем ответе Leo,
совсем не обязательно принимать по одному байту, достаточно ожидать в WaitCommEvent событие EV_RXCHAR и принимать, сколько придет, при этом необязательно пользоваться функциями WriteFileEx и ReadFileEx, достаточно и обычных WriteFile и ReadFile. Конечно, если WriteFile будет находиться  в одном потоке с приемом, то он должен быть асинхронным. И что совершенно отсутствует в ответе, так это то, что обязательно нужно отключить аппаратное FIFO, т.к. по умолчанию этот флаг включен. Это сброс определенного флага в DCB.
Записан
Rulik
Помогающий

ru
Offline Offline

« Ответ #7 : 02-11-2004 06:38 » 

Цитата

Цитата:

В коде на С++ для винды можно выставить блок кода в процессе(потоке), когда пока он выполняется не будет винда обращать внимание на остальные процессы и потоки которые могли бы помешать текущему, запросив время у процессора на обслуживание.



так это критическая секция -

делаем

#include "Afxmt.h"

CCriticalSection m_crisec;

f()
{
...
...
m_crisec.Lock();
//сюда больше никто не пролезет  
m_crisec.Unlock();
...
...
}


Не соглашусь с этим. Критическая секция защищает ресурс, а не выделяет тебе процессор эксклюзивно. Тебя в любой момент могут прервать другие процессы.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #8 : 02-11-2004 10:15 » 

Rulik, да ты прав. Я не имел в виду захват всего процессора, невнимательно прочитал выше
Записан

Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines