- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 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
var
CommHandle:integer;
DCB:TDCB;
Stat:TComStat;
Kols,TransMask,Errs:DWord;
Ovr:TOverlapped;
s:string;
i:integer;
{Чтение канала n}
function ReadChannel(n:integer):string;
begin
inc(n,32); //код запроса для прибора (это по спецификации прибора)
s:=chr(n); //символ запроса
WriteFile(CommHandle,s[1],length(s),Kols,@Ovr); //оправили этот код в прибор
TransMask:=0; //маска любого события в порте
Ovr.hEvent:=CreateEvent(nil, True, False, nil); //хз
repeat
if not WaitCommEvent(CommHandle, TransMask, @Ovr) then //если приём закончен не до конца, то...
if GetLastError = ERROR_IO_PENDING then WaitForSingleObject(Ovr.hEvent, INFINITE); //при условии "хз" подождать ещё чуть-чуть
ClearCommError(CommHandle,Errs,@Stat); //скинуть длину байт из буфера порта в переменную Stat
Kols:=Stat.cbInQue; //выяснить длину символов
until (Kols=1) or (Kols=14); //закончить, если в канале пусто (1) или данные есть (14)
SetLength(s,Kols); //установить переменную s длиной Kols
ReadFile(CommHandle,s[1],Kols,Kols,@Ovr); //прочитать данные из порта в s, обнулив буфер
if length(s)=1 then ReadChannel:='Пусто'; //дальше просто идёт обработка полученных данных
if length(s)=14 then ReadChannel:=copy(s,5,7);
end;
{Основной код}
for i:=1 to 60 do Value:=ReadChannel(i); //ПОЛУЧИТЬ ДАННЫЕ ИЗ ПОРТА n
Имеется прибор с хранением данных в 60 каналах. Связь осуществляется по RS-232.
Чтобы получить данные, нужно отправить № кода нужного канала. В ответ придут данные этого канала.
Если канал пустой, то приходит 1 байт, если данные есть, то 14 байт.
Создана функция ReadChannel(n) с запросом данных из канала n.
ПРОБЛЕМА:
Прочитать все 60 каналов удаётся иногда 3 раза, иногда 15 раз. Но обязательно когда-нибудь программа зависнет на
WaitCommEvent(CommHandle, TransMask, @Ovr), так ничего и не получив из порта.
Если между командами
WriteFile и WaitCommEvent
поставить sleep(50) //9600 бод = 1200 б/с, то бишь 12 мс на 1 байт
то всё пашет. Но это не дело же привязываться ко времени?
Как избавиться от зависания на WaitCommEvent, чтобы процесс продолжился?
Если прибор не получил байт, из-за чего не ответил, как это проверить? "Данных нет уже 0,5 с, значит и не будет; отправлю этот байт ещё раз".
guest 10.06.2011 15:29 # −2
sayidandrtfm 10.06.2011 16:07 # +2
P.S. Дуршлаг в топку.
Lure Of Chaos 10.06.2011 16:53 # +2
gegMOPO4 10.06.2011 17:37 # 0
bugmenot 12.06.2011 10:56 # −1
и сдаётся мне, что кто-то не знает, сколько битов на секунду в одном боде
Paragraf 10.06.2011 17:59 # +1
А может у кого то есть идеи?
danilissimus 10.06.2011 18:42 # 0
sbs 12.06.2011 05:33 # −2
Нашёл очень полезную подробную информацию здесь
http://compconnect.ru/2011/02/rabota-s-com-portom-v-delphi-pri-pomoshhi-winapi-chast-2-asinxronnyj-rezhim/
bugmenot 12.06.2011 06:14 # +1
и что, уютненький говнокодик опять скатывается в сраный дельфинубофорум?
Lure Of Chaos 12.06.2011 10:17 # 0
bugmenot 12.06.2011 10:52 # 0
sbs 12.06.2011 14:17 # 0
Это тебе не
if ListbBox1.Items.Strings[ListBox1.ItemIndex]='0' then showmessage('Строка 0');
if ListbBox1.Items.Strings[ListBox1.ItemIndex]='1' then showmessage('Строка 1');
if ListbBox1.Items.Strings[ListBox1.ItemIndex]='2' then showmessage('Строка 2');
if ListbBox1.Items.Strings[ListBox1.ItemIndex]='3' then showmessage('Строка 3');
bugmenot 12.06.2011 18:34 # 0
кисонька, наложенный ввод/вывод - это просто и прямолинейно, если прочитать в справочнике PSDK перед тем, как колотить по клавиатуре