|
Работа с COM-портом |
|
|
|
Feb 3 2007, 12:24
|
Частый гость
 
Группа: Новичок
Сообщений: 100
Регистрация: 9-03-06
Пользователь №: 15 088

|
Дык, я ж говорю, что терминальной программой все нормально принимается (то что она несколько зависает, то ничего - главное все пакеты целые). Дело именно в моей программе =) Этим читаю: Код procedure InComm1(var i:byte;var IsIn:boolean); var bytes1:dword; begin IsIn:=false; clearcommerror(hcom1,com_error,@stat1);
if stat1.cbInQue>0 then begin if readfile(hcom1,databuf1,bufsize1,bytes1,nil) then begin i:=databuf1; IsIn:=true; end else showmessage('Ошибка приема'); end;
end; Читаю просто вызовом функции в потоке. (та же проблема остается при использовании CPort310)
|
|
|
|
|
Feb 3 2007, 12:45
|
Участник

Группа: Свой
Сообщений: 56
Регистрация: 25-06-05
Пользователь №: 6 300

|
ReadFile() вызывается в отдельном потоке по какому событию? При помощи SetCommMask или еще как? PS: Пока писал, ответ появился. Почитайте что-нибудь типа такого: http://www.delphimaster.ru/articles/comport2/index.htmlСразу скажу, что лучше Overlapped режим.
|
|
|
|
|
Feb 3 2007, 16:05
|
Частый гость
 
Группа: Новичок
Сообщений: 100
Регистрация: 9-03-06
Пользователь №: 15 088

|
Сегодня выяснилось, что и в Terminal приходят обрывки пакетов, реже чем в моей программе, но все-таки они есть. portmon показывает, что там приходят именно обрывки  Сейчас железо очередной раз перепроверяю. Попробую снизить скорость. Блин, где же собака порылась ?
Сообщение отредактировал CSB - Feb 3 2007, 16:08
|
|
|
|
|
Feb 3 2007, 22:25
|
Местный
  
Группа: Свой
Сообщений: 421
Регистрация: 25-12-04
Пользователь №: 1 675

|
Цитата(CSB @ Feb 3 2007, 16:05)  Попробую снизить скорость Скорость чего? Ваши 8 байт раз в 1мс только на 115200 и пролезут (если я математику не забыл)
|
|
|
|
|
Feb 4 2007, 00:43
|
Частый гость
 
Группа: Новичок
Сообщений: 100
Регистрация: 9-03-06
Пользователь №: 15 088

|
Цитата Скорость чего? Ваши 8 байт раз в 1мс только на 115200 и пролезут (если я математику не забыл) Скорость передачи. Это тестовая задача, потому можно варьировать некоторыми параметрами. Просто буду снимать меньше показаний и все. Такое впечатление, что пакеты теряются по дороге к ПК, хотя если смотреть по JTAG'у, то все нормально. Математика: 115200 kbps - это 11520 kBps (10 байт кадр). У меня получается 8 kBps. Поэтому остается некоторый запас.
|
|
|
|
|
Feb 4 2007, 00:53
|
Частый гость
 
Группа: Новичок
Сообщений: 100
Регистрация: 9-03-06
Пользователь №: 15 088

|
Цитата Может в паузе между байтами или пакетами? Не понял что вы имели в виду. (Паузы между пакетами разные - зависят от воздействия на датчик.) Ну путь винда как-то отделяет во времени пакеты, но теряться-то при этом они не должны, т.к. входного буфера должно вполне хватать.
|
|
|
|
|
Feb 4 2007, 01:33
|
Местный
  
Группа: Свой
Сообщений: 421
Регистрация: 25-12-04
Пользователь №: 1 675

|
Цитата(CSB @ Feb 4 2007, 00:43)  Скорость передачи. ... Я имел ввиду, что на 57600 уже не пролезет. Цитата(CSB @ Feb 4 2007, 00:43)  ... (10 байт кадр). ... Бит? т.е. без контроля - тока старт и стоп. Обычно, хвосты теряются из-за ошибок передающей стороны - когда выдаете следующий байт не дождавшись "ухода" предыдущего в линию.
|
|
|
|
|
Feb 4 2007, 12:13
|
Частый гость
 
Группа: Новичок
Сообщений: 100
Регистрация: 9-03-06
Пользователь №: 15 088

|
Цитата Бит? т.е. без контроля - тока старт и стоп. угу, конечно бит. Цитата Обычно, хвосты теряются из-за ошибок передающей стороны - когда выдаете следующий байт не дождавшись "ухода" предыдущего в линию. Следующий байт записываю в регистр передачи только по окончанию передачи предыдущего байта.
|
|
|
|
|
Feb 4 2007, 22:45
|
Участник

Группа: Участник
Сообщений: 24
Регистрация: 8-10-06
Пользователь №: 21 094

|
В принципе, можно попробовать работать с портом напрямую. Я писал прогу, работающую как цифровой осциллограф, у меня получились следующие результаты:
Погрешность измерения временных интервалов: На частоте до 1 кГц: не более 1%; На частоте 1-10 кГц: не более 10%; На частоте 10-50 кГц: не более 50%;
Вот кусок кода, отвечающий за доступ к порту:
//Маска битов для определения линии запуска WaitMask:=$0; if CTS_Start.Checked then WaitMask:=WaitMask or $10; if DSR_Start.Checked then WaitMask:=WaitMask or $20; if RI_Start.Checked then WaitMask:=WaitMask or $40; if DCD_Start.Checked then WaitMask:=WaitMask or $80;
//Настройка порта with SPort do begin OpenDriver; WriteByte(Base+3,$83); WriteWord(Base,$0001); WriteByte(Base+3,$3); end;
HoldByte:=0; WR:=SPort.ReadByte(Base+4); SPort.WriteByte(Base+4,WR and $FC); if HoldRTS.Checked then HoldByte:=HoldByte or $02; if HoldDTR.Checked then HoldByte:=HoldByte or $01;
//Зарядка конденсатора, ожидание переходных процессов. StartTimer.Enabled:=true; While StartTimer.Enabled and (Aborted = false) do begin //Держать сигналы WR:=SPort.ReadByte(Base+4); SPort.WriteByte(Base+4,WR or HoldByte); Application.ProcessMessages; end; //Ожидание первого импульса. D:=SPort.ReadByte(Base+6) and WaitMask; //D1:=D and WaitMask;
repeat Application.ProcessMessages;
WR:=SPort.ReadByte(Base+4); SPort.WriteByte(Base+4,WR or HoldByte);
D1:=SPort.ReadByte(Base+6); D1:=D1 and WaitMask; until (D<>D1) or Aborted;
//Байт для удержания RTS и/или DTR WR:=SPort.ReadByte(Base+4); SPort.WriteByte(Base+4,WR or $02);
//Включение таймеров HighResTimer1.Enabled:=true; HighResTimer1.StartTimeMeasure; STime:=GetTickCount;
while ((GetTickCount-STime)<MeasureTime) and (not Aborted) do begin //RTS / DTR SPort.WriteByte(Base+4,WR); //Сигналы D:=SPort.ReadByte(Base+6); if D<>D1 then begin HighResTimer1.StopTimeMeasure; Time:=HighResTimer1.GetTimeDifference; HighResTimer1.StartTimeMeasure; SetLength(Data, I+1); Data[I,0]:=Time+Data[I-1,0]; Data[I,1]:=D; D1:=D; Inc(I); end; end;
EndTime:=GetTickCount;
HighResTimer1.StopTimeMeasure;
Разумеется, нужно знать спецификации UART. Сразу предупреждаю: в windows работа с железками в реальном времени возможна только из RING 0. Всё остальное - разные степени приближения.
--------------------
|
|
|
|
|
Feb 5 2007, 23:53
|
Местный
  
Группа: Свой
Сообщений: 278
Регистрация: 18-01-05
Из: Санкт-Петербург
Пользователь №: 2 031

|
Цитата Пакет обрамлен стартовыми и оконечными байтами (при таком обрамлении пакета мне проще онадизировать целостность пакета). Формат передачи: 10 бит, стартовый бит + 8 бит данных + 1 стоп-бит. Все стандартно. 1.Байт стаффинг используется? Что например получится если один из неадресных байтов будет таким же как адресный? 2.Вы говорили что пакеты неполные получаете => целостность пакетов нарушена. Если п.1 не поможет попробуйте оставить всё как есть, но передавать из железяки всё время одинаковый пакет типа s 1 2 3 4 5 e, где s, e стартовый и стоповый байты, а цифирки - значения передаваемых байтов. Может локализуете проблему.
|
|
|
|
|
Feb 6 2007, 09:32
|
Частый гость
 
Группа: Новичок
Сообщений: 100
Регистрация: 9-03-06
Пользователь №: 15 088

