Форум программистов, компьютерный форум, киберфорум
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.90/29: Рейтинг темы: голосов - 29, средняя оценка - 4.90
3 / 3 / 0
Регистрация: 08.10.2010
Сообщений: 114

997 при работе с СОМ портом

22.05.2012, 10:29. Показов 5865. Ответов 9
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем доброго. Давно не был здесь, но вот представился повод.
Сразу отмечу, что поиск курил. Но, то ли нет моей проблемы, то ли не так искал.
Начну по-порядку. Взял я себе плату небольшую и решил побаловаться с ней. Все настроил. Закодил ее. Потом перешел к Delphi. Почитал про работу с COM портами. Сразу отказался от использования компонентов в пользу WinAPI, чтобы четко понимать происходящее и все Тру делать.

Для начала все отбыдлокодил, подключение / запись посадил на кнопки без процедур / функций и вроде все заработало. Начал с отправки одного символа. И ОНО сработало. Вот тут пошло первичное оформление кода. Автоматический поиск платы, принудительное подключение к определенному порту и прочие хотелки. По факту написания всех функций и процедур начал тестирование / отладку и тут "на тебе" - 997. Протекает наложенное событие ввода / вывода. Что за хрень? Ладно. Переписываю все заново. Добавляю настройки таймаутов, перехожу в асинхронный режим работы. Тестирую. Та же ерунда. Подумал на плату. Вдруг что пишет в порт, а я не знаю. Сношу код платы, перезаливаю пустой. Очистил ее полностью. Тестирую - 997 [facepalm]. В оформлении кода и оптимизации прошло еще 2 вечера. Потом еще 2 на чтение WinAPI по работе с COM портами и типичными ошибками.

Короче, я бессилен. Чувствую, что без опыта коллег мои нервы будут съедены напрочь. Теперь к коду...

Подключение к плате:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
procedure ForcedConnectToBoard(ForcedPort: string);
begin
if connected = false then
  begin
  hPort := CreateFile(
                      PChar(ForcedPort), //Указываем порт
                      GENERIC_READ or GENERIC_WRITE, //Для чего открываем порт
                      0, //Указываем отсутствие общего доступа к порту
                      nil, //Нет атрибутов защиты
                      OPEN_EXISTING, //Аттрибут открытия порта
                      FILE_FLAG_OVERLAPPED, //Указываем для синхронной работы с портом
                      0 //Не указано, зачем это нужно, но говорят, что нужно
                      );
 
    //Проверка на наличие подключения
    if hPort = INVALID_HANDLE_VALUE //Если Хендл порта не присвоен
          then
            SendToMonitor('Ошибка соединения с портом ' + ForcedPort + SendError)
          else
            begin
            SendtoMonitor('Успешное подключение к плате.');
            //Пишем состояние подключения в переменную
            connected:=true;
            end;
 
    //Настройка порта
    if not GetCommState(hPort, Dcb) //Получаем данные о настройках порта
          then
            SendToMonitor('Ошибка получения данных о состоянии порта' + SendError)
          else
            begin
              //Настраиваем порт
              Dcb.BaudRate := CBR_9600; //Скорость соединения 9600
              Dcb.Parity := NOPARITY; //Нет контроля четности
              Dcb.ByteSize := 8; //1 байт - 8 бит
              Dcb.StopBits := ONESTOPBIT; //1 стоповый бит
            end;
 
    //Установка конфигурации порта
    if not SetCommState(hPort, Dcb)
          then
            SendToMonitor('Ошибка конфигурации порта' + SendError)
          else
            SendToMonitor('Конфигурация порта произведена успешно.');
 
    //Получение структуры CommTimeOut
    if not GetCommTimeouts(hPort, CommTimeouts)
        then SendToMonitor('Ошибка получения данных о таймаутах' + SendError)
          else
            begin
              CommTimeouts.ReadIntervalTimeout :=MAXDWORD;  //Настраиваем ReadFile на немедленный прием всех данных из буфера порта
              CommTimeouts.ReadTotalTimeoutMultiplier := 0; //...настраиваем
              CommTimeouts.ReadTotalTimeoutConstant := 0;   //...и продолжаем настраивать
              CommTimeouts.WriteTotalTimeoutMultiplier := 0;//А для WriteFile таймаут...
              CommTimeouts.WriteTotalTimeoutConstant := 0;  //...не требуется
              //Пишем новые параметры структуры
              SetCommTimeouts(hPort, CommTimeouts); //записываем измененную структуру
            end;
 
    //Очистка порта
    if not PurgeComm(hPort, PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR or PURGE_RXCLEAR)
          then
            SendToMonitor('Ошибка сброса порта' + SendError)
          else
            SendToMonitor('Порт сброшен и готов к работе.');
 
    //Разделитель в монитор
    SendSeparator;
  end
  else
    SendToMonitor('Подключение уже установлено.');
