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

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

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

Author24 — интернет-сервис помощи студентам
Всем доброго. Давно не был здесь, но вот представился повод.
Сразу отмечу, что поиск курил. Но, то ли нет моей проблемы, то ли не так искал.
Начну по-порядку. Взял я себе плату небольшую и решил побаловаться с ней. Все настроил. Закодил ее. Потом перешел к 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
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.05.2012, 10:29
Ответы с готовыми решениями:

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

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

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

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

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

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

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

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

Не по теме:

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



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

Не по теме:

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



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

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

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

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

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

какое оптимальное время для ожидания?
хм, устройство ваше? Или дергайте разработчика о его таймаутах в протоколе обмена.
0
3 / 3 / 0
Регистрация: 08.10.2010
Сообщений: 114
24.05.2012, 20:19  [ТС] 7
Цитата Сообщение от 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
10234 / 6612 / 498
Регистрация: 28.12.2010
Сообщений: 21,155
Записей в блоге: 1
24.05.2012, 23:50 8

Не по теме:

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



Что такое SendToMonitor() ? Чего у него внутри?
0
3 / 3 / 0
Регистрация: 08.10.2010
Сообщений: 114
25.05.2012, 22:51  [ТС] 9
Да ничо особенного
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  [ТС] 10
Может быть все таки кто-нибудь знает в чем дело?
0
28.05.2012, 11:03
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
28.05.2012, 11:03
Помогаю со студенческими работами здесь

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru