Keresés

Hirdetés

Új hozzászólás Aktív témák

  • P.H.

    senior tag

    válasz csewe #1459 üzenetére

    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]

    Arguing on the Internet is like running in the Special Olympics. Even if you win, you are still ... ˙˙˙ Real Eyes Realize Real Lies ˙˙˙

  • Tele von Zsinór

    őstag

    válasz csewe #1461 üzenetére

    Szerintem ez lesz neked a tökéletes: [link]
    ezen az oldalon szépen le is van írva, hogy lehet használni.

  • P.H.

    senior tag

    válasz csewe #1461 üzenetére

    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.

    Arguing on the Internet is like running in the Special Olympics. Even if you win, you are still ... ˙˙˙ Real Eyes Realize Real Lies ˙˙˙

  • P.H.

    senior tag

    válasz csewe #1466 üzenetére

    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]

    Arguing on the Internet is like running in the Special Olympics. Even if you win, you are still ... ˙˙˙ Real Eyes Realize Real Lies ˙˙˙

  • P.H.

    senior tag

    válasz csewe #1468 üzenetére

    A createfile első paraméterét 'LPT1'-ról átírod 'LPT2'-re.

    Arguing on the Internet is like running in the Special Olympics. Even if you win, you are still ... ˙˙˙ Real Eyes Realize Real Lies ˙˙˙

  • P.H.

    senior tag

    válasz csewe #1470 üzenetére

    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]

    Arguing on the Internet is like running in the Special Olympics. Even if you win, you are still ... ˙˙˙ Real Eyes Realize Real Lies ˙˙˙

  • P.H.

    senior tag

    válasz csewe #1473 üzenetére

    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]

    Arguing on the Internet is like running in the Special Olympics. Even if you win, you are still ... ˙˙˙ Real Eyes Realize Real Lies ˙˙˙

  • P.H.

    senior tag

    válasz csewe #1475 üzenetére

    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.

    Arguing on the Internet is like running in the Special Olympics. Even if you win, you are still ... ˙˙˙ Real Eyes Realize Real Lies ˙˙˙

  • P.H.

    senior tag

    válasz csewe #1478 üzenetére

    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]

    Arguing on the Internet is like running in the Special Olympics. Even if you win, you are still ... ˙˙˙ Real Eyes Realize Real Lies ˙˙˙

  • _AnTi_

    tag

    válasz csewe #1658 üzenetére

    Szia!

    Mindkét komponensnél a font.size-al tudod módosítani a betűméretet. Pl.:

    memo1.font.size:=12;

    Az egyetlen gond ezzel a két komponenssel, hogy ha változtatod a betűméretet, akkor az összes benne lévő szöveg mérete módosul.

    Nézz körül a richedit környékén, ha kicsit többre vágysz!

    Szép vagyok és okos, ügyes és aranyos...

Új hozzászólás Aktív témák