/* Questo programma consente una comunicazione half-duplex asincrona tra due entit… dotate di interfaccia seriale RS 232 pilotata da UART NATIONAL 8250. Viene usato un controllo diretto dei registri di tale integrato. L'algoritmo di base del programma e': inizializza porta con parametri di velocita', parita' ecc. do controlla lo stato della linea e rileva eventuale errore se non c'e' errore se Š arrivato un char, leggilo e presentalo a video se hai premuto un tasto, trasmetti il char corrispondente while not errore */ #include #include #include #define ESC 27 unsigned int RBR,THR,DLL,DLM,IER,IIR,LCR,MCR,LSR,MSR; //-------------------------------------------------------------- void inizializza(void) /* per scegliere la porta (com1, com2 ..) e inizializzare la UART relativa */ { unsigned int port; clrscr(); printf("N. porta ? (1 per com1, 2 per com2) "); scanf("%d",&port); if (port==1) port=0x03F8; // indirizzo base di com1 else port=0x02F8; // indirizzo base di com2 printf("\n"); RBR=port; // contiene il dato ricevuto - sola lettura // bit 7 del registro controllo linea (LCR) = 0 THR=port; // contiene il char da trasmettere dopo quello corrente // (solo scrittura). Bit 7 del registro controllo linea (LCR)=0 /* Come si vede il buffer (1 byte) di trasmissione coincide con quello di ricezione, quindi con questa UART 8250 non potremo avere comunicazioni in full-duplex */ DLL=port; // Š quello al quale bisogna inviare il byte basso della // costante di tempo individuato in base alla tabella // baud-rate,costante di tempo // bit 7 del registro controllo linea (LCR) = 1 // DLL viene anche chiamato LSB DLM=port+1; // Š quello a cui inviare il byte alto della tabella // di cui sopra. DLM viene anche chiamato MSB. // Facciamo un esempio. La tabella, per 1200 bps Š // bps MSB LSB // 1200 00H 60H // 4800 00H 18H // Se voglio impostare a 1200 bps su com1 devo: // 1) mettere a 1 il bit 7 di LCR, quindi porre 80H // all'indirizzo di LCR=3FBH (80H=10000000 base 2) // 2) inserire 60H in LSB (indirizzo 3F8H) // 3) inserire 00H in MSB (indirizzo 3F9H) IER=port+1; // con il bit 7 di LCR=0, Š il registro di abilitazione // interruzioni. Di solito si impostano i suoi bit a 0 // per disabilitare i 4 tipi di interruzioni di comunicazione. IIR=port+2; // registro di identificazione interruzione. Non viene // usato in questo esempio LCR=port+3; // Controllo della linea. Questo Š il registro che serve per // impostare velocit…, parit… ecc. // vedere significato dei bit su qualche libro. MCR=port+4; // Controllo modem. I bit 0 e 1 (i due bit meno signif.) // devono valere 1 se si vogliono attivare rispettivamente // DTR e RTS: quindi mettiamo il registro a 03H, anche se // non c'Š il modem. LSR=port+5; // Stato della linea: segnala la presenza di un dato // nel registro di ricezione (RBR) o gli eventuali // errori riscontrati o la disponibilit… a trasmettere. // La disponibilit… a trasmettere Š data dal bit di posto 5, // che vale 1 se la linea Š libera (buffer di trasm. vuoto) // cioŠ il dato precedente da trasmettere Š stato trasmesso // Eventuali errori sono nei quattro bit di posiz 4,3,2,1 . MSR=port+6; // stato del modem. Qui non viene usato outportb(LCR,0x80); /* comincio a impostare la velocit…: 1^ passo*/ outportb(DLL,0x18); /* imp. velocit…: 2^ passo*/ outportb(DLM,0x00); /* imp. velocit…: 3^ passo*/ outportb(LCR,0x03); /* parametri N81: nessuna parit…, 8 bit, 1 bit di stop*/ outportb(MCR,0x03); // attiva DTR e RTS /* outportb(MCR,0x13); // attiva DTR e RTS e cortocircuita la UART*/ outportb(IER,0); /* disattiva tutte le interruzioni */ } //------------------------------------------------ fine di inizializza void ricevi (void) { unsigned char dato; dato=inportb(RBR); putch(dato); if (dato==0x0D) // se Š un chr 13, cioŠ INVIO putch(0x0A); // dai un Line Feed } unsigned char trasmetti(void) { unsigned char dato; dato=getch(); // putchar(dato); if (dato==ESC) return(1); while (! (inportb(LSR)&0x20)) ; // mentre la linea non Š libera aspetto; // cioŠ aspetto finch‚ non si libera il buffer di trasmisione outportb(THR,(unsigned char) dato); return 0; } main() { unsigned char stato, flag=0; inizializza(); while (! flag) { stato=inportb(LSR); if ((stato & 0x1E) !=0) /* qualche errore in ricezione */ { printf("Errore di ricezione in LSR=%X esadec.\n",stato); flag=1; } else if ((stato & 0x01) != 0) /* ricevuto un dato coretto */ ricevi(); else if (kbhit()) flag=trasmetti(); } // while return 0; } // main