Referát z předmětu 36PZ

Úloha A: RS232

Skupina D: Duben


Zadání:
Sestavte program pro komunikaci po sériové lince a to přímým programováním registrů asynchronního obvodu UART 8250 dle následujících pokynů:

Poznámka: Programy nejprve napište bez použití přerušení, až poté s využitím služeb přerušovacího systému.

Vypracování:
Program Serial;

uses DOS,CRT;

const
{------------------- COM ports in PC -------------------}

 COM1= $3f8;
 COM2= $2f8;
 
Intr: Integer = $0b;
{------------------- 8250 registers --------------------} RBR= 0; { received data - read only - if DLAB=0 } THR= 0; { transmit data - write only - if DLAB=0 } DLL= 0; { baud generator (LSB) - if DLAB=1 } DLM= 1; { baud generator (MSB) - if DLAB=1 } IER= 1; { interrupt enable - r/w } IIR= 2; { interrupt identification - read only } LCR= 3; { line control register - r/w } MCR= 4; { modem control register - r/w } LSR= 5; { line status - read only } MSR= 6; { modem status register - read only } {------------------- 8250 register bits ----------------} IER_RX= 1; { intr on received data - priority 2 } IER_TX= 2; { intr on data transmitted - priority 3 } IER_ERR= 4; { intr on receive error (see LSR) - priority 1 } IER_MS= 8; { intr on modem sts change (see MSR) - priority 4 } IIR_PEND= 1; { active intr request } IIR_MASK= 6; { source id mask } IIR_MS= 0; { modem sts change } IIR_TX= 2; { data transmitted } IIR_RX= 4; { data received } IIR_ERR= 6; { receive error } LCR_5BIT= 0; { byte length codes } LCR_6BIT= 1; LCR_7BIT= 2; LCR_8BIT= 3; LCR_2STOP= 4; { two stop bits } LCR_PTYEN= 8; { parity enabled } LCR_EVPTY= $10; { even parity } LCR_FIXPTY= $20; { fixed parity } LCR_INTREN= $40; { interrupt enabled } LCR_DLAB= $80; { baud gen. access enabled } MCR_DTR= 1; { DTR modem signal } MCR_RTS= 2; { RTS modem signal } MCR_OUT1= 4; { user signal } MCR_OUT2= 8; { user signal - wired to 3 state IRQ driver } MCR_LOOP= $10; { test loop } LSR_RX= 1; { data received } LSR_OR= 2; { overrun - read once } LSR_PR= 4; { parity error - read once } LSR_FR= 8; { frame error - read once } LSR_BT= $10; { break error - read once } LSR_BF= $20; { tx buffer empty } LSR_TX= $40; { serializer empty } MSR_CSR_CH= 1; { CSR has changed - read once } MSR_DSR_CH= 2; { DSR has changed - read once } MSR_RI_END= 4; { RI ended - read once } MSR_RLSD_CH= 8; { RLSD changed - read once } MSR_CSR= $10; MSR_DSR= $20; MSR_RI= $40; MSR_RLSD= $80; DLM_300= 1; { 300 Baud } DLM_HIGH= 0; { more than 300 Baud } DLL_300= $80; { 300 Baud } DLL_600= $c0; { 600 Baud } DLL_1200= $60; { 1200 Baud } DLL_2400= $30; { 2400 Baud } DLL_4800= $18; { 4800 Baud } DLL_9600= $0c; { 9600 Baud } DLL_19200= $06; { 19200 Baud } {-------------------------------------------------------------------} type word=0..65535; parstr=string[255]; {-------------------------------------------------------------------} var com: word; loop: boolean; c: char; argv1, argv2: parstr;
org_int: pointer; xp, yp ,xv ,yv: byte;
{-------------------------------------------------------------------}
procedure init_com (portaddr: word; loop: boolean); begin port [portaddr+LCR]:= LCR_DLAB; { path to baud gen on } port [portaddr+DLM]:= DLM_HIGH; { more than 300 Baud } port [portaddr+DLL]:= DLL_1200; { 1200 Baud } port [portaddr+LCR]:= LCR_8BIT; { baud gen off, 8 bit, no par } port [portaddr+IER]:= 0; { no interrupt } if loop then port [portaddr+MCR]:= MCR_DTR or MCR_LOOP else port [portaddr+MCR]:= MCR_DTR;
port[com + IIR]:= $07; { 1 byte length buffer and its cleaning } port[com + MCR]:= $0b; { OUT2 to 1, enable int } if intr = $0c then { mask int } begin port[$21]:= port[$21] and $EF end else begin port[$21]:= port[$21] and $F7; end; port[com + IER]:= $01; { int on received character }
end;
{-------------------------------------------------------------------} function rx_rdy (portaddr: word): boolean; begin rx_rdy:=((port[portaddr+LSR] and LSR_RX) <>0); end; {-------------------------------------------------------------------} function tx_rdy (portaddr: word): boolean; begin tx_rdy:=((port [portaddr+LSR] and LSR_BF) <>0); end; {-------------------------------------------------------------------}
function rx_get (portaddr: word): char; begin rx_get:= chr(port [portaddr+RBR]); end;
{-------------------------------------------------------------------}
procedure tx_put (portaddr: word; c : char); begin port [portaddr+THR]:= ord (c); end;
{-------------------------------------------------------------------} function hx (t: parstr): word; var ix: integer; w: word; ok: boolean; begin w:=0; ok:=true; for ix:=1 to length(t) do if ok then begin if t[ix] in ['0'..'9'] then w:=16*w+ord(t[ix])-ord('0') else if t[ix] in ['A'..'F'] then w:=16*w+ord(t[ix])-ord('A')+10 else if t[ix] in ['a'..'f'] then w:=16*w+ord(t[ix])-ord('a')+10 else ok:=false; if w>$3FF then ok:=false; end; if ok then hx:=w else hx:=0; end; {-------------------------------------------------------------------}
procedure rx_int; interrupt; begin if (rx_rdy(com)) then begin window(1, 13, 80, 25); gotoxy(xp,yp); c:= rx_get(com); write(c); if c = chr(13) then writeln; xp:= wherex; yp:= wherey; end; port[$20]:= 20; end;
{-------------------------------------------------------------------} begin com:=COM1; loop:=false; c:='a'; argv1:=ParamStr(1); argv2:=ParamStr(2); case ParamCount of 0: begin writeln ('Usage: serial [l]'); writeln ('COM1 is at 3F8, COM2 is at 2F8.'); halt; end; 1: begin com:=hx(argv1); if com=0 then begin writeln ('Port address must be hex number in the range 10..3FF'); halt; end; end; 2: begin com:=hx(argv1); if com=0 then begin writeln ('Port address must be hex number in the range 10..3FF'); halt; end; loop:=true; end; end; init_com (com,loop);
getIntVec($0B, org_int); setIntVec($0B, addr(rx_int));
while (ord(c)<>0) do begin if (rx_rdy(com)) then write (rx_get(com)); if keypressed then if tx_rdy(com) then begin c:=readkey; tx_put (com,c); end; end; c:=readkey;
setIntVec($0B, org_int);
end.
Závěr:
V této laboratorní úloze se nám povedlo bez problémů realizovat komunikace mezi dvěma počítači spojenými přes rozhraní RS232.

Použité zdroje: