Istituto Professionale di Stato per l`Industria e l`Artigianato
Transcript
Istituto Professionale di Stato per l`Industria e l`Artigianato
Istituto Professionale di Stato per l'Industria e l'Artigianato MORETTO Via Luigi Apollonio, 21 BRESCIA Progetto finalizzato per Progettazione e costruzione di schede per interfacciamento tra PC e circuiti esterni tramite LX833 Realizzazione Celiento Giuseppe Chiodoni Fabio Della classe 5AI a.s. 1998-99 Corso per Tecnici delle Industrie Elettriche ed Elettroniche 1 PROGETTAZIONE E COSTRUZIONE DI SCHEDE PER L’INTERFACCIAMENTO TRA PC E CIRCUITI ESTERNI TRAMITE LX833 ........................................................................................................................................ 3 SCOPO DEL PROGETTO............................................................................................................................................ 3 PROGETTI DI INTERFACCE .............................................................................................................................. 19 Interfaccia display a sette segmenti decodificati ................................................................................................... 20 Interfaccia Led e Dip Switch .................................................................................................................................. 21 CONTROLLO E SINCRONIZZAZIONE DELLE VARIE INTERFACCE .............................................................................. 22 Assegnazione degli indirizzi ................................................................................................................................... 22 QUARZO 4MHZ .......................................................................................................................................................... 30 Caratteristiche Generali Di Un Convertitore Analogico-Digitale ......................................................................... 32 LA CONVERSIONE DIGITALE-ANALOGICA E ANALOGICA-DIGITALE .................................................. 34 CONVERTITORI ANALOGICI DIGITALI ADC.................................................................................................. 35 ADC AD APPROSSIMAZIONI SUCCESSIVE.................................................................................................... 36 CONVERTITORE ADC 0808..................................................................................................................................... 37 LCD LM018 HITACHI............................................................................................................................................ 38 SOFTWARE DI GESTIONE .................................................................................................................................. 43 2 PROGETTAZIONE E COSTRUZIONE DI SCHEDE PER L’INTERFACCIAMENTO TRA PC E CIRCUITI ESTERNI TRAMITE LX833 Scopo del progetto Lo scopo di questo progetto è quello di poter comandare, attraverso il linguaggio Pascal, circuiti esterni al computer utilizzando la scheda LX.833, progettata dalla rivista “Nuova Elettronica”, che abbiamo corredato con il PPI 82C55A costruito dalla Harris Semiconductor in tecnologia C-MOS. SCHEMA A BLOCCHI PC LX.833 INTERFACCE LX. 833 La scheda è predisposta per poter essere adattata alle esigenze che il consumatore ha, cioè è costituita da uno stampato detto “Mille fori” dov’è possibile assemblare altri componenti. 3 LX.833 è una scheda PC/XT, quindi possiede un BUS a 8 BIT per l’entrata e l’uscita dei dati; con una denominazione che va da: D0 fino a D7. Lo stampato è predisposto con i seguenti integrati : SN.74LS244, EP.833, e SN.74L245. L’SN.74LS244 funge da Buffer per i segnali provenienti dal BUS degli indirizzi in modo da separare le linee del BUS della scheda madre da quelle connesse all’82C55A. Con questo dispositivo anche se causassimo dei cortocircuiti sulle linee, ad esempio con collegamenti o saldature errati, questi non si ripercuoterebbero sul BUS principale e, pertanto, il computer continuerebbe a funzionare senza anomalie. L’EP.833 è una memoria PROM ( cioè una volta programmata non è più riprogrammabile) utile per decodificare gli indirizzi. Sui piedini d’uscita è collocato un piccolo connettore (JUMPER) che permette di selezionare quattro diversi gruppi di indirizzi da assegnare alla scheda; ognuno di questi gruppi è composto da otto indirizzi, per cui avremo a disposizione 4 * 8 = 32 indirizzi. Selezionando il JUMPER la scheda risponde nel campo di indirizzi che vanno da $300 a $307 (valori in esadecimale); selezionando su B vanno da $308 a $30F, con il C da $310 a $317 e su D da $318 a $31F. L’SN.74LS245 è un buffer di dati bidirezionali che viene utilizzato per trasferire gli 8 BIT dei dati dalla scheda al BUS del computer e viceversa. Segnali presenti sulla scheda ED0-ED7 Rappresentano i dati del BUS (D0-D7) bufferizzati a valle dell’integrato SN.74LS245. EA0-EA2 Sono la versione bufferizzata degli indirizzi bassi, A0-A2, a valle dell’integrato SN.74LS244. ERD E’ la versione bufferizzata del segnale IOR a valle dell’integrato SN.74LS244. EWR E’ la versione bufferizzata del segnale IOW a valle dell’integrato SN.74LS244. 4 S L O T NUOVA ELETTRONICA LX833 LOGICA DI CONTROLLO P C INTERFACCIA SPERIMENTALE PER PC/XT/AT U1 A30 B14 2 4 6 8 11 13 15 17 A1 IOR I1 I3 I2 B13 A29 A31 IOW A2 A0 1 19 1A1 1A2 1A3 1A4 2A1 2A2 2A3 2A4 18 16 14 12 9 7 5 3 1Y1 1Y2 1Y3 1Y4 2Y1 2Y2 2Y3 2Y4 EA1 ERD U1 U3 U2 EWR EA2 EA0 1G 2G ECS VCC 74LS244 LOGICA DI SELEZIONE R3 R2 R1 10K 10K R4 10K 10K U3 A28 A27 A26 A25 A24 A23 A22 A11 1 2 3 4 5 6 7 8 9 11 A3 A4 A5 A6 A7 A8 A9 AEN I0 I1 I2 I3 I4 I5 I6 I7 I8 I9 12 13 14 15 16 17 18 19 F0 F1 F2 F3 F4 F5 F6 F7 CAMPO DI SELEZIONE JP1-ON $300-$307 JP1 JP2 JP3 JP4 16V8 EP.833/1 JP2-ON $308-$30F JP3-ON $310-$317 JP4-ON $318-$31F BUFFER DATI BIDIREZIONALE U2 A9 A8 A7 A6 A5 A4 A3 A2 2 3 4 5 6 7 8 9 D0 D1 D2 D3 D4 D5 D6 D7 19 1 A1 A2 A3 A4 A5 A6 A7 A8 18 17 16 15 14 13 12 11 B1 B2 B3 B4 B5 B6 B7 B8 ED0 ED1 ED2 ED3 ED4 ED5 ED6 ED7 G DIR 74LS245 B1 +5V B31 C1 B7 -12V B9 +12V C2 100nF 10uF GND C3 C4 100nF 100nF C1, C2, C3 vanno connessi sui pin di alimentazione di U1, U2, U3 B3 +5V B29 5 8255A Il circuito integrato INTEL 82C55A è un dispositivo generale di I/O programmabile, progettato per l'uso con i microprocessori della famiglia INTEL. E’ dotato di 24 linee: - 8 appartenenti al Port A; - 8 appartenenti al Port B; - 8 appartenenti al Port C. le 8 linee del port A e del Port b possono essere programmate per funzionare o da ingressi o da uscite in 4 possibili modi: - Port A ingresso e Port B uscita; - Port A uscita e Port B uscita; - Port A ingresso e Port B ingresso; - Port A uscita e Port B ingresso. Le linne del Port C possono essere suddivise in due gruppi da 4 bit ciascuno. Ogni gruppo può essere programmabile o da ingresso o da uscita nei modi seguenti: - da PC0 a PC3 uscita e da PC4 a Pc7 ingresso; - da PC0 a PC3 ingresso e da PC4 a Pc7 uscita; - da PC0 a PC3 ingresso e da PC4 a Pc7 ingresso; - da PC0 a PC3 uscita e da PC4 a Pc7 uscita. Complessivamente nel Modo 0 si hanno 16 modi diversi di programmazione dell’82C55A. Descrizione delle funzioni svolte dall'82C55A 6 Generalità L'82C55A è un'interfaccia per I/O programmabile (PPI = Programmable Peripheral Interface) atta a collegare una generica periferica al Bus della CPU. La configurazione operativa dell'82C55A è controllabile da software, in modo da rendere inutile l'uso di circuiti logici esterni per il normale interfacciamento. Buffer per il Bus Dati Viene utilizzato un buffer three-state bidirezionale ad otto bit per interfacciare l'82C55A al Bus Dati del sistema. I dati sono trasmessi o ricevuti dal buffer sotto il controllo delle istruzioni di ingresso o di uscita inviate dalla CPU. Anche le parole di controllo e le informazioni di stato vengono trasferite attraverso questo buffer. 7 Circuiti logici di controllo e di lettura/scrittura La funzione di questo blocco è di gestire tutti i trasferimenti interni ed esterni sia dei dati che delle parole di controllo di stato. Riceve comandi dal Bus Indirizzi e da quello di controllo della CPU e controlla entrambi i gruppi di linee. (CS ) Chip Select. La presenza di un livello basso a questo piedino di ingresso abilita le comunicazioni tra l'interfaccia e la CPU. (RD) Read. La presenza di un livello basso a questo piedino di ingresso abilita l'8255A ad inviare dati o informazioni di stato alla CPU tramite il Bus Dati. In altre parole la CPU è abilitata a leggere dall'82C55A. WR Write. La presenza di un livello basso a questo piedino di ingresso abilita la CPU a scrivere dati o parole di controllo nell'82C55A. (A0 e A1) Port Select 0 e Port Select 1. Questi segnali di ingresso, assieme alle precedenti linee RD e WR , permettono di selezionare una delle tre porte di accesso ai rispettivi registri di controllo. Normalmente queste due linee sono connesse ai due bit meno significativi del Bus degli indirizzi (appunto A0 e A1). (RESET) Reset. La presenza di un livello alto a questo piedino azzera il registro di controllo e tutti i port (A, B e C) vengono settati come ingressi. Controllo del Gruppo A e del Gruppo B 8 La configurazione operativa di ciascun port è programmabile da software. Per far ciò la CPU invia una parola di controllo all'82C55A. La parola di controllo contiene appunto le informazioni atte a definire tale configurazione, quali ad esempio il modo operativo,il set di bit, etc.. Ciascun blocco di controllo (del Gruppo A e del Gruppo B) riceve comandi dal circuito di controllo e di lettura/scrittura o direttamente parole di controllo tramite il bus dati interno, ed emette i segnali di controllo per il port ad esso associato. Del Gruppo A fanno parte il Port A e la parte alta del Port C (linee da C7 a C4), mentre al Gruppo B appartengono il Port B e la parte bassa del Port C (linee da C3 a C0). Il registro di controllo può essere solo scritto. Non sono ammesse operazioni di lettura su tale registro. PORT A, B E C L'integrato 82C55A contiene al suo interno tre port ad otto bit (A, B e C). Tutti e tre possono essere configurati da programma in vari modi operativi, ma ciascuno ha delle caratteristiche proprie che lo differenziano dagli altri. Port A. È un port costituito da un buffer bidirezionale ad 8 bit dotato di memoria (latch) e di un registro di memorizzazione d'ingresso. Port B. È un port costituito da un buffer d'uscita ad 8 bit dotato di memoria e da un registro di memorizzazione d'ingresso bufferizzato ad 8 bit. Port C. E un port costituito da un buffer d'uscita ad 8 bit dotato di memoria e da un buffer d'ingresso ad 8 bit (senza memorizzazione). Questo port a sua volta può essere suddiviso in due port a 4 bit. Ciascuno di questi port di dimensioni contenute contiene un registro di memorizzazione a 4 bit che può essere utilizzato per i segnali di controllo d'uscita e d'ingresso assieme ai port A e B. Operazioni fondamentali dell'8255 A1 A0 RD WR CS 9 Operazione d'ingresso (READ) 0 0 1 0 1 0 0 0 0 1 1 1 0 0 0 Port A Port B Port C Data Bus Data Bus Data Bus Operazione d'uscita (WRITE) 0 0 1 1 0 1 0 1 1 1 1 1 0 0 0 0 0 0 0 0 Data Bus Port A Data Bus Port B Data Bus Port C Data Bus registro di controllo Funzione di disabilitazione x 1 x x 1 x x 0 1 x 1 1 1 0 0 Data Bus in three-state Condizione illegittima Data Bus in three-state Descrizione delle operazioni svolte dall'8255A Selezione del modo operativo Possono essere selezionati da software tre diversi modi operativi: Modo O - ingresso/uscita normale Modo 1 - ingresso/uscita controllato da strobe Modo 2 - bus bidirezionale Quando il segnale d'ingresso di reset assume un valore alto tutti i Port vengono selezionati come ingressi (cioè tutte le 24 linee si portano in uno stato di alta impedenza). Quando il comando di reset termina l'82C55A resta in tale condizione senza che siano richiesti altri comandi. Durante l'esecuzione del programma possono essere utilizzati tutti i modi operativi disponibili mediante l'invio dalla CPU di una sola istruzione contenente la parola 10 di controllo appropriata. Ciò permette di utilizzare un solo 82C55A per gestire contemporaneamente diversi tipi di periferiche. I modi operativi dei Port A e B possono essere definiti in maniera indipendente l'uno dall'altro, mentre il Port C viene diviso in due parti in funzione di quanto specificato per gli altri due port. Tutti i registri d'uscita, inclusi i flip-flop di stato, vengono resettati ogni volta che viene cambiato modo operativo. Le definizioni di modo dei due port possono essere combinate tra di loro in modo da adattare l'interfaccia alle varie periferiche. Ad esempio il Gruppo B può essere programmato in modo Out per controllare la chiusura di una serie di tasti o visualizzare su display dei risultati, mentre il Gruppo A può essere programmato in modo In per gestire una tastiera o un lettore di schede o qualsiasi altro dispositivo gestibile mediante interrupt. Le definizioni di modo e le loro combinazioni possibili possono sembrare all'inizio un'inutile complicazione e risultare difficili da comprendere, ma dopo il primo impatto se ne comprenderà la versatilità d'uso offerta da queste scelte e risulteranno alla fine di facile apprendimento. La progettazione dell'82C55A ha tenuto conto di vari fattori, quali l'efficienza della disposizione dei componenti sulla scheda di supporto e la facile connessione dei segnali di controllo tra CPU e interfaccia, ed ha cercato di offrire la massima versatilità di funzioni svolte sfruttando tutti i piedini disponibili dell'integrato. Possibilità di set/reset di un singolo bit Con una sola istruzione di uscita (OUT) della CPU può essere settato (posto ad 1) o resettato (posto a O) un singolo bit tra gli 8 disponibili sul Port C. Questa caratteristica permette di semplificare le subroutine di controllo di trasferimento dei dati. Quando le linee del Port C vengono usate come linee di controllo dei trasferimenti dei Port A e B, queste possono essere modificate come se il Port C fosse un normale Port d'uscita. Controllo dell'interrupt Quando l'82C55A è programmato per funzionare in modo 1 o modo 2, i segnali di controllo possono essere utilizzati direttamente per generare richieste di interrupt alla CPU. Quando 11 ciò avviene, i segnali di richiesta di interrupt generati dal Port C possono essere abilitati o disabilitati ponendo a livello alto o basso il flip-flop INTE associato, utilizzando l'istruzione set/reset di un singolo bit del Port C. Con tali istruzioni il programmatore può permettere o negare ad un dispositivo di I/O la possibilità di lanciare interrupt. Se viene posto ad 1 il contenuto di un dato bit del flip-flop INTE, l'interrupt del dispositivo relativo viene abilitato, mentre se viene posto a 0 l'interrupt risulta disabilitato. NOTA: tutti i flip-flop di mascheramento vengono automaticamente resettati quando viene selezionato un modo o se il dispositivo viene resettato. Modi operativi Modo 0 (ingresso uscita normale). Questa configurazione operativa permette di instaurare su tutti i 3 Port le normali funzioni di lettura o scrittura di un dato. Non è richiesto alcun segnale di controllo tipo handshake in quanto i dati vengono semplicementi letti o scritti nel Port relativo. Caratteristiche del Modo 0: - due Port ad 8 bit e due Port a 4 bit; - qualsiasi Port può essere definito come ingresso o come uscita; - le uscite sono memorizzate; - gli ingressi non sono memorizzati; - sono possibili 16 diverse combinazioni di I/O CONFIGURAZIONI POSSIBILI IN MODO 0 A A B B D3 D2 D1 D0 Gruppo Gruppo Gruppo Gruppo A A B B Port A Port C Port B Port C 12 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 uscita uscita uscita uscita uscita uscita uscita uscita ingresso ingresso ingresso ingresso ingresso ingresso ingresso ingresso PC7-PC4 uscita uscita uscita uscita ingresso ingresso ingresso ingresso uscita uscita uscita uscita ingresso ingresso ingresso ingresso uscita uscita ingresso ingresso uscita uscita ingresso ingresso uscita uscita ingresso ingresso uscita uscita ingresso ingresso PC3-PC0 uscita ingresso uscita ingresso uscita ingresso uscita ingresso uscita ingresso uscita ingresso uscita ingresso uscita ingresso Modo 1 (ingresso/uscita mediante strobe). Questo tipo di configurazione permette di trasferire dati da un Port mediante il controllo di segnali di handshake. Nel modo 1 il Port A e Port B usano le linee del Port C per generare o acquisire questi controlli. Caratteristiche del Modo 1: - due gruppi di trasferimento (Gruppo A e Gruppo B); - ciascun gruppo contiene un Port di dati ad 8 bit ed un Port di controllo dei dati da 4 bit; - i due Port di dati ad 8 bit possono essere sia d'ingresso che d'uscita. Sia le uscite che gli ingressi sono memorizzate; - i due Port a 4 bit vengono usati per emettere i segnali di controllo e fornire lo stato del dispositivo alle periferiche collegate ai due Port ad 8 bit. Definizione dei caratteri di controllo per l'ingresso di un dato. STB (ingresso di strobe). Se questo ingresso si trova a livello basso i dati in ingresso al port relativo vengono acquisiti e memorizzati nell'82C55A. IBF (flip-flop segnalazione buffer di ingresso pieno). Se questa uscita si porta a livello alto 13 vuol dire che dati presenti agli ingressi del Port sono gia stati acquisiti e quindi memorizzati; in altre parole viene emesso un segnale di “ricevuto” (acknowledge). Il segnale IBF viene posto ad 1 dal fronte di discesa dell'ingresso di strobe STB, mentre viene resettato dal fronte d'onda di salita del segnale d'ingresso RD . INTR (richiesta di interrupt). La presenza di un livello alto su questa uscita puo' essere usata per generare un interrupt alla CPU, in quanto indica che il dispositivo d'ingresso sta richiedendo l'intervento. Il segnale INTR viene posto ad 1 se sia il segnale STB che IBF ed INTE sono contemporaneamente a livello alto. Viene invece resettato dal fronte d'onda di discesa del segnale RD . Questo modo di funzionamento permette ad un generica periferica di ingresso di richiedere alla CPU di acquisirne un dato semplicemente rendendolo disponibile al Port relativo e generando un segnale di strobe. Definizione dei segnali di controllo per l'uscita di un dato OBF flip flop segnalazione buffer d'uscita pieno). Il segnale d'uscita OBF si porta a livello basso per indicare che la CPU ha emesso (scritto) il dato verso il port specificato. Questo segnale viene posto a 0 dal fronte d'onda di salita dell'ingresso WR e viene riposizionato ad 1 quando l'ingresso ACK si porta a livello basso. ACK (dato ricevuto). La presenza di un livello basso a questo ingresso informa 1'82C55A che il dato emesso dal Port A o dal Port B è stato accettato. In altre parole, con questo segnale il dispositivo periferico comunica che ha ricevuto il dato emesso dalla CPU. INTR (richiesta di interrupt). La presenza di un livello alto su questa uscita può essere usata per generare una segnalizzazione di interrupt alla CPU, in quanto indica che il dispositivo d'uscita ha ricevuto il dato trasmesso dalla CPU. Il segnale INTR viene posto ad 1 se sia il segnale ACK che OBF ed INTE sono contemporaneamente a livello alto. Viene invece resettato dal fronte d'onda di discesa del segnale WR. INTE A. È un segnale che viene controllato mediante la scrittura su singolo bit offerta dall'82C55A. È collegato al bit 6 del Port C (PC6). INTE B. È un segnale che viene controllato mediante la scrittura su singolo bit offerta dall'82C55A. È collegato al bit 2 del Port C (PC2). 14 Configurazioni possibili in Modo 1. Nel Modo 1 sia il Port A che il Port B possono essere configurati individualmente come ingressi o come uscite. Modo 2 (ingresso - uscita di dati attraverso bus bidirezionale e segnali di controllo). Questa configurazione operativa permette all'82C55A di interfacciarsi direttamente ad un dispositivo avente un bus bidirezionale ad 8 bit. I segnali di controllo (con modalità di handshake) permettono di regolare il flusso dei dati in maniera analoga a quella vista per il Modo 1. È possibile inoltre sia generare un segnale di interrupt che di abilitarne e disabilitarne il funzionamento. Caratteristiche del Modo 2: - si può usare solo il Gruppo A; - un bus bidirezionale ad 8 bit disponibile sul Port A e 5 linee di controllo accessibili sul Port C; - sia gli ingressi che le uscite sono memorizzate; - il port di controllo a 5 bit (Port C) viene usato per controllare e leggere lo stato del bus bidirezionale ad 8 bit (Port A). Descrizione dei segnali di controllo del bus bidirezionale INTR (richiesta di interrupt). La presenza di un livello alto su questa uscita puo' essere usata per generare un interrupt alla CPU sia per le operazioni di ingresso che per quelle d'uscita. 15 Operazioni d'uscita OBF (buffer d'uscita pieno). L'uscita OBF si porta a livello basso per indicare che la CPU ha scritto il dato sul Port A al fine di emetterlo. ACK (ricevuto). Quando questo ingresso si porta a livello basso abilita il buffer d'uscita del Port A, normalmente in condizione three-state, ad emettere il dato sul bus. In caso contrario il buffer d'uscita rimane in condizione di alta impedenza. INTE 1(flip-flop INTE associato ad OBF). È un segnale che viene controllato mediante la scrittura su singolo bit offerta dall'82C55A. È collegato al bit 6 del Port C (PC6). Operazioni d'ingresso STB (ingresso di strobe). La presenza di un livello basso a questo ingresso fa caricare il dato presente sul bus nel latch d'ingresso. IBF (flip-flop segnalazione buffer di ingresso pieno). Se questa uscita si porta a livello alto vuol dire che i dati presenti agli ingressi del port sono gia stati acquisiti e quindi memorizzati. INTE 2 (flip-flop INTE associato ad IBF). È un segnale che viene controllato mediante la scrittura su singolo bit offerta dall'82C55A. È collegato al bit 4 del Port C (PC4). CONSIDERAZIONI SULL'USO DELLE COMBINAZIONI DEI VARI MODI Vi sono delle combinazioni di programmazione dei vari modi operativi che non utilizzano interamente i bit disponibili del Port C. Le linee rimanenti possono essere utilizzate nel seguente modo: - se programmate come ingressi tutte le linee d'ingresso possono essere lette con una normale operazione di lettura del Port C; - se programmate come uscite i bit della parte alta del Port C (PC-PC4) possono essere modificati 16 singolarmente usando la funzione di set/reset di un bit alla volta; i bit della parte bassa del Port C (PC3-PQ) possono sia essere modificati singolarmente usando la funzione di set/reset di un bit alla volta che venire scritti regolarmente accedendo al Port C. SOMMARIO DEI SIGNIFICATI DELLE LINEE NEI VARI MODI PA0 PA1 PA2 PA3 PA4 PA5 PA6 PA7 IN MODO 0 OUT IN MODO 1 OUT IN IN IN IN IN IN IN IN OUT OUT OUT OUT OUT OUT OUT OUT IN IN IN IN IN IN IN IN OUT OUT OUT OUT OUT OUT OUT OUT 17 MODO 2 solo gruppo A IN/OUT IN/OUT IN/OUT IN/OUT IN/OUT IN/OUT IN/OUT IN/OUT PB0 PB1 PB2 PB3 PB4 PB5 PB6 PB7 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 IN IN IN IN IN IN IN IN IN IN IN IN IN IN IN IN OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT IN IN IN IN IN IN IN IN INTRB IBFB STBB INTRA STBA IBFA I/O I/O OUT OUT OUT OUT OUT OUT OUT OUT INTRB OBFB ACKB INTRA I/O I/O ACKA OBFA I/O I/O I/O INTRA STBA IBFA ACKA OBFA Caratteristiche d'uscita del Port B e Port C Qualsiasi bit d'uscita tra quelli disponibili sul Port B o sul Port C possono erogare 2.5 mA a 1.5 Volt. Queste caratteristiche permettono all'82C55A di pilotare direttamente dispositivi tipo darlington o display a tensione elevata. Lettura dello stato delle periferiche dal Port C In Modo 0 il Port C trasferisce dati da o verso le periferiche collegate. Quando invece l'82C55A è programmato in Modo 1 o 2, il Port C è dedicato alla generazione o alla rilevazione dei segnali di controllo di handshake delle periferiche. La lettura del Port C permette al programmatore di sapere lo stato dei dispositivi periferici. Non sono richieste procedure particolari per acquisire tale valore, è sufficiente un'operazione di lettura normale. 18 PROGETTI DI INTERFACCE Il circuito si propone l'obiettivo di realizzare un'interfaccia sperimentale in grado di gestire e comandare una serie di dispositivi elettronici mediante l'utilizzo di un Personal Computer IBM compatibile fatto funzionare con un software di gestione redatto in TURBO PASCAL. I dispositivi prescelti da interfacciare sono: a) gruppo di 4 relè reed; b) gruppo di 2 display a sette segmenti decodificati e pilotati da decoder driver 9368; c) gruppo di 8 diodi led; d) gruppo di 8 dip-switch; e) controllo di temperatura ed umidità realizzato con 8 Contraves, 1 display LCD LM018 e 1 display LCM5003. Data la complessità dell'interfaccia si è deciso di montare su un apposito circuito stampato a parte (diverso dal circuito LX833) l'hardware relativo ai dispositivi elencati da a) a e). Esaminiamo uno ad uno i circuiti relativi alle quattro interfacce da realizzare. Interfaccia relè VCC In Fig. 1 è riportato lo elettrico R25 dell'interfaccia verso relè D13 schema K1 D9 U8A reed. In essa si nota la presenza di un registro a Data Bus 8 bit 74LS374 U4 che pilota sulle uscite Q0, Q2, Q4, Q6 quattro buffer invertenti 7406 che SEL1 7406 U4 D0 D1 D2 D3 D4 D5 D6 D7 RELAY VCC K2 R26 Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 OC CLK D10 D14 U8B 7406 74LS374 RELAY VCC K3 R27 D11 a loro volta pilotano D15 U8C altrettanti relè reed a 5V. 7406 RELAY VCC K4 Si osservi che ogni relè R28 D12 19 D16 U8D 7406 RELAY reed è dotato di diodo volano per i noti problemi esistenti nel pilotaggio dei carichi induttivi. Si noti che l'attivazione di un relè è pure visualizzata attraverso un diodo led con relativa resistenza di limitazione posto in parallelo alla bobina di eccitazione. Il circuito integrato 74LS374 riceve i dati provenienti dal Data Bus della scheda LX833 ED0-ED7 e li memorizza sul fronte di salita del suo ingresso di clock alimentato dal segnale SEL1. Per attivare il relè K1 (connesso alla uscita Q0) il PC dovrà inviare al registro U4 il codice binario %00000001 ($01), per attivare K2 il PC dovrà inviare il codice binario %00000010 ($02), per attivare contemporaneamente i relè K1, K3 e K4 il PC dovrà inviare il codice binario %01010001 ($51). Il segnale SEL1 dovrà essere generato da una operazione WRITE eseguita all'indirizzo attribuito all'interfaccia nell'ambito di quelli previsti dalla Tab. 1. Interfaccia display a sette segmenti decodificati In Fig. 2 è riportato lo schema elettrico dell'interfaccia verso display a 7 segmenti decodificati. In essa si nota la presenza di un registro a 8 bit 74LS374 U5 che pilota due decoder TTL 9368 connessi a due display a 7 segmenti catodo comune del tipo FND500. Il codice binario relativo ai 4 bit D0-D3 attiva il display LSD (cifra meno significativa) il codice relativo ai 4 bit D4-D7 attiva il display MSD (cifra più significativa). Le due decodifiche 9368 sono mantenute trasparenti (LE connesso a 0); la funzione di memorizzazione è affidata al circuito integrato U5 che come è noto memorizza i dati presenti sugli ingressi D0-D7 sul fronte di salita dell'ingresso di clock alimentato dal segnale SEL2. Fig. 2 20 Per trasferire al gruppo display il dato binario %01010010 ($52) il PC dovrà inviare al registro U5 il codice binario D1 R6 D2 U5 Data Bus D0 D1 D2 D3 D4 D5 D6 D7 %01010010 o esadecimale $52. Sul display MSD apparirà la cifra 5 sul display LSD R5=330 SEL3 D3 Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 OC CLK apparirà la cifra. Il segnale SEL2 dovrà 74LS374 R8 D4 R9 D5 R10 D6 R11 D7 R12 =330 D8 VCC VCC U10 Data Bus SEL2 1 2 4 8 BI/RBO RBI LE U5 D0 D1 D2 D3 D4 D5 D6 D7 Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 DY1 A B C D E F G 9368 VCC SEL4 U11 OC CLK 1 2 4 8 BI/RBO RBI LE 74LS374 A B C D E F G 9368 essere generato da una operazione WRITE eseguita all'indirizzo LSD R13 =10K U6 A1 A2 A3 A4 A5 A6 A7 A8 B1 B2 B3 B4 B5 B6 B7 B8 FND500 MSD DY2 G DIR 74LS245 P1 FND500 Fig. 3 attribuito all'interfaccia nell'ambito di quelli previsti dalla Tab 1. Interfaccia Led e Dip Switch In Fig. 3 è riportato lo schema elettrico dell'interfaccia verso 8 led e 8 dip switch. In essa si nota la presenza di un registro a 8 bit 74LS374 U6 che pilota 8 led corredati della appropriata resistenza di limitazione della corrente. Nel circuito è pure presente un transceiver 74LS245 U7 che consente la lettura dello stato logico predisposto dal gruppo di dip switch P1-P8 alimentati dalle otto resistenze di pull-up. Si osservi che avendo posto l'ingresso DIR di U7 a livello 0, il trasferimento dati avviene nel transceiver da B verso A. Il segnale SEL3 (fronte di salita per clock di U6) dovrà essere generato da una operazione WRITE eseguita all'indirizzo attribuito all'interfaccia Led nell'ambito di quelli previsti dalla tabella 1. Il segnale SEL4 (livello basso per ingresso G di U7) dovrà essere generato da una 21 R20 =10K P8 operazione READ eseguita U10A all'indirizzo attribuito all'interfaccia Dip-Switch nell'ambito EA0 EA1 A B G U7A di quelli previsti dalla tabella 1. Y0 Y1 Y2 Y3 74LS139 EWR 74LS32 U10B U7B A B Y0 Y1 Y2 Y3 ERD G ECS Controllo e sincronizzazione delle varie Y0-RD Y1-RD Y2-RD Y3-RD 74LS139 74LS32 interfacce Y0-WR Y1-WR Y2-WR Y3-WR Altro circuito di selezione Fig. 4 La necessità di interconnettere i circuiti di Fig. 1, 2 e 3 al circuito di Fig. (LX833) impone di suddividere i circuiti in due gruppi: 1) dispositivi verso i quali il Interfacci Selezione Indirizzo a Relè SEL1 302 Display SEL2 303 Led SEL3 300 DipSEL4 301 Switch Modo Connessio ne Y2-WR Y3-WR Y0-WR Y1-RD WR WR WR RD 2) dispositivi verso i quali il PC effettua operazioni di PC effettua operazioni di tipo READ (interfaccia dip-switch) VCC EA0 EA1 EA2 1 2 3 A B C ERD ECS 6 4 5 G1 G2A G2B tipo WRITE (gruppo relè, gruppo display, gruppo led). Una soluzione al problema può, in linea di principio Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7 15 14 13 12 11 10 9 7 Y0-RD Y1-RD Y2-RD Y3-RD Y4-RD Y5-RD Y6-RD Y7-RD 74LS138 VCC U9 (write) EA0 EA1 EA2 1 2 3 A B C EWR ECS 6 4 5 G1 G2A G2B essere quella di Fig. 4. In essa sono presenti due decoder 74LS139 uno dedicato a gestire fino ad un massimo di U8 (read) Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7 15 14 13 12 11 10 9 7 Y0-WR Y1-WR Y2-WR Y3-WR Y4-WR Y5-WR Y6-WR Y7-WR 74LS138 Fig. 5 fig. 6 Circuiteria di selezione otto dispositivi funzionanti in modalità READ e l'altro dedicato a gestire fino ad un massimo di otto dispositivi funzionanti in modalità WRITE. Ciascun decoder ha l'ingresso di abilitazione G2B connesso al segnale ECS (abilitazione scheda), l'ingresso di abilitazione G2A è connesso al segnale ERD nel caso del decoder U8 (gestione interfacce READ) al segnale EWR nel caso del decoder U9 (gestione interfacce WRITE). Assegnazione degli indirizzi 22 Ipotizzando ora di assegnare gli indirizzi come presentato in tabella bisognerà da ultimo rendere la logica di funzionamento dell'interfaccia compatibile con i segnali forniti dal sistema di decodifiche U8 e U9. Le uscite dei decoder 74LS138 sono attive a livello basso per cui date le premesse SEL1, SEL2 e SEL3 dovranno essere ricavati negando con una porta 74LS04 i segnali rispettivi Y2-WR, Y3-WR e Y0-WR mentre SEL4 dovrà essere collegato direttamente a Y1-RD. Un altro esempio di circuiteria di assegnazione degli indirizzi viene presentata in Fig. 5 in tal caso anziché utilizzare due circuiti integrati 74LS139 si utilizza un solo circuito integrato 74LS138 (decodifica doppia) con ovvia conseguente riduzione dei costi. Interfaccia per il Controllo della Temperatura e dell’ Umidita’ Scopo del progetto Con questo circuito si vuole simulare un sistema di controllo di temperatura nel quale valori di soglia di temperatura ed umidità rilevati, saranno confrontati con i valori di soglia massima impostati. Nel caso che i valori rilevati superino quelli di soglia si attiveranno degli opportuni segnali di allarme. In Fig. 6 è riportato lo schema a blocchi del circuito. LX833 A IMPOSTAZION E TEMP. / UMID LCD 1 LCD 2 LX833 B ADC MISURAZIONE TEMP. / UMID 23 LED SONDE ESTERNE Fig. 6 Componenti utilizzati - Contraves; SN74LS93; SN74LS04; SN74LS138; Trasduttori di temperatura AD590; Trasduttore di umidità; Quarzo 4Mhz; Convertitore Analogico Digitale; LCD Hitachi LM018; LCD. Contraves Sono dei dispositivi di input logico che servono ad impostare combinazioni BCD o binarie fisse (Fig. 7). Tramite un selettore rotante numerato si può selezionare la combinazione desiderata; sono usati nei sistemi di controllo di macchine utensili, in unità di misurazione e di test, nei sistemi di controllo e regolazione, nei sistemi computerizzati ecc. Le caratteristiche principali di questi "commutatori Fig. 7 rotanti" sono l'alta regolarità di funzionamento, di precisione e di durata dei contatti. I Contraves possono essere accoppiati con displays LED a 7 segmenti o alfanumerici. • Caratteristiche 1. compattezza; 2. semplice assemblaggio; 24 3. precisa e facile lettura dei valori di set; 4. varia scelta dei limiti di conteggio: 10,11,12 e 16 posizioni di commutazione 5. diversa lunghezza del bordo per l'incorporazione di diodi o resistenze • Caratteristiche elettriche 1. massimo carico di contatto: 50V, 100mA; 2. resistenza di isolamento 100 MΩ; 3. resistenza di contatto incluso p.c.b. 70-100 mΩ. SN74LS93 Questo integrato in tecnologia TTL è un 4BIT-BINARY COUNTER, cioè è un contatore (modulo 16). E’ costituito da 4 FlipFlop JK, come si vede in Fig.8 Il primo Flip-Flop non è connesso agli altri, quindi consente la divisione per due del Fig. 8 numero di impulsi d’ingresso. Introducendo il segnale attraverso CK1, dato che Tab. 2 questo è connesso in cascata con gli altri due, si ottiene, sull’uscita Q3, un segnale di frequenza 1/8 di quella d’ingresso. 25 Per ottenere il conteggio dei 16 impulsi, come indicato in Fig.9, occorre collegare esternamente l’uscita del primo flip-flop (Q0) con l’ingresso CK1 del secondo (pin 1 con pin12). Fig. 9 SN74LS04 Questo integrato in tecnologia TTL (Fig.10) è un HEX INVERTER ed è costituito da sei porte NOT . Queste ultime hanno un solo ingresso, di conseguenza ci possono essere solo due configurazioni di ingresso: 0 ed 1. Tali dispositivi anche una hanno sola uscita. Dalla tabella Tab. 4 Fig. 10 di verità Tab.4, che fornisce per ogni livello d’ingresso la corrispondente uscita del circuito, si comprende che le porte NOT servono a complementare il segnale d’ingresso. SN74LS138 In Fig.11 sono riportate la piedinatura e la connessione interna del SN74LS138. Quest’ultimo è un decoder/demultiplexer (3-to8 LINE DECODER), la funzione svolta da questo integrato è quella di pilotare 8 uscite (Y0...Y7, attive basse) mediante 3 ingressi di selezione (A,B,C). Nel circuito da noi realizzato, mediante la combinazione binaria che si presenta sugli ingressi, 26 questo integrato seleziona il contraves da cui leggere. I pin G2A e G2B e G1 sono di enable. I primi due, attivi bassi, sono stati collegati a massa, mentre il G1 viene gestito tramite il PC; ciò è necessario per poter realizzare l’attivazione dell’integrato, come si può apprendere dalla FUNCTION TABLE (Tab. 5). Fig. 11 Tab. 5 Trasduttore di temperatura AD590 Sensori di temperatura integrati La moderna tecnologia dei circuiti integrati ha determinato già da qualche anno l'immissione sul mercato di trasduttori, finalizzati alla misura delle più diverse grandezze fisiche, che incorporano, oltre il sensore vero e proprio, circuiterie più o meno consistenti (circuito di condizionamento del segnale) per l'amplificazione del segnale del sensore, la sua normalizzazione e la sua linearizzazione. I sensori integrati di temperatura sono tra i più diffusi di questa relativamente recente generazione di trasduttori. 27 Analog Devices AD590 Funzionalmente è un bipolo che si comporta come un generatore di corrente ad alta impedenza; la corrente generata è proporzionale alla temperatura assoluta: I=k*T T in °K (Kelvin) con la costante di proporzionalità k che ha il valore nominale di 1µA/K: la corrente in µA coincide numericamente, entro i limiti di errore, con la temperatura in Kelvin. Il principio fisico utilizzato è sostanzialmente la dipendenza dalla temperatura della Vbe nei transistor a giunzione; il range utile va da -55 0C (218 K) a +150 0C (423 K), con una tensione di alimentazione ai capi del bipolo fra 4 e 30 V indifferentemente. Il funzionamento in corrente presenta il vantaggio di rendere il sistema di misura insensibile a cadute di tensione; permette pertanto di porre il sensore molto lontano dall'apparato di misura. Inoltre, sempre per l'intrinseca insensibilità a variazioni di tensione, la reiezione ai disturbi è molto elevata. Poiché il sensore ha una massa molto ridotta, la sua velocità di risposta è piuttosto alta: le versioni in contenitore metallico TO-32 (secondo suffisso H) hanno una costante di tempo termica in aria ferma di circa 60 s (la costante termica è il tempo impiegato per adeguarsi al 63% del salto di temperatura ambientale: dopo circa 3 costanti di tempo l'equilibrio termico è praticamente Fig. 12 raggiunto); questo valore scende di molto in aria in movimento, e ancor più se il sensore deve misurare la temperatura di un corpo solido con cui è mantenuto in contatto. L’AD590 è disponibile in varie versioni, distinte da un primo suffisso I/J/K/L/M, che si differenziano per precisione (e per prezzo). Le principali cause di imprecisione sono un errore di scala (il valore di k differisce dal valore nominale 1 µA/K) e un errore di offset (la caratteristica I/T non passa esattamente per 0 a 0 K). Per esempio, l'AD590K ha un errore non calibrato di ± 5,5 0C su tutto il range utile; se si compensa l'errore di scala agendo sul 28 guadagno del sistema di condizionamento del segnale l'errore si riduce a ± 2,0 0C. D'altra parte anche il fuori zero e' compensabile, prevedendo una regolazione di offset; in tal caso l'unica causa di errore superstite è la non-linearità della caratteristica (±0,8 0C per l'AD590K). Per trasformare l'informazione fornita dall'AD590 in tensione il modo più ovvio è far cadere la corrente su una resistenza. Tuttavia è più razionale far uso di un convertitore I/V a operazionale (convertitore correntetensione), la cui impedenza di ingresso idealmente nulla dà un ulteriore contributo alla reiezione delle interferenze e che si presta facilmente alla regolazione di scala e di zero. In Fig. 12 é riportato il circuito base: la VR serve a produrre la corrente IR che, sottratta alla IS generata dal sensore, annulla la I e quindi la V0 alla temperatura di inizio scala (per esempio a 0 °C). Trasduttore capacitivo di umidità I trasduttori capacitivi essenzialmente, in due consistono, superfici conduttrici, dette armature, separate da un isolante, detto dielettrico; una delle armature è mobile e quindi, in seguito ad una sollecitazione, varia la posizione reciproca delle comportamento è armature. quello di Il un condensatore con capacità variabile Fig. 13 a) Trasduttore di livello a capacità: a1 = armatura fissa; a2 = armatura mobile; d = dielettrico; b) Trasduttore di pressione a variazione capacitiva. funzione della grandezza da rilevare. In un condensatore ad armature piane e parallele, si ha la seguente relazione: C =∈ S / d con C: capacità del condensatore; ∈: costante dielettrica del materiale isolante; S: area della superficie delle armature; d: distanza fra le armature. Dalla relazione precedente si deduce che per variare la capacità si può o variare la superficie 29 affacciata delle armature o la distanza delle armature stesse. I trasduttori del primo tipo sono detti ad area variabile e sono impiegati per misure angolari o lineari; quelli del secondo tipo sono detti a distanza variabile e sono impiegati per misure di piccoli spostamenti. I trasduttori capacitivi sono caratterizzati da compattezza, stabilità, linearità, buona precisione e risoluzione. Gli inconvenienti principali sono: l'influenza delle capacità parassite dei terminali, dato il piccolo valore della capacità del trasduttore; la sensibilità alle variazioni di temperatura ( che peraltro può essere superata impiegando trasduttori costituiti da due capacità, una fissa e una di misura, e circuiti di misura opportuni, in cui venga rilevato il rapporto fra le due capacità); l'elevata impedenza di uscita (che, peraltro, in alcuni casi può essere un vantaggio, come, ad esempio, quando il traduttore debba essere inserito in parallelo ad un altro dispositivo). I trasduttori capacitivi possono essere impiegati, in particolare, per rilevazioni di: posizioni; spostamenti lineari ed angolari; accelerazioni lineari; forze e pressioni. Quarzo 4MHz Il cristallo di quarzo è un componente elettronico molto usato per realizzare generatori di clock estremamente stabili in frequenza; in tali circuiti la frequenza di oscillazione coincide con quella di risonanza del Rs Cs quarzo. Si ricorda il largo impiego negli orologi al quarzo, Ls Cp come generatore di clock x' y" nei x PC processore, y y' (clock del RTC real Ls Cs Cp time clock, clock del XTAL x" x" circuito di refresh delle Fig.? Fig. 14 RAM dinamiche, ecc.). Il y' y circuito equivalente del cristallo è riportato in Fig.15; il simbolo circuitale in Fig. 14. x Fig. 15 y" x' Un cristallo di quarzo appartiene alla categoria materiali “piezoelettrici”; che, in presenza di una sollecitazione di tipo meccanico, si 30 comportano da generatori di f.e.m. proporzionale alla sollecitazione. Questa proprietà è sfruttata nei microfoni piezoelettrici, negli accendigas piezoelettrici ma più in generale nei trasduttori piezoelettrici. Il fenomeno della “piezoelettricità” è reversibile ossia applicando una d.d.p. al cristallo questo si deforma meccanicamente; questa proprietà è sfruttata negli altoparlanti piezoelettrici nei buzzer (cicalini piezoelettrici). La “piezoelettricità” è comune a quasi tutti i cristalli privi di un centro di simmetria (per es.: quarzo, tormalina, topazio, acido tartarico, clorato di sodio). Per l’utilizzo come oscillatore viene tagliato in lamine a forma parallelepipeda e lo spessore delle lamine risulta rispettivamente proporzionale alla frequenza di oscillazione. Le frequenze di oscillazione variano da qualche migliaia di Hz (lamine di spessore maggiore) a qualche Mega Hz (lamine di spessore inferiore). Se si applica una pressione si manifesta sulle due facce perpendicolari all’asse elettrico una differenza di potenziale in continua, se invece si applica una trazione lungo le Asse ottico Asse neutro due facce che scorrono lungo l’asse neutro si manifesta sulle due facce normali (perpendicolari) all’asse elettrico una differenza di potenziale di verso opposto alla precedente; una Asse elettrico successione di compressioni e trazioni applicate lungo l’asse neutro, origina una differenza di potenziale sulle facce Fig. 16 Fig.? perpendicolari all’asse elettrico. Questo fenomeno è reversibile, cioè applicando sulle due facce perpendicolari all’asse elettrico una differenza di potenziale alternata il cristallo si mette a vibrare con una sua frequenza di oscillazione. Le frequenze del quarzo sono due, frequenza di risonanza serie fs e frequenza di risonanza parallelo fp, codeste assumono dei valori molto prossimi l’una all’altra. Le formule per trovare la frequenza sono : 1 fp = 2∏ 1 fs = 2∏ L1C1 31 1 C1 + C p ( ) L C1Cp fs è la frequenza di risonanza serie per X=0 ed fp è la frequenza di oscillazione parallela per X=infinito. In Fig.16 si possono notare le posizioni che assumono i vari assi rispetto al cristallo. ADC0808 Caratteristiche Generali Di Un Convertitore Analogico-Digitale La funzione dei convertitori A/D è quella di trasformare un livello di Vi A/D tensione in un numero N espresso in codice binario ad esso corrispondente }N (n bit) come esplicitato dalla formula: n= 8,10,12,14,16 bit V N = I ⋅ 2n VREF dove Fig. 17 VREF è la risoluzione del convertitore e n è il numero dei bit del convertitore A/D. 2n Precisione E’ definita dallo scarto tra il valore convertito ed il valore vero della grandezza in esame. Le cause che alterano la precisione del convertitore sono essenzialmente : • la deriva, intesa come effetto della temperatura, dell’invecchiamento dei componenti e delle fluttuazioni dell’alimentazione; • la non linearità del comportamento. Sensibilità E’ rappresentata dal più piccolo livello di tensione che può essere convertito. Si definisce anche il massimo valore dei segnali di ingresso che consentono al convertitore di lavorare nelle migliori condizioni di funzionamento. Potere risolutivo 32 E’ la più piccola variazione di tensione cui è sensibile il convertitore, questo non è da confondere con la sensibilità in quanto il convertitore può non avvertire tensioni prossime allo zero ma può sentire piccole variazioni in un punto qualsiasi delle sue caratteristiche di comportamento dinamico. Tempo di conversione Rappresenta il tempo impiegato dal circuito per eseguire la conversione da analogico in digitale. Gli elementi che lo compongono sono: • tempo di conversione incrementale: è il tempo impiegato a convertire una tensione corrispondente al potere risolutivo, cioè al minimo incremento cui il circuito è sensibile; • tempo di conversione sull’intera scala: tempo impiegato dal circuito ad effettuare la conversione della massima tensione misurabile ( a partire dal livello 0 ). Se è necessario inserire, all’ingresso del circuito, un filtro per l’eliminazione del rumore il tempo di conversione si allunga notevolmente. Nel campo dell’elettronica la conversione viene utilizzata per rendere un segnale comprensibile, o misurabile, per un qualsiasi strumento di misura o di elaborazione. I circuiti per convertire i segnali analogici in segnali codificati sotto forma digitale, e viceversa, sono diventati di grande importanza nei sistemi elettronico-informatici, perchè le connessioni di varie apparecchiature che comunicano fra loro richiedono mezzi adatti a tradurre da una forma all’altra. In generale le uscite dei sensori forniscono segnali di tipo analogico, i quali debbono essere tradotti in forma numerica per poter essere interfacciati con i sistemi di elaborazione. Una alternativa a questi sistemi ibridi è quella di sviluppare sistemi tutti digitali. Molti sforzi sono concentrati per sviluppare nuovi sensori, che abbiano uscite digitali, e nuovi elementi di controllo e azionamento, che abbiano ingressi digitali. Tuttavia, nonostante qualche risultato ottenuto nel campo dei programmi di ricerca spaziale e militare, questa alternativa rimane, per ora, soprattutto una tendenza di ricerca e non è ancora di pratica attuazione. I dispositivi, in grado di effettuare la conversione del segnale sono: 33 • I convertitori digitali analogici o D A C (Digital Analog Converter), oppure D/A; • I convertitori analogici digitali o A D C (Analog Digital Converter), oppure A/D; Ma non esistono solo due tipi di conversione nel campo dell’elettronica ci sono anche conversioni che permettono di ottenere da un segnale di ingresso in corrente un segnale di uscita proporzionale a quello in ingresso in tensione, e viceversa. Oppure si può anche convertire una tensione in frequenza, e viceversa. LA CONVERSIONE DIGITALE-ANALOGICA E ANALOGICA-DIGITALE Esistono apparecchiature elettroniche che forniscono unicamente segnali di tipo analogico: tra queste, ad esempio, molti trasduttori, che trasformano grandezze fisiche in elettriche e, nella maggior parte dei casi, il segnale prodotto è analogico, ovvero subisce variazioni proporzionali alla grandezza fisica applicata al suo ingresso. Poiché la manipolazione dei segnali può avvenire attraverso circuiti digitali, è evidente la necessità di convertire la grandezza analogica in digitale mediante i circuiti definiti convertitori analogici digitali. Viceversa il risultato dell’elaborazione di una rete logica deve poter comandare attuatori di tipo analogico. Dato che per attuatore si intende un sistema in grado di trasformare un segnale elettrico in una grandezza fisica proporzionale al segnale, è necessario che il risultato dell’elaborazione digitale sia convertito in analogico, per pilotare un attuatore. Un sistema in grado di trasformare un risultato digitale in un segnale analogico viene definito convertitore digitale/analogico. Nella conversione digitale/analogica e analogica/digitale si incontra un problema fondamentale: una grandezza analogica è costituita da un insieme continuo di valori, una grandezza digitale, per la sua natura binaria, è invece costituita da un insieme finito di valori possibili. Questo condiziona evidentemente la precisione della conversione. Per aumentare la sensibilità e la precisione si ricorre alla quantizzazione e al campionamento. Il convertitore è in generale solo uno dei blocchi circuitali che compongono un sistema di conversione da analogico a digitale e viceversa. Ad esempio un sistema di conversione D/A è composto tipicamente da un convertitore D/A e da un filtro passa basso in cascata al 34 convertitore con lo scopo di eliminare le discontinuità del segnale di uscita del DAC dovute alla sua caratteristica di trasferimento . In questo modo è possibile ottenere un segnale privo di disturbo e di rumore. Filtro passabasso D VO VO t t Fig. 18 Invece un sistema di conversione analogico-digitale è composto nel caso più semplice da un filtro passa basso, un circuito di sample and hold e dal convertitore ADC vero e proprio. Il tutto sarà comprensibile durante la lettura del testo. Comunque la presenza del filtro in ingresso si può spiegare con la necessità di limitare il contenuto armonico del segnale da convertire in modo che per la frequenza di campionamento scelta non si verifichi il fenomeno di aliasing. B1 VIN Filtro passabasso Circuito sample and hold ADC Bn V di ingresso clock Fig. 19 CONVERTITORI ANALOGICI DIGITALI ADC I convertitori analogico-digitali trasformano un livello di tensione in un codice binario ad esso corrispondente. Questa operazione può avvenire con soluzioni diverse, tuttavia alla base dei criteri di scelta dei convertitori ADC che vengono presi in esame vi sono tre parametri : la velocità di conversione, la risoluzione di conversione ed il costo. Per quanto riguarda la conversione essa può avvenire con diversi metodi: 35 • Ad approssimazioni successive • Ad integrazione E relativamente alle particolari strutture interne in: • Con convertitori paralleli veloci • Half-flash ADC AD APPROSSIMAZIONI SUCCESSIVE Il metodo di conversione ad approssimazioni successive è sicuramente il più diffuso in quante consente un buon compromesso fra velocità di conversione e risoluzione. Va Nel convertitore a 4 bit in Va' DAC MSB Buffer di stato Fig. 20 il segnale di ingresso Va viene comparato con precisi LSB EOC SAR Controllo Temporizz Fig.Figura 20 14 SOC livelli di tensione generati dal convertitore DAC. Dopo l’applicazione del comando di conversione SOC (Start Of Convertion), che azzera le uscite e inizializza il sistema, il registro ad approssimazioni successive SAR (Successive Approssimation Register) si trova nello stato 1000. Questo dato viene presentato in ingresso al DAC che fornisce il primo livello analogico, pari a metà della tensione di fondo scala del convertitore, da confrontare con il segnale Va . Se Va > Va ' l’uscita del comparatore è alta e il bit più significativo del SAR, e quindi anche quello del dato di uscita, si porta a zero. A questo punto, in sincronismo con il clock, viene portato ad 1 il secondo bit più significativo del SAR, cosicché il dato presente sugli ingressi del DAC sarà 1100 oppure 0100 a seconda del risultato del confronto precedente. Il secondo confronto porta a 0 o mantiene ad uno il secondo bit del SAR e del buffer di uscita, a 36 seconda che Va risulti minore o maggiore di Va ′ . Con procedimento analogo vengono effettuati il terzo e il quarto confronto. Alla fine della conversione, ovvero dopo quattro confronti successivi, il dato digitale contenuto nel buffer di uscita è pronto e valido; il blocco di temporizzazione segnala la fine della conversione EOC (End Of Convertion) e l’uscita può essere letta. Utilizzando la tecnica delle approssimazioni successive si richiedono n interazioni, e quindi n cicli di clock, per convertire una tensione di ingresso in un dato ad n bit, indipendentemente dal valore della tensione stessa. Questo fatto unitamente alle buone prestazioni in risoluzione, fa preferire la tecnica ad approssimazioni successive nella realizzazione di convertitori a media velocità, adatti ad esempio per applicazioni con microprocessori. CONVERTITORE ADC 0808 Questi due tipi di convertitori ADC sono i più usati nel mondo dell’acquisizione dati industriale. Infatti nel nostro caso e stato utilizzato un convertitore analogico-digitale ad approssimazioni successive. Questo convertitore, l’ADC0808, usa una tecnologia monolitica a CMOS. A 8 bit di uscita ed 8 ingressi gestiti da un multiplexer, ed è compatibile con i microprocessori più usati. 37 LCD LM018 HITACHI Il modulo LCD è un vecchio modello Hitachi H2572 alimentato a 5V. Esso può visualizzare fino ad un massimo di 40 caratteri su di unica una riga. L’interfaccia fra il modulo LCD e Fig. 21 l’esterno è sommariamente descritta nella Tab. 7. Si noti la presenza del bus dei dati bidirezionale da DB0 a DB7, l’ingresso R/W attraverso cui si specifica la direzione del flusso dei dati: da PC verso l’LCD se R/W è Low, dall’LCD verso il PC se R/W è High. L’Ingresso E (enable) che se posto a livello alto abilita il Data Bus e con esso il flusso FIG. Fig. 22 Tab. 6 38 dei dati, l’ingresso RS che specifica Pin n° Symbol se in un certo istante la transazione 1 Vss fra PC e LCD riguarda dati o 2 Vdd 3 Vo piuttosto comandi inviati al modulo 4 RS LCD. In Fig. 22 si può notare la disposizione dei pin di collegamento dell’LCD. In Tab. 6 sono riportati i tempi di ritardo da dare all’LCD per far si che questo possa funzionare correttamente rispettando l’esatta sequenza delle varie funzioni. In Fig. 21 è riportato il diagramma temporale di detta sequenza. Level Function H/L 5 R/W H/L 6 7 8 9 10 11 12 13 14 E DB0 DB1 DB2 DB3 DB4 DB5 DB6 DB7 H/L H/L H/L H/L H/L H/L H/L H/L H/L 0V Power Supply 5V Power Supply Power Supply L=instruction code input; H=Data input L=Data read; H=Data write Enable Signal Data bus line Data bus line Data bus line Data bus line Data bus line Data bus line Data bus line Data bus line Tab. 7 Principio di funzionamento Il principio di funzionamento di questo circuito è quello di impostare e effettuare controlli su delle soglie di temperatura e di umidità che possono variare riaspettivamente da 1 C° a 99C° e dall'1% al 99%. Agendo sui contraves le soglie impostate vengono visualizzate su un display LCD a 4 righe e, tramite software, dopo confrontate con i valori di temperatura e di umidità rilevati dai potenziometri, i quali simulano i relativi trasduttori di temperatura e di umidità. Se le misurazioni lette sui potenziometri sono maggiori di quelle impostate attraverso i contraves si accenderanno i rispettivi led che segnalano l'eventuale attivazione di un relè. Oltre alla segnalazione visiva, verrà visualizzato un messaggio di allarme sul display LM018 (es: SUPERATA SOGLIA T1). Inoltre sempre sul medesimo display comparirà un messaggio di avvertimento nel caso le soglie impostate siano uguali a zero (es: IMPOSTARE SOGLIA T1). 39 Modalità di collegamento Sulle 2 schede LX.833 abbiamo montato il PPI 82C55A. Le schede sono poi state inserite nel BUS del PC poiché da lì ricevono le relative informazioni mandate dal software di gestione. Inoltre ogni scheda è stata corredata di connettore DB37 come DB37 quello che si può notare in Fig. 23, il quale attraverso un cavo (costruito da Fig. 23 noi) rende possibile l’interazione con circuiti esterni al PC. Sulle schede LX.833 abbiamo dovuto apportare delle modifiche poiché non vi era la possibilità di prelevare le e alimentazioni necessarie da mandare alla circuiteria esterna al PC; abbiamo dunque dovuto attingerle dal BUS a 8 bit del computer seguendo le indicazioni relative al connettore del BUS di espansione PCXT presente sulla scheda madre (vedi tabella relativa in allegato). Gli ingressi dei Contraves (1,2,4,8), sono collegati al catodo dei diodi, questi ultimi a loro volta hanno l’anodo collegato a +Vcc attraverso 4 resistenze di Pull Up da 10 KΩ come Fig. 24 si può notare in Fig. 24. Questi diodi sono così connessi poiché i contraves in questo caso funzionano in logica negata. Infatti al comune di questi ultimi viene mandato, dal contatore “SN74LS138”, un 40 segnale a livello basso. Tale segnale manda in conduzione i diodi della combinazione numerica prescelta, portando così a livello basso i bit del Port B, i quali vengono poi negati attraverso il software di gestione riportandoli così a livello alto. Una volta fatto questo i bit vengono inviati al display LCD2 per essere visualizzati come livelli di soglia. Un problema è sorto quando si è trattato di collegare i displays. Infatti, non avendo a disposizione Port a sufficienza per un funzionamento indipendente dei due LCD abbiamo dovuto effettuare un collegamento parallelo tra loro. Per poter far sì che gli LCD funzionassero correttamente abbiamo mandato due segnali di attivazione del diplay (ENABLE) distinti. Facendo così è possibile attivare solamente il display che deve ricevere i dati. I bit D0,D1,…,D6,D7 che vanno ai display (Pin 7,8,9,10,11,12,13,14) sono collegati ad una resistenza di Pull Up da 10KΩ mandata a +VCC, per poter evitare l’eventuale presenza di disturbi. Nella seconda parte del circuito, cioè quella della misurazione delle temperature e delle umidità, abbiamo montato un convertitore analogico-digitale il quale, convertendo il segnale analogico proveniente dai potenziometri in un segnale digitale, fa in modo che i dati rilevati vengano trasferiti al computer per l’elaborazione tramite software e mandati all’LCD2 . I valori rilevati oltre ad essere visualizzati sul display vengono, sempre attraverso l’elaborazione software, confrontati con quelli impostati tramite i contraves e, a seconda del risultato, verranno o meno attivate le relative segnalazioni visive, i relativi messaggi di avvertimento. Il CK all’ADC0808 è fornito da un oscillatore costituito da un quarzo da 4 MHz, due porte NOT 74LS04 funzionanti in zona lineare e due condensatori di GENERATORE DI CLOCK ADC R5 compensazione. Le porte TTL 680 U4A servono da amplificatori invertenti 680 U4B Y1 1 . Per far questo devono funzionare R6 3 2 74LS04 C6 22pF C5 22pF GND né in interdizione ). Per ottenere condizione 14 1 4MHZ 74LS04 in zona lineare (non in saturazione questa 4 2 3 U5 A B QA 12 QB 9 8 QC 11 QD R0(1) R0(2) 74LS93 CLKADC GND GND di Fig. 24 funzionamento dobbiamo fare in modo che la tensione di ingresso VI risulti uguale a quella di uscita VU . Ciascuna porta NOT introduce uno sfasamento di 180º fra segnale di ingresso 41 e di uscita, e funzionano da amplificatori invertenti per piccole variazioni attorno al punto di lavoro, perciò lo sfasamento globale è pari a 0º ; la presenza del quarzo assicura che le condizioni di oscillazione di Barkausen siano verificate in prossimità della frequenza di risonanza serie del cristallo di quarzo. Questo tipo di oscillatore e’ semplice da realizzare (come si può notare in Fig. 24) e fornisce un segnale a frequenza fissa ed e’ discretamente preciso; purtroppo la frequenza e’ influenzata sia pure in minima parte dalla temperatura. Poiché al nostro integrato occorre una frequenza di 500K Hz abbiamo dovuto inserire anche un divisore di frequenza per 8 poiché il quarzo è da 4 Mhz. Questo divisore di frequenza è stato realizzato utilizzando un contatore binario da $0 a $F del tipo 74LS93 prelevando due segnali dalle uscite QD e QC : la frequenza del segnale proveniente dal quarzo viene divisa quattro volte se si considera l’uscita QC (1MHz) e otto volte se si considera l’uscita QD (500KHz). L’uscita dell’oscillatore l’abbiamo collegata al piedino CLK dell’ADC (come si notare in Fig. 25). Il convertitore opera rispettando una serie rigorosa di fasi: - Invio degli indirizzi di canale ai piedini A0,A1,A2; Fig. 25 42 - invio di un segnale al piedino ALE che permette la memorizzazione dell’indirizzo di canale selezionato nel latch interno all’ADC; - invio di un segnale al piedino di START che permette l’avvio della conversione; - attesa del segnale di fine conversione EOC. Dopodiché i dati letti verranno mandati al display che li visualizzerà. Agli ingressi del convertitore (IN4,IN5,IN6,IN7) abbiamo collegato dei potenziometri lineari, alimentati a 5V, da 1KΩ in modo da farli funzionare come dei partitori di tensione; in questo modo forniranno un segnale all’ingresso dell’ADC che varia da 0 a 5 Volt. La lettura ADC varierà fra 0 e 255. Quando i valori misurati superano la soglia impostata si accenderanno dei led. Questi sono stati collegati con il catodo a massa e l’anodo al rispettivo Port come segue. Temperatura 1 PC4 (Led 1 rosso) Temperatura 2 PC5 (Led2 rosso) Umidità 1 PC6 (Led 1 verde) Umidità 2 PC7 (Led 2 verde) SOFTWARE DI GESTIONE 43 PASCAL I linguaggi di programmazione degli elaboratori elettronici La programmazione degli elaboratori può essere attuata facendo uso del linguaggio macchina oppure di linguaggi di programmazione detti ad alto livello. Il linguaggio macchina è un linguaggio specifico di una determinata CPU e quindi presuppone una buona conoscenza del set di istruzioni del modo di indirizzamento, delle modalità di esecuzione delle istruzioni da parte della CPU e dell'architettura del sistema utilizzato. I linguaggi ad alto livello sono completamente indipendenti dal tipo di CPU su cui operano, sono molto più aderenti al modo di esprimersi di un essere umano e non richiedono una conoscenza specifica dell'architettura del sistema su cui viene redatto un determinato programma. Generalità sulla stesura di un programma Il programma scritto dal programmatore ed introdotto nella memoria dell'elaboratore viene detto programma SORGENTE (SOURCE-PROGRAM); quello materialmente eseguito dalla CPU, e perciò codificato in linguaggio macchina, viene denominato programma OGGETTO (OBJECT-PROGRAM). Sarà perciò necessario disporre di un traduttore che, partendo da istruzioni redatte in linguaggio ad alto livello, le trasformi in equivalenti istruzioni stese in linguaggio macchina. Ogni linguaggio dispone quindi di un traduttore in linguaggio macchina. Un generico linguaggio ad alto livello può essere strutturato per funzionare in modo INTERPRETE o in modo COMPILATORE. 44 Nel modo INTERPRETE il programma sorgente si trova in memoria RAM e viene introdotto attraverso una tastiera che di solito opera in codice ASCII (American Standard Code for Information Interchange); quando viene attivata l’esecuzione del programma l'interprete per ciascuna riga di programma effettua le seguenti operazioni: 1)- Controllo sintattico sulla riga di programma. 2)- Traduzione della riga di programma in linguaggio macchina. 3)- Esecuzione di quella riga di programma. La fase 1) di controllo sintattico può dare origine a segnalazioni di errore che appaiono sul terminale video con indicazione della riga di programma ove si è verificato l'errore e del tipo di errore riscontrato (codifica numerica) SYNTAX-ERROR. Per correggere l'errore è necessario riscrivere la riga di programma errata. La fase 2) di traduzione in linguaggio macchina, può dare origine a segnalazioni di errore di tipo COMPILATION-ERROR per correggere le quali è necessario sempre riscrivere una o più righe errate di programma. La fase 3) di esecuzione del segmento di programma oggetto anch'essa può dare origine a segnalazioni di errore di tipo RUN-TIME-ERROR per correggere le quali bisogna analizzare con attenzione qual'è la condizione che ha provocato l'errore. Nel modo COMPILATORE il programma sorgente si trova di solito su disco sotto forma di "file" (archivio di informazioni su disco); la preparazione del sorgente su disco avviene attraverso l'uso di un apposito strumento software" denominato EDITORE. il compilatore fa una analisi sintattica di tutto il programma sorgente fornendo eventuali segnalazioni di errore che servono al programmatore per correggere il programma. In caso il controllo sintattico abbia dato esito positivo, viene effettuata la traduzione in linguaggio macchina del programma sorgente, traduzione che viene registrata su disco sotto forma di "file". Il programma oggetto così prodotto dal compilatore in genere non è ancora eseguibile in quanto privo delle necessarie informazioni base per eseguire operazioni matematiche più o meno complesse o operazioni di Input Output. Si rende necessaria un'ultima operazione denominata operazione di LINK delle librerie che viene attuata per mezzo di un altro "strumento software" chiamato LINKING-LOADER. Il programma oggetto prodotto dal compilatore, "linkato" con le routine di libreria è quindi in grado di funzionare 45 autonomamente; anch'esso viene salvato su disco e costituisce il prodotto finale e conclusivo della compilazione. Programmi interpretati L'impiego di un linguaggio interprete presenta pregi e difetti che di seguito vengono elencati: - Il programma viene modificato in modo molto semplice (riscrivendo la riga di programma errata) e in modo altrettanto semplice è possibile verificare la validità della correzione. - Il programma sorgente è sempre presente in RAM quindi è di solito "listabile" su video o stampante (manca la segretezza richiesta in taluni casi). - La velocità di esecuzione del programma è piuttosto bassa in quanto ogni volta che viene impartito il comando di esecuzione (RUN per il BASIC e PASCAL) vengono sempre e comunque ripetute le fasi di controllo sintattico e di traduzione in linguaggio macchina del programma sorgente in quanto a priori non è possibile stabilire se la versione di programma presente in memoria è quella corretta oppure no. - L'area di memoria a disposizione è piuttosto modesta in quanto per consentire l'esecuzione di un programma interpretato deve essere presente in memoria oltre al programma sorgente, l'interprete (linguaggio - Interprete) completo corredato di RUNTIME-PACKAGE (biblioteca completa). Programmi Compilati L'impiego di un linguaggio compilatore presenta pregi e difetti che di seguito vengono elencati: - Il programma sorgente non può essere modificato con rapidità in quanto è necessario ricorrere all'EDITORE per ricaricare il programma in memoria, correggere la o le righe 46 errate e salvare su disco il programma corretto. La verifica richiede che venga ripetuta la procedura di compilazione al completo. - Il programma che viene eseguito dalla CPU è redatto in linguaggio macchina e quindi non è "listabile" su video o stampante (ciò consente un ottimo grado di segretezza sul codice sorgente che è stato utilizzato dal programmatore autore del programma) ciò costringe il cliente a rivolgersi al programmatore per eventuali future modifiche. - La velocità di esecuzione del programma è più elevata rispetto a quella di un programma interpretato (il controllo sintattico del programma e la traduzione in linguaggio macchina sono stati effettuati una volta per tutte dal compilatore prima di produrre il programma oggetto). - L'area di memoria a disposizione è la massima possibile in quanto per il suo funzionamento il programma oggetto non ha bisogno né del compilatore né tantomeno del programma sorgente che in casi di programmi di una certa lunghezza addirittura non potrebbe nemmeno stare nell'intera RAM del calcolatore. Si conclude perciò che, ove un determinato linguaggio abbia la possibilità di configurarsi nei due modi sopra descritti, sarà opportuno operare in ambiente Interprete nella fase di stesura, di correzione e di verifica di funzionalità (fase di Debugging) del programma stesso (sfruttando quindi tutti i vantaggi dell'ambiente Interprete) poi sarà quindi opportuno trasferirsi in ambiente Compilatore per procedere alla traduzione in linguaggio macchina del programma predisposto (con tutti i conseguenti vantaggi). Va comunque ribadito che, programmi di modeste dimensioni consentono di operare indifferente in modo Interprete e in modo Compilatore mentre programmi di cospicue dimensioni obbligano ad operare in modo Compilatore. Struttura di un programma Pascal Un programma Pascal consiste in una sequenza di istruzioni che realizzano un algoritmo, cioè una possibile soluzione ad un certo problema. Questo linguaggio è altamente strutturato, per cui possiede un insieme di regole rigidamente definite, ma nello stesso tempo flessibili all’uso. Un programma Pascal risulta diviso in più sezioni , ognuna delle quali ha una precisa collocazione e deve risultare sintatticamente corretta per garantire 47 l’assenza di errori in fase di compilazione. I compilatori Pascal forniscono una ricca gestione degli errori, che possono venire identificati non solo in fase di compilazione, ma anche in fase di esecuzione del programma. Non esistono, nel linguaggio Pascal, regole precise che guidino il programmatore all'uso di spazi bianchi e linee separatrici, oppure che impongano un particolare tipo di indentazione delle istruzioni, per cui il programmatore stesso può liberamente adottare per il suo programma qualunque tipo di formato. Questa libertà presenta vantaggi e svantaggi: se da un lato la fantasia del programmatore può sbizzarrirsi, dall'altro è bene che questi mantenga una certa chiarezza e uniformità di stile durante tutto il programma. Blocchi I programmi Pascal si compongono di una o più strutture a blocco. La definizione della struttura di blocco, come altre definizioni sintattiche, è di tipo ricorsivo, in quanto un blocco può essere annidato in altri blocchi. Questa struttura a blocchi permette di raggruppare insieme dichiarazioni e istruzioni in relazione tra loro e, in particolare: 1. permette di raggruppare una sequenza di istruzioni in un'unica istruzione composta; 2. fornisce un controllo sull'allocazione di memoria delle variabili (dichiarazione di variabili) e sulla loro referenziabilità, lecita o meno, nelle diverse parti del programma (visibilità). I blocchi possono contenere dichiarazioni, istruzioni e altri blocchi annidati e sono usati per organizzare un programma Pascal. Il blocco inizia con la dichiarazione di tutti gli oggetti che sono locali ad esso e, di conseguenza, referenziabili in ogni eventuale blocco annidato. La sezione dichiarativa, se esiste, è seguita da una o più istruzioni di programma, delimitate dalle due parole riservate begin e end. Gli oggetti locali ad un blocco non possono essere referenziati all'esterno di esso, ma solamente nel blocco in cui sono dichiarati o nei blocchi annidati in questo. La struttura a blocchi di un programma Pascal permette di seguire facilmente il flusso di controllo poiché i blocchi Pascal presentano una sola entrata e una sola uscita. 48 Il Pascal, inoltre, permette l'annidamento di blocchi di procedure e funzioni standard, appartenenti alla sua libreria. Programmare in Turbo Pascal La costruzione di un programma in Turbo Pascal prevede la conoscenza di alcune nozioni elementari , dato che questo tipo di codifica è soggetto ad una struttura ben precisa. Esiste una parte fissa, obbligatoria, costituita: 1. dall’intestazione program nome;(ove nome è il nome del programma dato dal programmatore); 2. dalla parola chiave begin che indica l’inizio della successione delle istruzioni; 3. dalla parola chiave end. Che marca la fine del programma. Il calcolatore darà una segnalazione di errore nell’analisi di un programma che manchi di queste tre parti. Va inoltre ricordato che è obbligatorio, nello scrivere un programma in Turbo Pascal, segnare la fine di ogni dichiarazione e di ogni istruzione con il punto e virgola (;). Intestazione del programma Ogni programma Pascal Standard inizia con un'intestazione del tipo: program nomeprogramma (input,output) I parametri, o argomenti, racchiusi tra parentesi, dopo l'indicazione del nome del programma, indicano i file di ingresso (input) e di uscita (output), tramite i quali il programma interagisce con l'ambiente esterno. Le variabili predefinite input e output identificano simbolicamente il file di ingresso, la tastiera, e di uscita, lo schermo. 49 Nel Turbo Pascal, l'intestazione del programma non è obbligatoria, in quanto il compilatore Turbo la ignora completamente. Si consiglia, comunque, di scrivere sempre l'intestazione, per garantire la portabilità dei programmi verso altri tipi di compilatori, oltre a migliorare la leggibilità dei programmi stessi. Corpo del programma Il corpo del programma, o blocco principale, contiene dichiarazioni ed istruzioni. La sezione dichiarativa definisce gli oggetti globali, cioè gli oggetti referenziabili da qualunque parte del programma, e deve precedere sempre la parte riservata alle istruzioni. Le dichiarazioni riguardano label, tipi, costanti, variabili e altri blocchi di sottoprogrammi (procedure e funzioni definite dall'utente). La sezione riservata alle istruzioni specifica, invece, le azioni che il calcolatore deve eseguire. Delle istruzioni possono fare parte operatori, parole riservate, chiamate di procedure e di funzioni standard, o definite dall'utente. I programmi Pascal terminano sempre con un punto, posto dopo l’ultimo delimitatore di fine blocco (end.). Visibilità Nel linguaggio Pascal, gli oggetti dichiarati possiedono una visibilità (scope) che può essere globale (oggetti noti in ogni parte del programma), oppure locale (oggetti noti solo nel blocco in cui sono dichiarati). Dal momento che è lecito annidare blocchi in altri blocchi, la visibilità di un oggetto dichiarato nel blocco più esterno permane anche nei blocchi più interni. In particolare, gli oggetti dichiarati nel blocco principale hanno una visibilità totale, cioè esistono per tutti i blocchi del programma. Nel linguaggio Pascal, ad ogni oggetto dichiarato, cioè label, costanti, tipi, variabili, procedure e funzioni, è associata una visibilità. 50 Dichiarazioni Il linguaggio Pascal presuppone che tutti gli oggetti vengano dichiarati prima di essere referenziati nel corso del programma. Per oggetto si intende ogni cosa che possiede un nome, dai programmi alle label, dai tipi alle variabili, dalle procedure alle funzioni. La sezione riservata alle dichiarazioni è collocata tra l'intestazione di blocco e la sezione istruzioni, per ogni blocco presente nel programma. Nel Pascal Standard è necessario rispettare un ordine di precedenza prestabilito per i vari tipi di dichiarazione, ordine che può essere ignorato nel Turbo Pascal. In ogni caso, comunque, le dichiarazioni devono sempre precedere, all’interno del blocco, le istruzioni. Le sei parti di cui si compone una sezione dichiarativa sono: 1. label - label (etichette) usate per referenziare linee di programma; 2. const - costanti simboliche il cui valore non è alterabile durante l'esecuzione del programma; 3. type - strutture e tipi di dati definiti dal programmatore; 4. var - dichiarazioni delle variabili e del loro tipo (ad esempio real, integer ecc); 5. procedure - sottoprogrammi definiti dal programmatore; 6. function - funzioni definite dal programmatore. Label Le label sono utilizzate per referenziare particolari punti del programma, a cui il programmatore intende trasferire il controllo con una istruzione goto. Il Pascal Standard richiede che le label siano interi senza segno, al massimo quattro cifre, ma il Turbo Pascal permette di definire label qualunque intero senza segno o, in genere, qualunque identificatore purché legale. Costanti 51 Le costanti sono oggetti il cui valore non cambia nel corso dell’esecuzione del programma. Esse, possono rappresentare qualunque dato ed il loro tipo è implicito nel formato del valore che rappresentano. Tipi Il linguaggio Pascal Standard definisce diversi tipi e strutture dati per variabili e costanti: real, integer, boolean, char, array, record, set, file . Il Turbo Pascal aggiunge, a questi, altri due tipi predefiniti: byte e string. 1. real. Le costanti di questo tipo possono assumere un valore positivo o negativo, anche frazionario, di estensione e precisione limitati dal compilatore e dal calcolatore usato. Nel Turbo Pascal, il campo dei valori assunti da un numero reale spazia da 1.0E-38 a 1.0E+38, con una mantissa di 11 cifre significative. Le variabili di tipo real, incluso lo zero, sono scritte con il punto decimale, secondo la seguente forma: 0.0; 1.0; 0.223. 2. integer. Le costanti e le variabil di questo tipo possono assumere valori positivi o negativi, compresi tra maxint e – (maxint+1), dove maxint è una costante predefinita, dipendente dal sistema, che indica il massimo valore intero disponibile. Nel Turbo Pascal, maxint vale 32767 e i valori delle variabili di tipo integer possono oscillare da 32767 a –32768; i tipi integer occupano 2 byte (16 bit) di memoria e le costanti di tipo integer sono scritte senza punto decimale. Nel Turbo Pascal, inoltre, è lecita la notazione esadecimale per rappresentare grandezze di tipo integer e di tipo byte. Le costanti esadecimali iniziano con il carattere $, seguito dalle cifre esadecimali (0...F), come: $4A1; $A0; $FFCD. 3. boolean. Le variabili di questo tipo assumono il valore true o false. Esse richiedono un byte di memoria e rappresentano il risultato di espressioni logiche (relazionali), che sono contenute in istruzioni condizionali e che permettono al programma di prendere delle decisioni, sulla base del loro valore. Il linguaggio Pascal predefinisce le due costanti true e false, che il programma utilizza nelle espressioni logiche. 4. char. Nel Pascal Standard il tipo char indica sigoli caratteri, racchiusi tra due apici: ‘A’ ‘B’ ‘c’ ‘d’ ‘&’ ‘?’ ‘’ (spazio). La rappresentazione interna dei caratteri è in codifica 52 binaria. Nel confronto fra due caratteri, sono i codici corrispondenti che vengono nella realtà esaminati. Poiché la codifica dei caratteri dipende dal sistema (ASCII, EBCDIC, ecc.), il Turbo Pascal non definisce un set standard particolare di caratteri. Nel Turbo Pascal si può assegnare alle variabili e alle costanti di tipo char un qualunque carattere appartenente al set esteso dei caratteri ASCII, con valore ordinale compreso tra 0 e 255. Questo set esteso di caratteri ASCII permette al programmatore di utilizzare speciali caratteri grafici. Il programmatore può servirsi di valori costanti, racchiusi tra apici, oppure della funzione chr(), per assegnare valori di tipo char. Un valore di tipo char occupa un byte di memoria. 5. array. Nel Turbo Pascal, il programmatore può definire un array, i cui elementi siano di tipo semplice, come integer, real, char, byte, string e boolean. Sebbene tutti gli elementi di un array debbano essere dello stesso tipo, sono definibili anche array complessi, costituiti da elementi contenenti più di un singolo tipo di dato, utilizzando il record come tipo dell'elemento dell'array. Si può pensare ad un array come a un gruppo di celle numerate, ognuna delle quali contiene un dato. E' sufficiente usare il numero (o indice) corrispondente a tali celle, per referenziare direttamente il dato contenuto. L'indice che referenzia le celle dell'array, può essere un qualunque tipo scalare. In fase di dichiarazione dell'array è necessario indicare il tipo dell'indice oppure il campo di valori che l'indice stesso può assumere: questi valori possono essere interi positivi o negativi, oppure valori scalari interni ai limiti di campo dichiarati. Il tipo di indice definisce anche la massima dimensione degli array. Le versioni commerciali del turbo Pascal permettono di definire array di qualunque dimensione intera, purché contenuta in un'area di memoria inferiore a 64 kB. Ciò significa che quattro array di 16 kB di tipo byte (o due di 16 kB di tipo integer) possono occupare interamente lo spazio di memoria disponibile per l'allocazione dei dati. 6. byte. Questo tipo è, nel Turbo Pascal, un sottotipo del tipo integer e può, dunque, essere usato con le stesse modalità e nelle stesse circostanze del tipo integer. Un dato di tipo byte può assumere un valore intero compreso tra 0 e 255. Le variabili di tipo byte occupano un byte (8bit) di memoria e le costanti di tipo byte sono sempre scritte senza punto decimale o con due cifre nella notazione esadecimale. 53 7. string. Nel Turbo Pascal, una variabile del tipo predefinito string rappresenta una successione di caratteri molto simile ad un array. Il primo elemento (posizione zero) di questa struttura dati corrisponde al valore di un byte, che memorizza la lunghezza della stringa (compresa tra 0 e 255). Questo valore cambia se il programmatore assegna alla stringa oggetti di lunghezza differente. In fase di dichiarazione della variabile di tipo string, si alloca lo spazio corrispondente in memoria: var nome : string[maxlung] Nel corso di tutto il programma, non è possibile assegnare alla stringa nome un oggetto la cui lunghezza superi lo spazio di memoria allocato. Il programmatore può definire le stringhe come array. Variabili Le variabili sono oggetti identificati da un nome e il loro valore può cambiare nel corso dell'esecuzione del programma. Il tipo associato ad ogni variabile deve essere esplicitamente dichiarato, prima che la variabile venga referenziata nel programma. Le variabili Pascal non sono inizializzate automaticamente in fase di dichiarazione, ma è necessario assegnar loro esplicitamente un valore, altrimenti esse rimangono non definite. Procedure Le procedure sono gruppi di istruzioni (blocchi) che costituiscono un sottoprogramma in grado di eseguire determinate azioni. L’attivazione di una procedura avviene tramite una istruzione di chiamata di procedura , che si compone del nome o identificatore della procedura, seguito dalla lista di parametri, se esistono, che costituiscono gli argomenti della procedura. Al termine dell’esecuzione della procedura, il controllo si trasferisce all’istruzione del programma successiva a quella di chiamata della procedura. 54 Il Turbo Pascal predefinisce un certo numero di procedure, che eseguono operazioni di ingresso e di uscita, di gestione di stringhe, di visualizzazione sullo schermo, di manipolazione di file. Le procedure definite dall'utente sono, invece, dichiarate come gli altri oggetti del programma. La dichiarazione di procedura inizia con un’intestazione, seguita dal blocco della procedura. Il blocco della procedura può contenere dichiarazioni di altri oggetti, tra cui label, costanti, tipi, variabili, funzioni e procedure, che risultano locali al blocco stesso e ai blocchi annidati. Funzioni Anche le funzioni sono sottoprogrammi, ma vengono attivate in fase di valutazione di espressioni che contengono un riferimento alle funzioni stesse. Diversamente dalle procedure, le funzioni generalmente restituiscono un valore (risultato) all’espressione che le attiva e il loro uso riguarda in gran parte l’esecuzione di algoritmi logici o matematici. Anche per le funzioni è definito un passaggio di parametri simile a quello delle procedure. Il Turbo Pascal predefinisce un certo numero di funzioni, che eseguono calcoli e restituiscono un risultato; sono funzioni trigonometriche, di calcolo matematico di conversione. Le funzioni sono dichiarate come ogni altro oggetto del programma. Una dichiarazione di funzione inizia con un'intestazione, seguita dal blocco della funzione. Il blocco della funzione può contenere dichiarazioni di altri oggetti, tra cui label, costanti, tipi, variabili, funzioni e procedure, che risultano locali al blocco stesso e ai blocchi annidati. Il risultato della funzione è ottenuto assegnando , all’interno del blocco della funzione, un valore all’identificatore di funzione. Istruzioni 55 Le istruzioni di un programma rappresentano le azioni che il calcolatore deve eseguire e costituiscono il corpo dei blocchi del programma e dei sotto-programmi. Il Pascal definisce sia istruzioni semplici che istruzioni composte. Delle istruzioni semplici fanno parte l'istruzione di assegnamento, l'istruzione vuota, le istruzioni di chiamata di procedure e l'istruzione goto. Il Turbo Pascal definisce anche l’istruzione inline, che permette di inserire codice macchina nei programmi Pascal. Delle istruzioni composte fanno parte tutte le istruzioni ottenute disponendo sequenzialmente istruzioni semplici, l’istruzione condizionale, l’istruzione ripetitiva e l’istruzione with. Di seguito sono elencate alcune delle istruzioni più usate. 1. Istruzione di assegnamento. In ambiente Pascal, l’isturzione di assegnamento fa sì che una variabile assuma un nuovo valore. L’esecuzione di questa istruzione comporta che l’espressione a destra dell’operatore di assegnamento venga valutata e il valore così ottenuto sia assegnato alla variabile posta alla sinistra dell’operatore. Nel linguaggio Pascal, l’operatore di assegnamento è rappresentato dalla coppia di simboli “:=”. Un esempio di assegnamento è il seguente: totale:=(cost*1.3)+(variabile*0.8) 2. Istruzione di chiamata a procedura. E’ costituita dall’identificatore della procedura da attivare, seguito da un certo numero di parametri, che sono i valori da fornire in ingresso alla procedura stessa. Quando il calcolatore esegue questa istruzione, il controllo del programma passa al blocco della procedura attivata. Al termine dell’esecuzione della procedura attivata, il controllo ritorna all’istruzione immediatamente successiva a quella di chiamata. 3. Istruzioni composite. E’ una struttura di controllo che riunisce un gruppo di istruzioni, la cui escuzione avviene sequenzialmente. Essa si compone di una o più istruzioni, individualmente corrette, delimitate dalle parole riservate begin e end, e può contenere annidate al suo interno altre istruzioni composite. La forma generale di un’istruzione composita è la seguente: begin istruzione 1 istruzione 2 . 56 . . istruzione n end. 4. Istruzioni condizionali. L’istruzione condizionale decide, sulla base della valutazione di una condizione di controllo(true o false), in quale direzione far procedere il flusso escutivo. Le istruzioni condizionali sono: Istruzione if. Il costrutto “if a è true then esegui b” definisce uno dei concetti più semplici ed intuitivi della programmazione. L’istruzione if rappresenta la struttura di controllo fondamentale di programmazione: permette, infatti, di esguire un’istruzione (singola o composita ), sulla base della veridicità di una data condizione di controllo. La forma generale dell’istruzione if è la seguente: if condizione then istruzione (se condizione allora istruzione); Istruzione if...else. Rappresenta un’estensione dell’istruzione if...then e aggiunge chiarezza al programma che la usa qualora il programmatore debba decidere tra due flussi alternativi di istruzioni. La forma generale dell’istruzione if...else è la seguente: if condizione then istruzione 1 (se condizione allora istruzione 1) else istruzione 2 (altrimenti istruzione 2) Istruzione case. Costituisce una versione particolare dell’istruzione if...else, in quanto permette di selezionare ed eseguire un’istruzione singola all’interno di un gruppo di istruzioni. Il risultato della valutazione viene confrontato con le costanti elencate nella listacase, con lo scopo di verificarne la congruenza. La forma generale dell’istruzione case è la seguente: case espressione of lista 1 di costanti: istruzione 1; .... lista n di costanti: istruzione n 57 end; Istruzione case...else. Risolve esplicitamente il problema di mancata selezione di una delle alternative-case. La forma generale dell’istruzione case..else è la seguente : case espressione of lista 1 di costanti: istruzione 1; .... lista n di costanti: istruzione n else istruzione end; 5. Strutture iterative. Uno dei requisiti base, per la realizzazione di programmi di una certa complessità, è la disponibilità di strutture programmative che permettano l’esecuzione ripetuta di una sequenza di istruzioni, per tutto il tempo in cui un’espressione logica rimane true. Queste situazioni sono attuabili con le rispettive strutture iterative che seguono. Istruzione while. Garantisce, per tutto il tempo in cui la condizione di controllo rimane true, l’esecuzione ripetuta dell’istruzione-oggetto, singola o composita. Poiché, prima dell’esecuzione dell’istruzione-oggetto, avviene il test sulla condizione di controllo, il risultato di questa valutazione regola il numero di volte (zero o più) che la struttura while sarà eseguita. La forma generale dell’istruzione while è la seguente: while condizione do istruzione 58 Istruzione repeat...until. Garantisce l’esecuzione ripetuta di una o più istruzioni, fino a quando la corrispondente espressione di controllo non diventi true. L’esecuzione delle istruzioni-oggetto avviene almeno una volta, indipendentemente dal valore iniziale della condizione di controllo, il cui test, infatti, viene effettuato alla fine dell’esecuzione della struttura stessa. La forma generale dell’istruzione repeat...until è la seguente: repeat istruzione/i until condizione (ripeti) (istruzione) ( fino a che condizione) Istruzione for. Garantisce l’esecuzione, ripetuta per un certo numero di volte, di un’istruzione o di un gruppo di istruzioni. Di questa struttura fa parte una variabiledi controllo che si incrementa (to) o decrementa (downto) automaticamente di una unità ad ogni esecuzione del ciclo, passando da un valore iniziale ad un valore finale. All’interno della struttura for non deve esserci alcuna istruzione che modifichi il valore della variabile di controllo. La forma generale dell’istruzione for è la seguente: for variabile-controllo:= espressione1 to espressione 2 do istruzione oppure for variabile-controllo:= espressione1 downto espressione 2 do istruzione Formato e stile Il programmatore che scrive in linguaggio Pascal può definire per il suo programma un formato qualunque. Gli spazi bianchi o le linee separatrici hanno un preciso significato solo quando sono usate per isolare gli identificatori e le parole riservate, oppure nelle costanti di tipo stringa. Le istruzioni possono essere disposte secondo formati diversi per migliorare la 59 leggibilità del programma, ma il compilatore non considera il formato scelto, quando interpreta il codice sorgente. Il Turbo Pascal permette di scrivere linee di 127 caratteri come lunghezza massima, e il programmatore può decidere come disporre i caratteri su ogni linea. Punteggiatura I programmi in Pascal utilizzano tre caratteri fondamentali di punteggiatura: la virgola (,), il punto e virgola (;) e il punto (.). La virgola ha il compito di separare gli elementi di una lista; il punto e virgola separa tra loro le istruzioni e non segue mai l'ultima di esse; il punto, infine, permette di terminare il programma e segue sempre l'ultimo delimitatore di fine blocco end. Ciò permette al compilatore di verificare che ogni delimitatore di inizio blocco begin abbia il corrispondente delimitatore di fine blocco end. Commenti Il programmatore può inserire commenti in qualunque punto del programma Pascal, purché li racchiuda tra i delimitatori "{" e "}" o, indifferentemente, tra i delimitatori "(*" e "*)". Operatori Il Turbo Pascal definisce diverse classi di operatori, in corrispondenza di vari tipi di espressioni, e definisce sei livelli di precedenza, in base alla natura delle operazioni eseguite. Questi livelli sono, in ordine decrescente: 1. Espressioni racchiuse tra parentesi ( ). 2. Conversione di segno o negazione. 3. Operatore not. 4. Operatori di moltiplicazione aritmetica e logica: * / div mod and shl shr. 60 5. Operatori di somma aritmetica e logica: + - or xor. 6. Operatori relazionali: = < > < > <= >= in. Operatori aritmetici Il Pascal definisce sei operatori aritmetici: +, -, *, /, dvi, mod. Questi operatori permettono di eseguire le usuali operazioni algebriche di addizione, di sottrazione e negazione, di moltiplicazione, di divisione fra interi e fra reali e di resto della divisione fra interi. Operatori binari Il Turbo Pascal definisce un insieme di operatori binari per manipolare singoli bit di valori integer e byte. Le espressioni che contengono questi operatori realizzano un'interfaccia con la struttura hardware del calcolatore: il programmatore infatti può modificare direttamente i singoli bit di una certa variabile. I tipi di operatori binari sono: not, and, or, xor, shr, shl. Operatori logici Degli operatori logici fanno parte: 1. Operatori booleani; questo tipo di operatori (not, and, or e xor) consetono di costruire le not epressioni logiche booleane : complementa il valore booleano dell'espressione logica che lo segue (not true = false) and l'espressione logica è vera se sono veri entrambi gli operandi (true and false = false) 61 or l'espressione logica è vera se è vero uno degli operandi (true or false = true) xor l'espressione logica è vera se è vero un solo operando (true xor false = true). 2. Operatori relazionali; Gli operatori relazionali si applicano ad operandi di qualunque tipo scalare standard: real, integer, boolean, char e byte. Il risultato è sempre di tipo boolean cioè true o false. Gli operatori relazionali disponibili nel Turbo Pascal sono i seguenti: = uguale a < > diverso da > maggiore di < minore di >= maggiore o uguale a <= minore o uguale a. 62 PROGRAMMI DI GESTIONE DELLE INTERFACCE Interfaccia relè, display 7 segmenti, led, dip-switch PROGRAM INTERFACCIA(INPUT,OUTPUT); USES CRT; VAR K : INTEGER; ADDR, LED, DIP, RELE, DISPLAY:WORD; PROCEDURE PLED; { PROGRAMMA DI GESTIONE DIODI LED } VAR N:ARRAY[1..41] OF BYTE; { APERTURA DI UN VETTORE N } K: INTEGER; { DICHIARAZIONE VARIABILE CONTATORE } BEGIN { I LED SI ACCENDONO CONVERGENDO DAGLI ESTREMI VERSO IL CENTRO } N[1]:=$00; N[2]:=$81; N[3]:=$42; N[6]:=$24; N[7]:=$42; N[4]:=$24; N[5]:=$18; N[8]:=$81; N[9]:=$00; { UN SOLO LED ACCESO PARTENDO DA L8 VERSO L1 } N[10]:=$80; N[13]:=$10; N[11]:=$40; N[12]:=$20; N[14]:=$08; N[15]:=$04; N[16]:=$02; 63 { ACCENSIONE PROGRESSIVA DEI LED DA DESTRA VERSO SINISTRA RIEMPIMENTO PROGRESSIVO DEL REGISTRO } N[17]:=$01; N[18]:=$03; N[19]:=$07; N[22]:=$3F; N[23]:=$7F; N[20]:=$0F; N[21]:=$1F; N[24]:=$FF; { UN SOLO LED ACCESO ALTERNATIVAMENTE PRIMA L8 QUINDI L1 POI L7 E QUINDI L2 E COSÌ VIA } N[25]:=$00; N[26]:=$80; N[27]:=$01; N[30]:=$20; N[31]:=$04; N[34]:=$10; N[35]:=$04; N[38]:=$40; N[39]:=$01; N[28]:=$40; N[29]:=$02; N[32]:=$10; N[33]:=$08; N[36]:=$20; N[37]:=$02; N[40]:=$80; N[41]:=$FF; PORT[DISPLAY]:=$00; PORT[RELE]:=$00; FOR K:=1 TO 41 DO BEGIN PORT[LED]:=N[K]; { OPERAZIONE DI SCRITTURA SUI LED } DELAY(200); GOTOXY(11,19); { RITARDO 200MS } WRITE(K);{ POSIZIONAMENTO DEL CURSORE COORDINATE 11,19 } GOTOXY(7,15); WRITE('QUESTA PROCEDURA È IN GRADO DI FARE ACCENDERE'); GOTOXY(7,16); WRITE('8 DIODI LED IN VARI TIPI DI SEQUENZA'); END; 64 END; PROCEDURE PDIP; { PROGRAMMA DI GESTIONE DIP-SWITCH LEGGE IL DATO PRESENTE SUL DIP-SWITCH E POI LO TRASFERISCE SUL DISPLAY A 7 SEGMENTI } VAR J:BYTE; BEGIN GOTOXY(7,15); WRITE('QUESTA PROCEDURA PERMETTE DI VISUALIZZARE'); GOTOXY(7,16); WRITE('SUL DISPLAY IL VALORE IMPOSTATO SUL DIP-SWITCH'); REPEAT J:=PORT[DIP]; { INIZIO CICLO RIPETITIVO } { OPERAZIONE DI LETTURA DAI DIP- SWITCH } J:=255-J; { CONVERSIONE DA LOGICA NEGATIVA A POSITIVA } PORT[DISPLAY]:=J; { OPERAZIONE DI SCRITTURA SUI DISPLAY GOTOXY(11,19); WRITE(J:4); } UNTIL FALSE; { CONDIZIONE DI LOOP INFINITO } END; PROCEDURE PRELE; { PROGRAMMA DI GESTIONE DEI RELÈ } VAR DATO:BYTE; H:BYTE; BEGIN DATO:=0; PORT[RELE]:=$00; { SPEGNIMENTO DEI RELE } PORT[LED]:=$00; { SPEGNIMENTO DEI LED } K:=PORT[DIP]; { LETTURA DEL VALORE IMPOSTATO SUL DIP-SWITCH } 65 K:=255-K; GOTOXY(11,19); WRITE(K); GOTOXY(7,15); WRITE('QUESTA PROCEDURA PERMETTE DI AZIONARE I RELE'); GOTOXY(7,16); WRITE('IN SEQUENZA OGNI 16 CONTEGGI VISUALIZZATI DAL'); GOTOXY(7,17); WRITE('DISPLAY PARTENDO DAL VALORE 03'); READLN; REPEAT GOTOXY(19,19);WRITE(DATO:4); PORT[DISPLAY]:=DATO; { SCRITTURA DEL DATO SUL DISPLAY } IF (DATO MOD 16)=3 THEN BEGIN { QUESTA ISTRUZIONE PERMETTE DI ATTIVARE } { UN RELE OGNI 16 IMPULSI } H:=(((DATO DIV 16)+1) MOD 4)+1; { CONVERSIONE DEL RISULTATO INTERO } { DI DATO/16 IN BASE 4 PER ATTIVARE IL RELE CORRISPONDENTE } GOTOXY(27,19);WRITE('RELE: ',(((H+2) MOD 4)+1):2); CASE H OF 1 : PORT[RELE]:=$40; { INDIRIZZO CORRISPONDENTE AL RELE 1 } 2 : PORT[RELE]:=$01; 3 : PORT[RELE]:=$10; 4 : PORT[RELE]:=$04; END; END; DATO:=DATO+1; DELAY(500); UNTIL DATO=K+1; END; PROCEDURE PDISPLAY; 66 VAR DATO,K : BYTE; BEGIN DATO:=0; K:=PORT[DIP]; K:=255-K; GOTOXY(11,19); WRITE(K); GOTOXY(7,15); WRITE(' QUESTA PROCEDURA PERMETTE DI FARE '); GOTOXY(7,16); WRITE(' AVANZARE I DISPLAY FINO AL NUMERO '); GOTOXY(7,17); WRITE(' FISSATO SUI DIP- SWITCH '); READLN; REPEAT GOTOXY(19,19);WRITE(DATO); PORT[DISPLAY]:=DATO; DATO:=DATO +1; DELAY(500); UNTIL DATO=K+1; END; BEGIN { PROGRAMMA PRINCIPALE MAIN } CLRSCR; ADDR:=$300; { $300-$307 CAMPO DI INDIRIZZAMENTO DELLA SCHEDA } LED:=ADDR; DIP:=ADDR+$1; RELE:=ADDR+$2; DISPLAY:=ADDR+$3; REPEAT CLRSCR; 67 GOTOXY(10,3); WRITE(' 1- GESTIONE LED '); GOTOXY(10,5); WRITE(' 2- GESTIONE DISPLAY'); GOTOXY(10,7); WRITE(' 3- GESTIONE RELE'''); GOTOXY(10,9); WRITE(' 4- GESTIONE DIPSWITCH'); GOTOXY(10,11); WRITE(' 0- FINE'); GOTOXY(11,13); READLN(K); CASE K OF 1:PLED; 2:PDISPLAY; 3:PRELE; 4:PDIP; END; UNTIL K=0; END. Interfaccia controllo di temperatura ed umidità PROGRAM TEMP_UMID; USES CRT; TYPE STR80 = STRING[80]; CONST SCHEDA=$300; PA=SCHEDA+$0; 68 PB=SCHEDA+$1; PC=SCHEDA+$2; CW=SCHEDA+$3; SCHEDA1=$308; PA1=SCHEDA1+$0; PB1=SCHEDA1+$1; PC1=SCHEDA1+$2; CW1=SCHEDA1+$3; VAR I, C : INTEGER; NO : STR80; CHIAVE: CHAR; PROCEDURE INIT_8255; BEGIN PORT[CW]:=$81;{ PORT A USCITA; PORT B USCITA; PC4-PC7 USCITA; PC0-PC3 INGRESSO } END; PROCEDURE INIT_8255A;{PORT A INGRESSO: COLLEGATO ALL'ADC DA D0 A D7 PORT B USCITA: COLLEGATO ALL'ADC, PBO AD A0, PBI AD A1, PB2 AD A2, PB3 A START PB4 AD ALE PORT C INGRESSSO (DA PC0 A PC3): COLLEGATO ALL'ADC PC0 ALL'EOC PORT C USCITA (DA PC4 A PC7): COLLEGATO AI LED, PC4 A T1, PC5 A T2 PC6 A U1, PC7 AU2} BEGIN PORT[CW1]:=$91; END; PROCEDURE PAUSE; BEGIN DELAY(2); END; PROCEDURE LCD_CMD1(C:BYTE); VAR H:BYTE; BEGIN H:=PORT[PB] AND $9F; {LEGGE PORT PB E AZZERA RS E RW} PORT[PB]:= H; PORT[PA]:=C; H:=H OR $10; {ALZA ENABLE} PORT[PB]:=H; 69 PORT[PB]:=H AND $EF; PAUSE; END; PROCEDURE LCD_CHAR1(C:CHAR); VAR A:BYTE; BEGIN A:=PORT[PB] AND $9F; {LEGGE PORT PB E AZZERA RS E RW} A := A OR $40; PORT[PB]:=A ; PORT[PA]:= ORD(C); A:=A OR $10; PORT[PB]:=A; PORT[PB]:=A AND $EF; PAUSE; END; PROCEDURE INIT_LCD1; BEGIN LCD_CMD1($30); { 8 BIT + 1 LINEA + 5 X 7 DOTS } LCD_CMD1($30); LCD_CMD1($30); LCD_CMD1($34); LCD_CMD1($08); LCD_CMD1($0E); END; PROCEDURE CLEAR1; { CANCELLA TUTTO IL DISPLAY E PORTA IL CURSORE POSIZIONE HOME (INDIRIZZO 0) } BEGIN LCD_CMD1($01); DELAY(20); END; PROCEDURE HOME1; BEGIN LCD_CMD1($02); DELAY(20); END; PROCEDURE LCD_STR1(STR:STRING); VAR I,LS : INTEGER; BEGIN LS := LENGTH(STR); IF LS > 40 THEN LS := 40; 70 FOR I := 1 TO LS DO LCD_CHAR1(STR[I]); END; PROCEDURE LCD_CMD2(C:BYTE); VAR H:BYTE; BEGIN H:=PORT[PB] AND $9F; {LEGGE PORT PB E AZZERA RS E RW} PORT[PB]:= H; PORT[PA]:=C; H:=H OR $80; {ALZA ENABLE} PORT[PB]:=H; PORT[PB]:=H AND $7F; PAUSE; END; PROCEDURE LCD_CHAR2(C : CHAR); { INVIO DI UN CARATTERE ALL' LCD } VAR A:BYTE; BEGIN A:=PORT[PB] AND $9F; {LEGGE PORT PB E AZZERA RS E RW} A := A OR $40;{ALZA RS} PORT[PB]:=A ; PORT[PA]:= ORD(C); A:=A OR $80; {E2 A 1} PORT[PB]:=A; PORT[PB]:=A AND $7F; {E2 A 0} PAUSE; END; PROCEDURE CLEAR2; { CANCELLA TUTTO IL DISPLAY E PORTA IL CURSORE IN POSIZIONE HOME (INDIRIZZO 0) } BEGIN LCD_CMD2($01); DELAY(40); END; PROCEDURE HOME2; BEGIN LCD_CMD2($02); DELAY(40); END; PROCEDURE LCD_LEFT; BEGIN LCD_CMD2($18); END; 71 PROCEDURE LCD_RIGHT; BEGIN LCD_CMD2($1C); END; PROCEDURE INIT_LCD2; BEGIN LCD_CMD2($3C); { 8 BIT + 1 LINEA + 5 X 8 DOTS } LCD_CMD2($3C); LCD_CMD2($1C); LCD_CMD2($06); LCD_CMD2($0C); END; FUNCTION LEGGI_CONTRAVES(N:BYTE):INTEGER; VAR C,A:BYTE; BEGIN C:=PORT[PB] AND $F0;{LEGGO LA SITUAZIONE SUL PORT B E MASCHERO LA PARTE ALTA} C:=C OR (N SHL 1); PORT[PB]:=C; PORT[PB]:=C OR $01;{ ABILITA IL 74LS138} A:=PORT[PC]; { ASSEGNA ALLA VARIABILE IL VALORE DEL PORT C } A:=NOT(A);{ RIPORTO IL DATO IN LOGICA POSITIVA } LEGGI_CONTRAVES:=A AND $0F; PORT[PB]:=C; END; FUNCTION U2:INTEGER; VAR A:INTEGER; BEGIN A:= LEGGI_CONTRAVES(1)*10 + LEGGI_CONTRAVES(0); IF A=0 THEN BEGIN LCD_STR1('IMPOSTARE SOGLIA U2'); DELAY(2000); END ELSE CLEAR1; U2:=A; END; FUNCTION U1:INTEGER; VAR A:INTEGER; BEGIN A:= LEGGI_CONTRAVES(3)*10 + LEGGI_CONTRAVES(2); 72 IF A=0 THEN BEGIN LCD_STR1('IMPOSTARE SOGLIA U1'); DELAY(2000); END ELSE CLEAR1; U1:=A; END; FUNCTION T2:INTEGER; VAR A:INTEGER; BEGIN A:= LEGGI_CONTRAVES(5)*10 + LEGGI_CONTRAVES(4); IF A=0 THEN BEGIN LCD_STR1('IMPOSTARE SOGLIA T2'); DELAY(2000); END ELSE CLEAR1; T2:=A; END; FUNCTION T1:INTEGER; VAR A:INTEGER; BEGIN A:= LEGGI_CONTRAVES(7)*10 + LEGGI_CONTRAVES(6); IF A=0 THEN BEGIN LCD_STR1('IMPOSTARE SOGLIA T1'); DELAY(2000); END ELSE CLEAR1; T1:=A; END; FUNCTION ADCONV (CHANNEL:INTEGER) : INTEGER; VAR A:REAL; BEGIN A:=1; PORT[PB1]:= ((PORT[PB1] AND $F8) OR (CHANNEL AND $7)); A:=A+A; PORT[PB1]:= (PORT[PB1] OR $10); {ALE A 1} A:=A+A; PORT[PB1]:= (PORT[PB1] AND $EF);{ALE A 0} A:=A+A; 73 PORT[PB1]:= (PORT[PB1] OR $8); {START A 1} A:=A+A; PORT[PB1]:= (PORT[PB1] AND $F7);{START A 0} A:=A+A; WHILE (PORT[PC1] AND 1) = 0 DO ADCONV:= PORT[PA1]; END; FUNCTION T1M:INTEGER; VAR B:INTEGER; BEGIN B:= ADCONV(7); IF (B>T1) THEN BEGIN LCD_STR1('SUPERATA SOGLIA T1'); DELAY(2000); END ELSE CLEAR1; T1M:=B; END; FUNCTION T2M:INTEGER; VAR B:INTEGER; BEGIN B:= ADCONV(4); IF (B>T2) THEN BEGIN LCD_STR1('SUPERATA SOGLIA T2'); DELAY(2000); END ELSE CLEAR1; T2M:=B; END; FUNCTION U1M:INTEGER; VAR B:INTEGER; BEGIN B:= ADCONV(5); IF (B>U1) THEN BEGIN LCD_STR1('SUPERATA SOGLIA U1'); DELAY(2000); END 74 ELSE CLEAR1; U1M:= B{*100.0/255;} END; FUNCTION U2M:INTEGER; VAR B: INTEGER; BEGIN B:= ADCONV(6); IF (B>U2) THEN BEGIN LCD_STR1('SUPERATA SOGLIA U2'); DELAY(2000); END ELSE CLEAR1; U2M:= B{*100.0/255}; END; PROCEDURE ALL_T1; BEGIN IF (T1M>T1) THEN PORT[PC1]:=PORT[PC1] OR $10 ELSE PORT[PC1]:=PORT[PC1] AND $EF; END; PROCEDURE ALL_T2; BEGIN IF (T2M>T2) THEN PORT[PC1]:=PORT[PC1] OR $20 ELSE PORT[PC1]:=PORT[PC1] AND $DF; END; PROCEDURE ALL_U1; BEGIN IF (U1M>U1) THEN PORT[PC1]:=PORT[PC1] OR $40 ELSE PORT[PC1]:=PORT[PC1] AND $BF; END; PROCEDURE ALL_U2; BEGIN IF (U2M>U2) THEN PORT[PC1]:=PORT[PC1] OR $80 ELSE PORT[PC1]:=PORT[PC1] AND $7F; END; 75 PROCEDURE LCD_STR2(STR:STRING); VAR I,LS : INTEGER; BEGIN LS := LENGTH(STR); IF LS > 80 THEN LS := 80; FOR I := 1 TO LS DO LCD_CHAR2(STR[I]); END; PROCEDURE CLEAR_STR; VAR I:INTEGER; BEGIN NO:=''; FOR I := 1 TO 80 DO NO := NO + ' '; END; PROCEDURE TEMP1(T1,T1M:INTEGER); VAR S,S1:STRING; I:INTEGER; BEGIN S:= 'T1_I'; FOR I:=1 TO LENGTH(S) DO NO[I]:=S[I]; STR(T1:2,S1); FOR I:=1 TO LENGTH(S1) DO NO[I+5]:=S1[I]; S:='T1_M'; FOR I:=1 TO LENGTH(S) DO NO[I+8]:=S[I]; STR(T1M:2,S1); FOR I:=1 TO LENGTH(S1) DO NO[I+13]:=S1[I]; END; PROCEDURE UMID1(U1,U1M:INTEGER); VAR S,S1:STRING; I:INTEGER; BEGIN S:= 'U1_I'; FOR I:=1 TO LENGTH(S) DO NO[I+40]:=S[I]; STR(U1:2,S1); FOR I:=1 TO LENGTH(S1) DO NO[I+45]:=S1[I]; S:='U1_M'; FOR I:=1 TO LENGTH(S) DO NO[I+48]:=S[I]; STR(U1M:2,S1); FOR I:=1 TO LENGTH(S1) DO NO[I+53]:=S1[I]; END; PROCEDURE TEMP2(T2,T2M:INTEGER); VAR S,S1:STRING; I:INTEGER; BEGIN S:= 'T2_I'; 76 FOR I:=1 TO LENGTH(S) DO NO[I+16]:=S[I]; STR(T2:2,S1); FOR I:=1 TO LENGTH(S1) DO NO[I+21]:=S1[I]; S:='T2_M'; FOR I:=1 TO LENGTH(S) DO NO[I+24]:=S[I]; STR(T2M:2,S1); FOR I:=1 TO LENGTH(S1) DO NO[I+29]:=S1[I]; END; PROCEDURE UMID2(U2,U2M:INTEGER); VAR S,S1:STRING; I:INTEGER; BEGIN S:= 'U2_I'; FOR I:=1 TO LENGTH(S) DO NO[I+56]:=S[I]; STR(U2:2,S1); FOR I:=1 TO LENGTH(S1) DO NO[I+61]:=S1[I]; S:= 'U2_M'; FOR I:=1 TO LENGTH(S) DO NO[I+64]:=S[I]; STR(U2M:2,S1); FOR I:=1 TO LENGTH(S1) DO NO[I+69]:=S1[I]; END; BEGIN INIT_8255; INIT_8255A; INIT_LCD1; INIT_LCD2; CLEAR1; CLEAR2; CLRSCR; CHIAVE:=CHR(0); {ASCII_TEST;} REPEAT {CLEAR2;} CLEAR_STR; TEMP1(T1,T1M); UMID1(U1,U1M); TEMP2(T2,T2M); UMID2(U2,U2M); WRITELN(NO:80); LCD_STR2(NO); ALL_T1; ALL_T2; ALL_U1; ALL_U2; 77 DELAY(5000); IF KEYPRESSED THEN CHIAVE:= READKEY; UNTIL CHIAVE=CHR(27); END. Massa Reset GND RESET B1 A1 I/O L I/O CH Channel CK check B2 A2 D7 MSB Dati DRV Appendice A : Espanzione PC Alimentazione +5V B3 A3 D6 Richiesta di IRQ2 B4 A4 D5 -5V B5 A5 D4 DRQ2 B6 A6 D3 Alimentazione -12V B7 A7 D2 0 stati di attesa OWS B8 A8 D1 Alimentazione +12V B9 A9 D0 Massa GND B10 A10 I/O Bus XT (8 bit) Interrupt 2 Alimentazione Richiesta DMA2 LSB Dati CH RDY Scrittura in MEMW LB11 A11 AEN Memoria Lettura in e Indirizzi MEMR LB12 A12 A19 Memoria IOW LB13 A13 A18 Lettura I/O IOR LB14 A14 A17 DACK3 LB15 A15 A16 richiesta DMA3 Richiesta DMA3 DRQ3 Riconoscimento DACK1 B16 A16 A15 LB17 A17 A14 richiesta DMA1 Richiesta DMA1 Refresh DRQ1 B18 A18 A13 REFRESH LB19 A19 A12 memoria Clock da scheda CLK B20 A20 A11 IRQ7 B21 A21 A10 madre Richiesta di Interrupt 7 MSB Indirizzi Scrittura I/O Riconoscimento L Abilitazion 78 Tabella? di