|
Байт стаффинг не используется: пакет-то обрамлен с двух сторон и имеет фиксированную длину, поэтому отличать адресный байт от неадресного просто. Цитата 2.Вы говорили что пакеты неполные получаете => целостность пакетов нарушена. Если п.1 не поможет попробуйте оставить всё как есть, но передавать из железяки всё время одинаковый пакет типа s 1 2 3 4 5 e, где s, e стартовый и стоповый байты, а цифирки - значения передаваемых байтов. Может локализуете проблему. Передавал и смотрел в железяку JTAG'ом - отправлялось все нормально. Кабель для связи - экранированный.
|
|
|
|
|
Feb 6 2007, 09:52
|
Участник

Группа: Свой
Сообщений: 56
Регистрация: 25-06-05
Пользователь №: 6 300

|
Была такая же бага (потери кусков данных), когда читал просто в цикле по такому же принципу: Код if stat1.cbInQue>0 then И тоже терминальной программой все нормально принималось. Только, когда использовал компонент TComm от AsyncPro и событие OnRxChar, получил все данные без потерь от непрерывного потока на обычном COM-порту при скорости 115200. На том же компоненте удалось получать данные и при скорости 921600 на виртуальном COM-порту от FTDI. По поводу проверки железа - Rx и Tx закорачивается в конце кабеля. Пишется микрокусок программы (а то и отдельная микропрограмма) на передачу-прием-контроль. Сразу видно, что не так. Для виндовс программы тоже желательно провести такую процедуру, чтобы быть увереным в своей программе.
|
|
|
|
|
Feb 6 2007, 10:44
|

Частый гость
 
Группа: Свой
Сообщений: 89
Регистрация: 28-10-05
Из: Киев
Пользователь №: 10 227

|
Цитата(CSB @ Feb 2 2007, 16:11)  Тема не раз поднималась, но все таки остались вопросы. Есть датчик, который посылает на ПК некие промежуточные результаты. На ПК все нормально принимается и обсчитывется конечный результат. Пакеты по 8 байт. Скорость UART 115200 kbps. Использую ReadFile() и CPort ( В CPort тоже используется ReadFile() ). Но как только частота передачи возрастает до 1000 посылок в секунду, то в винде начинатся проблемы: приходят неполные пакеты, часто приходит только заголовок пакета, а остальная часть нули или заголовок может оказаться в середине пакета. Увеличение приемного буфера в винде не решило проблемы. При отключении графики и прочего пакеты иногда принимаются нормально. Но без отображения результатов никак.
ЗЫ В Terminal все принимается нормально - там есть возможность записать в лог принимаемые байты. Пробовал DLPortIО, но так и не понял как подружить COM с этим драйвером. была похожая проблемма: никак не удавалось получить полный пакет. решил с помощью побайтового приема (ReadFile() в цикле принимает один байт, который потом складывается в буфер)
|
|
|
|
|
Feb 6 2007, 16:25
|
Частый гость
 
Группа: Новичок
Сообщений: 100
Регистрация: 9-03-06
Пользователь №: 15 088

|
Цитата терминальной программой все нормально принималось. Повторюсь: проблема была выявлена и при работе с терминалом. Цитата решил с помощью побайтового приема По-байтовый прием и делаю. Тут на форуме читал, что ReadFile() весьма медленная функция и нужно писать свой драйвер или юзать что-то типа DriverLINX Port IO. Но DriverLINX Port IO пока так и не смог прикрутить к СОМ-порту.
|
|
|
|
|
Feb 6 2007, 20:39
|
Местный
  
Группа: Свой
Сообщений: 278
Регистрация: 18-01-05
Из: Санкт-Петербург
Пользователь №: 2 031

|
Цитата Тут на форуме читал, что ReadFile() весьма медленная функция и нужно писать свой драйвер Ну хз. Ни в Win98 ни в WinXP подобной проблемы у меня не было, хотя пакеты имели бо'льший размер! ReadFile должна возвращать количество принятых байт, возвращает 8? Было бы неплохо посмотреть код настройки ком порта.
|
|
|
|
|
Feb 9 2007, 17:41
|
Участник

Группа: Свой
Сообщений: 63
Регистрация: 5-05-06
Пользователь №: 16 804

|
По-моему, надо использовать асинхронный режим IO (CreateFile с флагом OVERLAPPED), и буфер достаточно большого размера (ну хоть несколько Кб).
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|