end;
Запись в порт(файл):
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
procedure SendCommand(WriteBuf: PChar);
var
  LenBytesToSend, LenBytesSended: DWORD;
  OverWrite: TOverlapped;
begin
 //Очищаем монитор
 ClearMonitor;
 
 //Получаем количество посылаемых байт
 LenBytesToSend:= SizeOf(WriteBuf);
 
 //Очистка порта
 if not PurgeComm(hPort, PURGE_TXCLEAR or PURGE_RXCLEAR)
      then SendToMonitor('Ошибка сброса порта' + SendError)
      else SendToMonitor('Порт сброшен и готов к работе');
 
 //Создаем событие записи
 OverWrite.hEvent := CreateEvent(nil, True, False, nil);
 if OverWrite.hEvent = Null
  then  SendToMonitor('Ошибка создания события записи' + SendError);
 
 //Собственно запись в порт
 if not WriteFile(
                  hPort,          //Порт, в который ведем запись
                  WriteBuf^,      //Что пишем в порт. ^ - не пойму для чего, без нее тоже вроде нормально работает...
                  LenBytesToSend, //Количество послаемых байт
                  LenBytesSended, //Количество реально посланных байт
                  @OverWrite      //Используем структуру OverLapped для ассинхронной записи
                  )
      then SendToMonitor('Ошибка отправки команды в порт' + SendError)
      else SendToMonitor('Команда успешно отправлена. Количество отправленных байт: ' + IntToStr(LenBytesSended));
 
end;
Вот такая ерунда. Заранее спасибо за ответы и помощь.

Добавлено через 10 часов 23 минуты
Еще одни момент: сброс порта (Purge) не помогает ни разу...
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
22.05.2012, 10:29
Ответы с готовыми решениями:

Ошибка при работе с COM-портом
Здравствуйте! Пульт, собранный на микроконтроллере, периодически посылает по RS485 на компьютер запросы, компьютер - отвечает. Однако,...

Работа с сом-портом
Суть программы-обмен данными с некоторым микроконтроллером. Одна из особенностей- RX и TX соединяются вместе. Получается, когда я...

Работа с СОМ портом
Для тех кто в танке то есть мой случай . Думаю можно отдельную тему вынести программирование СОМ порта. Поясните на как открыть ,...

9
 Аватар для raxper
10237 / 6615 / 498
Регистрация: 28.12.2010
Сообщений: 21,154
Записей в блоге: 1
22.05.2012, 10:59
...это значит, что операции ввода-вывода у вас в коде перекрываются http://msdn.microsoft.com/en-u... s.85).aspx. Вы привели весь код?
0
3 / 3 / 0
Регистрация: 08.10.2010
Сообщений: 114
23.05.2012, 15:22  [ТС]
2raxp - спасибо, я понимаю, что это значит.
Я не понимаю, откуда это появляется и как с этим бороться.
По коду привел все, что участвует. Если нужно, могу скинуть весь код (правда вечером). Но после компиляции я использую лишь кнопку подключения и кнопку записи. Вроде больше ничего не выполняется. 4 дня уже, все перепроверил. Может просто глаз замылен...

Добавлено через 1 минуту
UPD: CancelIoEx - только сейчас увидел в API, теоретически должно помочь?

Добавлено через 21 час 58 минут
CancelIO - не помогло, а CancelIoEx не идентифицируется... Кто-нибудь? Чем-нибудь?

Добавлено через 5 часов 22 минуты
Пойду ка я к Вашим младшим братьям. Лучше маленький форум, но хоть сколько-то эффективный, а не за 2 дня 1 полуживой ответ/вопрос от капитана. Конверсии никакой...
0
 Аватар для raxper
10237 / 6615 / 498
Регистрация: 28.12.2010
Сообщений: 21,154
Записей в блоге: 1
23.05.2012, 16:08

Не по теме:

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



Поскольку вы работаете в асинхронном режиме, то ERROR_IO_PENDING (997), который возвращает вам GetLastError() (а эту проверку в вашем коде не наблюдаю), говорит о том, что операция выполняется в фоне и нужно подождать, всего лишь.
0
3 / 3 / 0
Регистрация: 08.10.2010
Сообщений: 114
23.05.2012, 16:24  [ТС]

Не по теме:

Не по теме: я в курсе, что форум не чат. А полного кода никто и не просил. Я же специально отметил, что если нужно - приведу. Оказалось, что никому не нужно. И я знаю, что нужно это в первую очередь мне, но не имею привычки без повода засирать темы, ибо сам модератор.



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

Если я правильно Вас понял, то смотреть мне нужно либо в сторону снятия if not проверки (что некорректно, но без нее работало - получается в ней проблема), либо, что более вероятно, в сторону WaitForSingleObject.

Интересно только: какое оптимальное время для ожидания?

И... спасибо
0
 Аватар для raxper
10237 / 6615 / 498
Регистрация: 28.12.2010
Сообщений: 21,154
Записей в блоге: 1
23.05.2012, 17:01
Проверка GetLastError сидит в процедуре SendError, там комплексный лог генерится, застандартил его, чтобы каждый раз не писать.
точно? Так дело не пойдет, выкладываем всю подноготную. Как модератору вам должна быть знакома тема телепатов

в сторону WaitForSingleObject
да.

какое оптимальное время для ожидания?
хм, устройство ваше? Или дергайте разработчика о его таймаутах в протоколе обмена.
0
3 / 3 / 0
Регистрация: 08.10.2010
Сообщений: 114
24.05.2012, 20:19  [ТС]
Цитата Сообщение от raxp Посмотреть сообщение
точно? Так дело не пойдет, выкладываем всю подноготную. Как модератору вам должна быть знакома тема телепатов
Есть такая беда, но и засирателей хватает, выложу код, как доберусь до дома, но уверяю Вас, там ни намека на вмешательство в процесс. Процедура получает String и после него впечатывает код последней ошибки. Все.

Цитата Сообщение от raxp Посмотреть сообщение
хм, устройство ваше? Или дергайте разработчика о его таймаутах в протоколе обмена.
Arduino, не нашел в документации темы таймаутов, да и при работе с COM портом (по статьям в сети), таймауты на запись не ставятся. Остается искусственная задержка WaitForSingleObject для гарантии передачи данных или получении адекватного кода ошибки

Добавлено через 1 час 51 минуту
Delphi
1
2
3
4
5
function  SendError: string;
begin
  //Получение кода последней ошибки для отправки в монитор
  Result:='! Код ошибки: ' + IntToStr(GetLastError);
end;
Добавлено через 50 минут
дописал WaitForSingleObject, теперь программа даже за 10 секунд не отправляет 1 символ... Уже крыша едет...

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 //Собственно запись в порт
        WriteFile(
                  hPort,          //Порт, в который ведем запись
                  WriteBuf^,      //Что пишем в порт. ^ - не пойму для чего, без нее тоже вроде нормально работает...
                  LenBytesToSend, //Количество послаемых байт
                  LenBytesSended, //Количество реально посланных байт
                  @OverWrite      //Используем структуру OverLapped для ассинхронной записи
                  );
      waited := WaitForSingleObject(hPort, 10000);
      case waited of
           WAIT_OBJECT_0: SendToMonitor('Команда успешно отправлена. Количество отправленных байт: ' + IntToStr(LenBytesSended));
           Wait_timeout: SendToMonitor('Время ожидания отправки в порт истекло');
           WAIT_FAILED: SendToMonitor('Ошибка отправки команды в порт' + SendError);
           WAIT_ABANDONED: SendToMonitor('Мьютекс шалит. Где-то перекрестные потоки...');
      end;
