- Xiaomi 13T és 13T Pro - nincs tétlenkedés
- Szívós, szép és kitartó az új OnePlus óra
- Xiaomi 14 - párátlanul jó lehetne
- Samsung Galaxy S23 Ultra - non plus ultra
- Google Pixel topik
- Milyen okostelefont vegyek?
- Netfone
- Honor 200 Pro - mobilportré
- Motorola Edge 50 Neo - az egyensúly gyengesége
- Realme 9 Pro+ - szükséges plusz?
Ú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
Hirdetés
- Azonnali VGA-s kérdések órája
- EA Sports WRC '23
- Autós topik
- f(x)=exp(x): A laposföld elmebaj: Vissza a jövőbe!
- Norvégia átmenetileg betiltja az áramigényes kriptobányászatot
- sziku69: Fűzzük össze a szavakat :)
- Allegro vélemények - tapasztalatok
- Xbox tulajok OFF topicja
- Milyen autót vegyek?
- Kínai és egyéb olcsó órák topikja
- További aktív témák...
- Easun iSolar SMW 11kW Twin Hibrid inverter // Dupla MPPT // BMS // WiFi
- GAMER PC : RYZEN 7 5700G/// 32 GB DDR4 /// RX 6700 XT 12 GB /// 512 GB NVME
- GAMER MSI LAPTOP : 15,6" 144 HZ /// i5 12450H /// 16GB DDR4/// RTX 4050 6GB/// 1TB NVME
- Manfrotto 055 magnézium fotó-videófej Q5 gyorskioldóval
- Sony ECM-W2BT
- BESZÁMÍTÁS! Gigabyte B550M R7 5700X 32GB DDR4 512GB SSD RX 7700 XT 12GB DeepCool CC560 Seasonic 650W
- ÚJ Apple Macbook Air 15,3 M4 10C CPU/10C GPU/16GB/256GB - Ezüst -(2025) - 3 év gari - MAGYAR
- Telefon felvásárlás!! iPhone 15/iPhone 15 Plus/iPhone 15 Pro/iPhone 15 Pro Max
- Samsung Galaxy A12 64GB, Kártyafüggetlen, 1 Év Garanciával
- Steam, EA, Ubisoft és GoG játékkulcsok, illetve Game Pass kedvező áron, egyenesen a kiadóktól!
Állásajánlatok
Cég: Promenade Publishing House Kft.
Város: Budapest
Cég: PC Trade Systems Kft.
Város: Szeged