Hirdetés
- Xiaomi 15T - reakció nélkül nincs egyensúly
- Samsung Galaxy Watch (Tizen és Wear OS) ingyenes számlapok, kupon kódok
- Visszatérnek a Samsung tervezte CPU-magok és GPU az Exynos 2800-ban?
- Rugalmas OLED panelre válthat a Samsung Galaxy A57
- Milyen okostelefont vegyek?
- Samsung Galaxy A54 - türelemjáték
- Motorola G86 - majdnem Edge
- Google Pixel 9 Pro XL - hét szűk esztendő
- QWERTY billentyűzetes, üzenet-fókuszú androidos mobil a Clicks Communicator
- CES 2026: Minden kiszivárgott bemutatója előtt a Motorola új csúcstelefonjáról
Új hozzászólás Aktív témák
-
P.H.
senior tag
Valóban megáll LPT portnál, ha nincs rádugva semmi, illetve ha a ''az én cuccom pedig nem válaszol csak végrehajt'' azt jelenti, hogy nem billenti meg az ACK vonalat sem, akkor megoldás az overlapped (magyarul aszinkron) I/O.
Kérdés: azt nem írtad, hogy a jel kiment azért?
Az overlapped I/O-t inkább ide írom, még hasznos lehet. 4 kis rutin, ezek mennek LPT-re és COM-ra is, illetve a COM-ra lesz még egy kis toldalék.
..uses Windows;
..type
....TCOMM = record
........Handle: THANDLE;
........TimeOut: DWORD;
........Overlap: OVERLAPPED;
........State: DCB; end;
..const
....COMM_SUCCESS = 0;
....COMM_OPEN_FAILED = 1;
....EVENT_CREATION_FAILED = 2;
....COMM_STATE_SET_FAILED = 3;
{===================================================================}
..function _OPENCOMM(PortName:PCHAR; var Com:TCOMM): byte;
....begin
......result:=COMM_SUCCESS;
......ZEROMEMORY(@com,sizeof(com));
......com.handle:=CREATEFILE(portname,
..........(GENERIC_READ or GENERIC_WRITE),
..........0,
..........nil,
..........OPEN_EXISTING,
..........(FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED),
..........0);
......if com.handle = INVALID_HANDLE_VALUE then
........result:=COMM_OPEN_FAILED
......else begin
........com.overlap.hevent:=CREATEEVENT(nil,true,false,nil);
........if com.overlap.hevent = 0 then begin
..........result:=EVENT_CREATION_FAILED;
..........CLOSEHANDLE(com.handle); end; end; end;
{===================================================================}
..procedure _CLOSECOMM(var Com:TCOMM);
....begin
......CLOSEHANDLE(com.overlap.hevent);
......CLOSEHANDLE(com.handle); end;
{===================================================================}
..function _READCOMM(var Com:TCOMM; var Size:DWORD; var Dest): boolean;
....var Moved: DWORD;
....begin
......RESETEVENT(com.overlap.hevent);
......result:=READFILE(com.handle,dest,size,moved,@com.overlap);
......if not result and (GETLASTERROR = ERROR_IO_PENDING) then
........begin
........WAITFORSINGLEOBJECT(com.overlap.hevent,com.timeout);
........result:=GETOVERLAPPEDRESULT(com.handle,com.overlap,moved,false);
........end;
......if result then size:=moved; end;
{===================================================================}
..function _WRITECOMM(var Com:TCOMM; var Size:DWORD; var Src): boolean;
.....var Moved: DWORD;
.....begin
......RESETEVENT(com.overlap.hevent);
......result:=WRITEFILE(com.handle,src,size,moved,@com.overlap);
......if not result and (GETLASTERROR = ERROR_IO_PENDING) then
........begin
........WAITFORSINGLEOBJECT(com.overlap.hevent,com.timeout);
........result:=GETOVERLAPPEDRESULT(com.handle,com.overlap,moved,FALSE);
........end;
......if result then size:=moved; end;
{===================================================================}
Kell egy struktúra, ami tartalmaz minden struktúrát és változót, amit kell: TCOMM
Kell egy eljárás, ami megnyitja a portot (megkapja a nevét string-ként - 'LPT1', 'LPT2', ..., 'COM1',COM2', ...), és a struktúrát és megnyitja: _OPENCOMM. Ha a megnyitás sikertelen, akkor visszaadja, hogy miért (a port foglalt vagy nem létezik, illetve segédváltozó kreálása sikertelen).
Kell egy eljárás, ami bezárja a portot: _CLOSECOMM
Kell egy-egy író és olvasó eljárás: _WRITECOMM és _READCOMM. Ezek megkapják, hogy honnan/hova és hány byte-ot olvassanak be vagy írjanak ki, illetve közvetve a struktúrában a kísérleti időt millisecundum-ban: TimeOut mező (hogy ne kelljen minden egyes alkalommal megadni). Vissza boolean, hogy sikerült-e a teljes transfer, illetve ha nem, akkor a méretváltozóban visszadja, hogy ténylegesen mennyi sikerült a megadott idő alatt.
Ezekkel egy egyszerű rutin:
..procedure TForm1.StartClick(Sender:TObject);
....var
......Data:byte;
......Bytes: DWORD;
......lpt2: TCOMM;
....begin
......data:=1;
......if _OPENCOMM('LPT2',lpt2) = COMM_SUCCESS then begin
........lpt2.timeout:=5000;
........bytes:=sizeof(data);
........_WRITECOMM(lpt2,bytes,data);
........_CLOSECOMM(lpt2); end; end;
A megnyitás után beállítja a timeout-ot (most 5000 ms), majd kiír a portra (jelen esetben, ha minden igaz, tartja a byte-ot a kimeneten, mivel ACK nem érkezik), majd lezárja. Gondolom, sejthető, hogy neked akkor nem is kell timer így, mivel a _WRITECOMM-ot kell egy ciklusba tenni, mivel az 5 másodpercenként fog visszatérni, FALSE-szal ugyan, de az nem érdekes.
A fentiek hasonlóan működnek 'COMx' portnév megadásával is, de ott az _OPENCOMM után lehetőség van a paraméterek beállítására, pl. így (most legyen com1 a struktúra neve):
..GETCOMMSTATE(com1,com1.state);
....with com1.state do begin
......baudrate:=9600;
......bytesize:=8;
......parity:=EVENPARITY;
......stopbits:=ONESTOPBIT; end;
....SETCOMMSTATE(com1,com1.state);
Gondolom, kommentálni nem kell, hogy mit jelent a jelenlegi beállítások lekérése, egyes paraméterek átírása, majd beállítás.
A progamozási stílus remélet átlátható, az API-hívások, a belsőeljárás-nevek és a konstansok nagybetűsek, és igyekeztem a lehető legkevesebb utasítást egy sorban hagyni.
[Szerkesztve] -
P.H.
senior tag
Ok, az viszont benn van a munkahelyemen, holnap elhozom. Nem akarok itt és most improvizálni, mert az olvasás, ha minőségi, akkor overlapped kell legyen. Írásnál még elviselhető, hogy addig megáll a program, amíg ki nem írja a teljes adatot, de az olvasás már csak ne működjön úgy, hogy megmondod, hogy mondjuk 1 KB-ot vársz a port-ról, aztán a program 'lefagy', amíg be nem jött a teljes mennyiség. Már ha egyáltalán pontosan tudható, hogy mikor fog jönni.
-
P.H.
senior tag
Kiírja a portra a megadott adatokat, nem kell visszajelzés. Olvasni vissza a readfile-lal lehet, paraméterei megegyeznek a writefile-lal.
Egyszerű példa, hogy mennyire alacsony szintű ez: az első próbálkozásom portokkal az volt, hogy megírtam szinte a fenti kódot, hogy olvasson be a COM1-ről 512 byte-ot. ('COM1', és readfile), fogtam egy soros golyós egeret, menet közben rányomtam a COM1-re, persze semmi driver, észre se vette a Windows, elindítottam a programot. Kb. 5 másodpercig húzkodtam az egeret, aztán kiírta a program, hogy megvan az 512 beolvasott byte. Ennyi.
[mod]: Igazából kiírásnál nem is kell, hogy legyen valami rádugva a port-ra, úgy is sikeres az írás. Csak kinyomja a register-ekbe, mintha OUT-tal írnád.
[Szerkesztve] -
P.H.
senior tag
A writefile írja ki valójában az adatot, de az egész a file-kezelés analógiájára épül (megnyitás-transfer-lezárás), és mivel kizárólagosan nyitja meg a portot (más nem férhet hozzá, amíg nyitva van), legjobb egy egységként kezelni az egész folyamatot.
A writefile amúgy akármilyen hosszú adatot ki tud küldeni egyszerre, nem kell byte-ozni (paraméterei: handle, a kiírandó buffer címe, a buffer hossza, mutató egy DWORD-re (most Moved), illetve egy nil itt most, visszatérési értéke egy boolean. Akkor sikeres a transfer, ha TRUE-val jön vissza, és a megadott DWORD (Moved) értéke megegyezik a paraméterként megadott buffermérettel.)
[mod]: az oldal ''The only step you are required to do is call LoadIODLL somewhere at the beginning of your program. Make sure you do this or you will find yourself faced with all sorts of interesting crashes.''
Az egyetlen lépés, ami szükséges, a LoadIODLL meghívása valahol a program elején. Csináld meg, vagy érdekes/érthetetlen dolgokat fogsz tapasztalni. (Az enyémhez term. nem kell majd. Illetve vagy egy olyan érzésem, hogy az IO.DLL a program teljes ideje alatt fogja a portot. Vagy mindet. De nem ismerem, csak nézegetem az oldalát.)
[Szerkesztve] -
P.H.
senior tag
Szerintem feleslegesen bonyolítod a dolgot ezzel a IO.DLL-lel, meg azzal a szemlélettel, hogy kézzel megadott port-ra írsz. Az összes Windows tudja a fenti kódomat, ami persze működik is, kipróbáltam.
Első ránézésre az IO.DLL link-jére és a kódodra, a LoadIODLL() hívás hiányozik. Az IO.H szerint:
function LoadIODLL: longint; stdcall; external 'io.dll'.
[Szerkesztve] -
P.H.
senior tag
Az API portkezelő általános portkezelésre van kihegyezve, a kódod valahogy így nézne ki legegyszerűbben, NT alapú Windows-okban (9x alatt már a CreateFile első paramétere):
var
..Data: byte;
..Moved: DWORD;
..hPort: THANDLE;
begin
..hport:=createfile('LPT1',
......(GENERIC_READ or GENERIC_WRITE),
......0,
......nil,
......OPEN_EXISTING,
......FILE_ATTRIBUTE_NORMAL,
......0);
..if hport <> INVALID_HANDLE_VALUE then begin
....writefile(hport,data,sizeof(data),moved,nil);
....closehandle(hport); end;
end;
Ez megnyitja az LPT1 portot írásra-olvasásra, kizárólagos használattal. Ha a kapott handle érvényes (= a megnyitás sikeres), akkor a Data változó tartalmát kiírja a portra, majd lezárja a handle-t.
Ehhez csak uses Windows; kell a program vagy unit elejére, bár az alapból ott van. -
P.H.
senior tag
Gondolom vannak pl. IN és OUT utasítások az assembly részben, ezek Windows alatt nem lehetnek benne felhasználói programokban, csak a kernelben és driver-ekben, azaz privilégizált utasítások (privilege instruction, DOS-ban nincs ilyen megkötés, azért ment Pascal-ban). Tehát a programmal semmi gond, biztosan helyes, csak ez az út járhatatlan.
Inkább Windows-on (API) keresztül csináld az LPT-vezérlést.
[Szerkesztve] -
P.H.
senior tag
válasz
Bandus99
#1453
üzenetére
Azért nem fordul le, mert a c1 char típusú, a pred(cs) pedig nem. (affene, már mondatot is ;-vel zárok alapban
)
esetleg így:
type Thn = (he, ke, sz, cs, pe, szo, va);
var
..Ch1: Thn;
begin
..ch1:=pred(cs);
..writeln(ord(ch1));
..readln;
..end.
Azért writeln(ord(ch1)), mert alapban a writeln nem ismeri a Thn típust, így ki lehet íratni az elem index-ét (0-6 között lesz.)
Ez biztos, hogy Delphi-s, nem sima Pascal? Vagy console-os Delphi program lesz? Csak a readln/writeln miatt kérdem.
[Szerkesztve] -
P.H.
senior tag
Csak elferült valamiért dőlt betűsre... Na mindegy.
Még annyi, hogy
- ha tényleg '0.0' formában jönnek az adatok, akkor magyar Windows alatt mindenképp kell a második, try-except-es rész, az StrToFloat-hoz (default a vesszős elválasztás)
- a második kódban term. else if áll, 'else of' helyett.
- a második except-be után akkor is bele fog futni, ha a string végén kevesebb, mint 3 szám van, amellett, hogy ha 1-nél több tizedes-elválasztó van. (a '.1' és a '1.' string-eket nem tudom hirtelen, hogy kezeli-e az StrToFloat helyesen, de talán igen)
[Szerkesztve] -
P.H.
senior tag
Ha mindenképp a string végén van a 3 lebegőpontos, space-szel elválaszva, akkor haladj hátulról.
var
..I,J,Pos: longint;
..Szam: array [1..3] of double;
..Data,Temp: string;
..begin
....data:='szin bela 0,0 0,0 0,0';
....for pos:=3 downto 1 do begin i:=length(data);
......while (i > 1) and (data <> ' ') do dec(i);
......temp:=copy(data,i+1,MAXLONGINT);
......szam[pos]:=strtofloat(temp);
......delete(data,i,MAXLONGINT); end; end;
(ha a copy() vagy a delete() utolsó paramétere MAXLONGINT, akkor a string végéig fog másolni/törölni).
Ha az sem igaz, hogy biztosan space-ekkel vannak elválasztva, akkor
(data <> ' ') helyett mehet (datain ['0'..'9','.',',' ] ), akkor is törölni fogja az elválasztó karaktert.
Arra viszont figyelj, hogy ha StrToFloat-tal konvertálod számmá, akkor angol Windows alatt . (pont) a tizedes-elválasztó, magyar alatt pedig ',' (vessző), különben leáll exception-nal. Érdemes így írni, amit írtam fentebb:
......try..szam[pos]:=strtofloat(temp);
......except for j:=1 to length(temp) do
........if temp[j] = '.' then temp[j]:=','
........else of temp = ',' then temp[j]:='.';
........try szam[pos]:=strtofloat(temp);
........except { ekkor hiba van, 2 pont vagy 2 vessző } end; end;
Ekkor a pontokat lecseréli vesszőre és a vesszőket pontokra, és lemegy, mindegy, milyen nyelvű a Windows. Illetve nem teljesen, mert ha a Vezérlőpontban a tizedes-elválasztót átírták valami másra, akkor így jártak :)
[mod]: csak normális kinézetű lesz lesz lassan...
[Szerkesztve] -
P.H.
senior tag
Legegyszerűbben a pos függvénnyel.
Pl.: i:=pos('amit keresel','amiben keresel').
Longint típust ad vissza, ha ez nulla, akkor a keresett szöveg nincs a sztringben, nemnulla esetén annak első előfordulási pozíciója.
[mod]: a kis- és nagybetűk között különbséget tesz.
[Szerkesztve]
Új hozzászólás Aktív témák
- Fizetős szoftverek ingyen vagy kedvezményesen
- A fociról könnyedén, egy baráti társaságban
- Motoros topic
- Brogyi: CTEK akkumulátor töltő és másolatai
- Alkoholista nevelde
- Hisense LCD és LED TV-k
- Kuponkunyeráló
- Arc Raiders
- Xiaomi 15T - reakció nélkül nincs egyensúly
- Magga: PLEX: multimédia az egész lakásban
- További aktív témák...
- Szép! Lenovo Thinkpad T14s G2 Üzleti "Golyóálló" Laptop 14" -50% i5-1135G7 4Mag 16GB/512GB FHD IPS
- Bomba ár! Lenovo ThinkPad Yoga 370 - i5-G7 I 8GB I 256SSD I 13,3" FHD Touch I W11 I Cam I Gari!
- Bomba ár! Lenovo ThinkPad Yoga 260 - i5-G6 I 8GB I 256SSD I 12,5" Touch I W11 I Cam I Gari!
- HP EliteBook 850 G8 Fémházas Tartós Laptop 15,6" -65% i7-1165G7 16/512 Iris Xe FHD
- Bomba ár! Lenovo ThinkPad X390: i5-G8 I 16GB I 256-1TSSD I 13,3" FHD Touch I HDMI I Cam I W11 I Gar
- Apple Magic Mouse A3204 (USB-C)
- BESZÁMÍTÁS! MSI B450M R5 5500 16GB DDR4 512GB SSD RX 6650XT 8GB RAMPAGE Shiva ADATA 600W
- Gamer PC-Számítógép! Csere-Beszámítás! R5 8600G / 6700XT 12GB / 16GB DDR5 / 512 SSD + 2TB HDD!
- Xiaomi Redmi 14C / 4/128GB / Kártyafüggetlen / 12Hó Garancia
- GYÖNYÖRŰ iPhone 13 mini 128GB Midnight -1 ÉV GARANCIA - Kártyafüggetlen, MS4076
Állásajánlatok
Cég: PCMENTOR SZERVIZ KFT.
Város: Budapest
Cég: Laptopszaki Kft.
Város: Budapest
)