UPD: waited: THandle

Добавлено через 20 часов 0 минут
Блииннн...

Добавлено через 4 часа 23 минуты
Ладно, продолжаю ждать...
0
 Аватар для raxper
10237 / 6615 / 498
Регистрация: 28.12.2010
Сообщений: 21,154
Записей в блоге: 1
24.05.2012, 23:50

Не по теме:

...обещанного три года ждут :)



Что такое SendToMonitor() ? Чего у него внутри?
0
3 / 3 / 0
Регистрация: 08.10.2010
Сообщений: 114
25.05.2012, 22:51  [ТС]
Да ничо особенного
Delphi
1
2
3
4
5
procedure SendToMonitor(SendedMessage: string);
begin
 Form1.Memo1.Lines.Add(IntToStr(MonitorLine)+')' + SendedMessage);
 MonitorLine:=MonitorLine + 1;
end;
Добавлено через 18 часов 25 минут
Не да?
0
3 / 3 / 0
Регистрация: 08.10.2010
Сообщений: 114
28.05.2012, 11:03  [ТС]
Может быть все таки кто-нибудь знает в чем дело?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
28.05.2012, 11:03
Помогаю со студенческими работами здесь

Работа с сом-портом
Есть прибор подключаемый через сом-порт и хотелось бы написать программу получения данных с помощью Labview. C помощью матлаба это...

Работа с СОМ-портом
Пишу программу для работы с устройством через COM-порт. Я отсылаю устройству запрос так: WriteFile(hComPort, buff, buffSize,...

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

Наводки при работе с портом Atmega8515
Atmega 8515 DDRB = 0xFF; //выход все порты б portb - out PORTB = 0xFF; PORTC = 0xFF;//on DDRC = 0x00;//in Если...

Управление кодировкой при работе с COM-портом
Здравствуйте господа! Столкнулся с такой трудностью. Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
Мысли в слух. Про "навсегда".
kumehtar 16.04.2026
Подумалось тут, что наверное очень глупо использовать во всяких своих установках понятие "навсегда". Это очень сильное понятие, и я только начинаю понимать край его смысла, не смотря на то что давно. . .
My Business CRM
MaGz GoLd 16.04.2026
Всем привет, недавно возникла потребность создать CRM, для личных нужд. Собственно программа предоставляет из себя базу данных клиентов, в которой можно фиксировать звонки, стадии сделки, а также. . .
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . . а удачный момент так и не приходит.
Фиксация колонок в отчете СКД
Maks 14.04.2026
Фиксация колонок в СКД отчета типа Таблица. Задача: зафиксировать три левых колонки в отчете. Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка) / / . . .
Настройки VS Code
Loafer 13.04.2026
{ "cmake. configureOnOpen": false, "diffEditor. ignoreTrimWhitespace": true, "editor. guides. bracketPairs": "active", "extensions. ignoreRecommendations": true, . . .
Оптимизация кода на разграничение прав доступа к элементам формы
Maks 13.04.2026
Алгоритм из решения ниже реализован на нетиповом документе, разработанного в конфигурации КА2. Задачи, как таковой, поставлено не было, проделанное ниже исключительно моя инициатива. Было так:. . .
Контроль заполнения и очистка дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: реализовать контроль корректности заполнения дат назначения. . .
Архитектура слоя интернета для сервера-слоя.
Hrethgir 11.04.2026
В продолжение https:/ / www. cyberforum. ru/ blogs/ 223907/ 10860. html Знаешь что я подумал? Раз мы все источники пишем в голове ветки, то ничего не мешает добавить в голову такой источник, который сам. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru