Indirizzi e-mail a cui far pervenire osservazioni, critiche e
Transcript
Indirizzi e-mail a cui far pervenire osservazioni, critiche e
Indirizzi e-mail a cui far pervenire osservazioni, critiche e suggerimenti atti a migliorare la guida. [email protected] [email protected] GUIDA ALL’USO E ALLA PROGRAMMAZIONE DI UN MICROCONTROLLORE “PIC” - INTRODUZIONE Un microcontrollore PIC e` un gioiello della tecnologia attuale, questo a differenza dei tipici microprocessori e` qualcosa di piu` elaborato, infatti è capace di interagire con il mondo esterno attraverso numerose periferiche che si trovano gia` al suo interno. In realta` un microcontrollore lo possiamo considerare come un computer completo, racchiuso in un unico circuito integrato. La sigla PIC sta per : “Programmable Interface Controller”, ed è una varieta` specifica di microcontrollori creata dalla “Microchip”. Naturalmente come tutti i microcontrollori, hanno anche una vasta gamma di linguaggi di programmazione, pertanto ho scelto per questa guida il linguaggio C; utilizzando nello specifico il compilatore “Mikro C” distribuito da “Mikroelektronika”; invece per quanto riguarda il microcontrollore ho scelto il “PIC16F84A”. 1. REALIZZAZIONE DI UN PROGRAMMATORE JDM PER PIC Nel primo punto della nostra guida proponiamo l’autocostruzione di un programmatore per Pic. Nel nostro caso per iniziare abbiamo scelto un programmatore semplice da costruire, soprattutto molto più economico dei vari programmatori di Pic esistenti sul mercato. Inoltre c’è da dire che questo programmatore proprio perché è economico non è molto affidabile quindi consigliamo di realizzare questo circuito solo per muovere i primi passi nel mondo dei microcontrollori Pic. Lo schema e` il seguente : SCHEMA ELETTRICO: Come si nota il circuito e` molto semplice, in quanto non esistono eccessivi componenti elettronici. L’intero circuito e` formato infatti da uno zoccolo a 18 piedini che ospita un microcontrollore della serie PIC 16XXX, l’alimentazione e` fornita` dall’USB ed in parte dalla porta seriale. La porta RB6 del Pic (piedino 12) e` collegata direttamente al terminale RTS della seriale (piedino 7) e trasporta il segnale di clock. La porta RB7 del Pic (piedino 13) e` collegata ai terminali DTR e CST della seriale (rispettivamente il piedino 4 e 8) e trasporta il segnale dei dati. Il piedino VSS del Pic (piedino 5) e` collegato La porta MCLR del Pic (piedino 4 Reset) e` collegata al terminale TxD della seriale (piedino 3), in piu` sul piedino 4 del Pic vi e` collegato un led che ci indica qualitativamente se il programmatore e` in funzione. Infine il piedino VDD del pic (piedino 14) e` collegato alla sorgente di alimentazione attraverso il piedino 1 della USB e tramite la resistenza per assicurare un potenziale continuo al microcontrollore fornendo un minimo di protezione al circuito, limitando la corrente. Pagina 2 di 23 CIRCUITO STAMPATO N.b = I due circuiti stampati sono in dimensioni reali La sua realizzazione e` molto semplice e` richiede poco tempo (circa mezz’ora). Puo` essere realizzato su millefori oppure su circuito stampato con l’uso dei trasferibili, visto che non vi sono troppe piste e fori. Una volta preparato lo stampato, si possono saldare i componenti, iniziando dalle resistenze (perche` hanno un profilo piu` basso), di conseguenza lo zoccolo i led, ed infine i due connettori per la seriale e per la USB. 2. SOFTWARE PER LA PROGRAMMAZIONE DEL PIC Esistono vari programmi in rete, compatibili con questo programmatore, ma ritengo che il piu` completo, freeware e soprattutto in lingua italiana sia Ic-Prog, scaricabile dal sito http://www.ic-prog.com/; compatibile con la maggior parte dei microcontrollori della Microchip esistenti sul mercato. Per iniziare ad usare il software, si consiglia di scaricare la versione 1.05 C dal seguente link: http://www.ic-prog.com/icprog105C.zip; e di scompattare tutti i file *.zip uno per uno in una cartella, includendo anche i plug-ins IC-Prog NT/2000 driver e Helpfile in Italian language scaricandoli dai seguenti link : (http://www.ic-prog.com/icprog_driver.zip e http://www.ic-prog.com/guida.zip). Avviare l’eseguibile “icprog.exe” (se usate Windows NT/2000/Xp/Vista/7 e compaiono messaggi di errore, si prega di consultare la appendice 5 Risoluzione dei problemi/Errore privileged instruction. Pagina 3 di 23 In seguito cliccate nel menù Settaggi /hardware e impostare nel menù a tendina “programmatore”: “JDM Programmer”, e spuntare anche l’impostazione “API di Windows” nel menù “Interfaccia”. Per completezza selezionate nel menù Settaggi/Chip/Microchip PIC/Altro /PIC16F84A. Infine per impostare il vostro Ic-Prog in Italiano impostate “italian” nel menù a tendina “language” in Settings/Options/ language Dopo aver settato completamente il software vi troverete davanti un interfaccia grafica di questo tipo: Pagina 4 di 23 Dove alcuni pulsanti della barra degli stumenti del programma sono spiegati di seguito: Serve per selezionare i file da scrivere, all’interno della E2prom (Rom) del Pic. Come vedremo in seguito, dovremo selezionare in questo menu solo file con l’estensione “*.hex” cioe` il vero e proprio file in linguaggio macchina che verrà caricato nella E2prom del Pic. Serve per leggere il contenuto della E2prom del Pic, inoltre ci potrebbe servire per verificare il contenuto della E2prom del Pic per dei controlli. Questo pulsante serve per programmare, fisicamente (scrivere) l’E2prom del nostro Pic, sempre dopo aver caricato i file dal menu, apri. Pagina 5 di 23 3. IL COMPILATORE Anche dal punto di vista dei compilatori, in rete ne esistono di tante tipologie, ma per questa guida ho scelto un compilatore C distribuito dalla Mikroelektronika cioe` “MicroC”, scaricabile dal sito http://www.mikroe.com./ . Per iniziare ad usare il software scaricare questo, dal sito prima indicato, in seguito munirsi di una licenza valida distribuita dallo stesso sito ed avviare l’installazione. Dopo aver installato il programma, esso si presenterà` cosi`: Per iniziare a editare un programma cliccare dal Menù Project/New Project… . Pagina 6 di 23 In questa finestra vi inseriamo il nome del programma che vogliamo creare (in “Project Name”), la destinazione dei file che andra` a creare (in “Project Path”; inoltre apriamo una nuova cartella altrimenti i file potrebbero disperdersi), in seguito vi inseriamo un commento (facoltativo) in “Description”. Infine specifichiamo il pic (P16F84A) con l’opportuna frequenza di clock (in “Device) espressa in MHz. In piu` in “Device Flag” selezioniamo il tipo di oscillatore che stiamo usando (esempio XT_OSC per un quarzo oppure RC_OSC per un Oscillatore Resistenza_Condensatore). Dopo aver impostato i valori, in New Project, possiamo scrivere il programma in linguaggio C++ (consultare l’appendice 6 “Cenni sulla programmazione in c++”), in seguito per compilare il programma cliccate su Project/Build. Se tutto è andato a buon fine (quindi non ci sono errori di sintassi all’interno del programma) nella tabella inferiore vi segnalerà il buon esito, e nella nostra cartella (creata precedentemente) troveremo salvato il listato in c++ e il programma vero è proprio (con estensione *.hex) compilato in linguaggio macchina, da programmare nella E2prom del nostro pic. Pagina 7 di 23 4.PROGRAMMAZIONE FISICA DEL PIC Adesso con il programma Ic-Prog Apriamo il file “*.hex” nella cartella che abbiamo creato. Inseriamo il programmatore nella porta seriale del nostro Pc, e con il Pic gia` montato sullo zoccolo, premiamo il pulsante “programma tutto”. . L’interfaccia Grafica si presenterà cosi: Il Pic è pronto all’uso, me se dovrebbe verificarsi un errore del tipo “Verifica fallita al code address 0000h !” consultare la sezione “risoluzione dei problemi/Fallita Programmazione al Code address 0000h” 5.RISOLUZIONE DEI PROBLEMI Errore : Privileged instuctuion Se avviate per la prima volta Ic-Prog su windows NT/2000/Xp/Vista/7, e vi compare questo messaggio di errore, premete OK per saltarlo, poi nel menu Settings/Options/Misc spuntare l’opzione “Enable NT/2000/XP driver”. In seguito vi compariranno i seguenti messaggi di conferma : confermate tutto premendo YES, Ic-prog si riavvierà da solo, altrimenti riavviatelo manualmente. Pagina 8 di 23 Fallita Programmazione al Code address 0000h Questo messaggio di errore compare frequentemente, quando si programmano i microcontrollori (PIC). Le cause di questo errore possono dipendere da molti fattori: • • • • • • • • Verificare Il cavo usato per collegare il programmatore al PC: Usare solo prolunghe a 9 poli Pin-to-Pin, disponibili nei negozi di elettronica; Verificare se i settaggi sono giusti: IcProg va settato a seconda del programmatore usato (JDM Programmer). Inoltre, bisognerà indicare la porta in uso (Com1 o Com2). Verificare se la seriale del Pc fornisce abbastanza tensione al nostro programmatore: in questo caso bisognerà modificare il programmatore (saldando due fili in uscita della porta USB montata sul circuito stampato) in modo da poterlo alimentarre rigorosamente a 5V. Verificare se è stato installato il driver per Windows NT/2000/XP: Lo trovate in allegato, va inserito nella stessa cartella di IcProg e andrà attivato da Settaggi -> Opzioni -> Misc -> "Abilita il driver NT/2000/XP". Verificare se è abilitato il Code protect : se il CP è abilitato IcProg non riesce a verificare il contenuto della memoria programma del PIC, quindi "crede" che la programmazione non sia andata a buon fine; Controllare quindi, attraverso la casella di controllo, che il code protect sia disabilitato. Verificare se il programmatore è alimentato: (LED Power on acceso); Verificare se il microcontrollore (PIC) è funzionante :o se è stato montato correttamente sul programmatore. Per evitare qualsiasi errore: verificate la funzionalità del programmatore nel menù Settaggi \ Controllo Hardware; verificare se il segnale arriva al dispositivo, spuntando “Attiva Data Out”, e osservare se “Data In” si spunta autonomamente. Inoltre spuntando “Attiva MCLR” sul nostro programmatore JDM vediamo accendersi il led rosso. Pagina 9 di 23 6.CENNI SULLA PROGRAMMAZIONE IN C ++ -VARIABILI Tipo Descrizione Size* char Character or small integer. 1byte short int (short) Short Integer. 2bytes int Integer. 4bytes long int (long) Long integer. 4bytes float double long double Boolean value. It can take one of two values: true or false. Floating point number. Double precision floating point number. Long double precision floating point number. wchar_t Wide character. bool Range* signed: -128 to 127 unsigned: 0 to 255 signed: -32768 to 32767 unsigned: 0 to 65535 signed: -2147483648 to 2147483647 unsigned: 0 to 4294967295 signed: -2147483648 to 2147483647 unsigned: 0 to 4294967295 1byte true or false 4bytes 8bytes +/- 3.4e +/- 38 (~7 digits) +/- 1.7e +/- 308 (~15 digits) 8bytes +/- 1.7e +/- 308 (~15 digits) 2 or 4 bytes 1 wide character * I valori delle colonne Size e Range dipendono dal sistema dove viene compilato il programma. I valori riportati sono quelli che si trovano sulla maggior parte dei sistemi a 32-bit. -DICHIARAZIONE DI VARIABILE Tale dichiarazione può comprendere anche la sua inizializzazione tipo identificatore = espressione; ES : int voto = 3 + 5; -OPERATORI ARITMETICI + (SOMMA) - (SOTTRAZIONE) * (MOLTIPLICAZIONE) / (DIVISIONE) % (RESTO DI UNA DIVISIONE) - OPERATORI DI CONFRONTO O RELAZIONALI < (MINORE ) <= (MINORE UGUALE) > (MAGGIORE ) >= (MAGGIORE O UGUALE ) = = (UGUALE) ! = (DIVERSO) Dove “=” è un operatore di ASSEGNAZIONE DA NON CONFONDERE CON == Pagina 10 di 23 << 1 (shift a sinistra di una posizione) >>1 (shift a destra di una posizione) - ESPRESSIONE L’espressione è composta da operatori e operandi con la priorità alle parentesi, dalle più interne alle più esterne, e con associatività a sinistra. - PRECEDENZA Essa e` definita da una ben precisa tabella, che stabilisce il livello 1 a piu` bassa priorita` e il livello 17 a piu` alta priorita`. Nel caso invece di operatori appartenenti allo stesso livello di priorità, la precedenza e` stabilita` dalla associatività, che e` definita da sinistra. ES. Prima la sottrazione che è più a 3-4+2 = sinistra poi la somma -1+2 = 1 Come nelle normali espressioni matematiche qualora si voglia cambiare l’ordine di precedenza degli operatori si ricorre alle parentesi, prima le piu` interne e poi, mano mano, le più esterne (annidate). ES. a +b*c qui viene eseguita prima la moltiplicazione e poi la somma perche` la “*” e la “+” si trovano su livelli di priorita` diversi. Mentre ((a+b)*c) qui viene eseguita prima la somma e poi la moltiplicazione ( grazie alle parentesi). - OPERATORI BOOLEANI ! A (NOT A) A & B (A AND B) A | B (A OR B) A^B (A XOR B) Bit a Bit cioè sui Bit corrispondenti Bit a Bit Bit a Bit Bit a Bit A<<1 (scorrimento a sinistra di una posizione) A>>1 (scorrimento a destra di una posizione) STRUTTURE DI CONTROLLO O COSTRUTTI LA SEQUENZA : essa e` una struttura in cui le istruzioni che la compongono vengono eseguite una dopo l’altra nell’ordine indicato. Tale sequenza e` vista dal compilatore come un unico blocco logico racchiuso tra parentesi graffe {}. ES. Pagina 11 di 23 { Istruzione 1 Istruzione 2} LA SELEZIONE: tale struttura in base alla verita` o meno di un' espressione logica, esegue la sequenza 1 o la sequenza 2. (esistono anche degli IF nidificati). ES.1 V if ( espressione logica) {SEQ. 1} else {SEQ. 2} F ES. 2 if (I < 100) if (I > 0) 0< I < 100; ITERAZIONI Ciclo con controllo in testa “while ” F V Le istruzioni interne al blocco sequenza verranno ripetute se “espressione” e` vera ( ≠ 0 ); viceversa quando l’espressione e` falsa ( = 0 ) il controllo passerà` alla prima istruzione successiva alla struttura “while”. Se l’espressione e` falsa, fin dalla prima volta la sequenza non viene eseguita nemmeno una volta. Se l’espressione dovesse essere sempre vera si entra in un ciclo infinito o loop infinito (vedi EX1). Si sceglie questa struttura quando non si conosce a priori il numero delle iterazioni. Definire la variabile di controllo del ciclo prima di entrare nel ciclo stesso, altrimenti tale struttura “while” va in errore while (espressione) {sequenza} Pagina 12 di 23 Ciclo con controllo in coda “do …. while “ Il ciclo termina quando espressione risulta falsa. La sequenza viene sicuramente eseguita almeno una volta, in quanto “Espressione” viene eseguita al termine del ciclo e non all’inizio, come avveniva per la struttura “while”. In genere questa struttura viene usata per ripetere di nuovo un programma gia` andato in esecuzione almeno una volta. Anche in questo caso la variabile di controllo del ciclo deve essere definita prima di entrare nel ciclo stesso do {sequenza } while (espressione); Il “Ciclo di for” Sequenza di eventi del ciclo for: 1) Viene inizialmente valutata “espressione 1” (espressione di inizializzazione che puo` contenere anche la dichiarazione della variabile di controllo del ciclo . ES: int i = 0; 2) Viene poi valutata “espressione 2” (espressione di controllo ) se e` diversa da 0, verrà eseguita la sequenza, mentre se e` falsa cioe` uguale a 0, si esce dalla struttura for . 3) Alla fine della esecuzione di ogni ciclo prima di calcolare espressione 2, viene eseguita espressione 3 (espressione di incremento o decremento). for (espressione1;espressione2;espressione3) {sequenza } All’interno delle parentesi tonde del “ciclo for” possono mancare tutte o solo alcune espressioni ma devono necessariamente essere presenti tutti i punti e virgola. ES: for (int i = 1; i<=N ; i ++) {sequenza } Tale struttura si usa quando si conosce a priori il numero delle iterazioni. Pagina 13 di 23 ARRAY – VETTORI E MATRICI I vettori rappresentano il modo piu` semplice per aggregare i dati tra di loro, ricordiamo, dati dello stesso tipo. Tale vettore rappresenta una variabile indicizzata dalle seguenti proprietà: 1. Tutti gli elementi che compongono un vettore devono essere dello stesso tipo (tipo del vettore); 2. la struttura e` individuata da un unico nome (nome del vettore); 3. il numero degli elementi che compongono la struttura di un vettore e` definito al momento della dichiarazione del vettore e deve essere rigorosamente intera e maggiore di zero; 4. l’accesso ad un singolo elemento del vettore si ottiene tramite un indice posizionale che viene posto tra parentesi quadra, in fase di uso del vettore (vedi ES2 riga 3) ; 5. Tutti gli elementi vengono memorizzati in locazioni contigue e la posizione del primo elemento corrisponde sempre all’indice 0; Definizione o dichiarazione del vettore : tipo_elementare nome_vettore [numero elementi] ES1. char led [14] = {0x81,0x42,….}; char n; for (n=0;n =4;n ++)…… e` una espressione in esadecimale; N.B. 0x32 0b00110010 e` una espressione in binario. N.B. Una volta definito il vettore con il tipo, il nome e il numero di elementi costituenti il vettore, si può anche dare un valore ai singoli elementi del vettore scrivendo tutti questi valori tra parentesi graffe. ES2. Char leds [2] = {0x81,0x42}; for (char n=0 ; n<2 ; n++) portb = leds [2]; Note : Il PIC possiede due porte di I/O. La prima e` la Port A a 4 bit di I/O e la seconda e` la B a 8 bit di I/O. -In fase di programmazione bisogna definire se le porte di cui si vuole fare uso, debbano essere porte di ingresso o porte di uscita. In termini sintattici la scelta si fa in questo modo: TRISB=0 TRISB=1 Definisce gli 8 bit della Port B come Output Definisce gli 8 bit della Port B come Input Pagina 14 di 23 TECNICHE DI PROGRAMMAZIONE PROBLEMA 1: Complementare uno o piu` bit di un Byte rimanendo gli altri bit inalterati. 0 BIT MASCHERA 0 0 1 1 1 0 1 1 1 0 A Basandoci sulla seguente tabella di verità della X-OR, e sulle definizione degli operatori logici del C++ ( X-or ^) si puo` affermare che le X-or di un generico bit con con 1 logico comporta la complementazione del bit stesso, dunque per risolvere il nostro problema si fa la X-or (^) fra il byte sul quale operare, con una parola maschera costituita da tutti 0, tranne che per i bit che si vuole complementare che vanno posti a 1 nella parola maschera. A^ 0 ES. Sia dato il seguente byte 1A70A61A50A4 1A30A21A10A0 e si voglia complementare il bit A5 rimanendo gli altri inalterati, occorre fare la seguente operazione. 1 0 1 0 1 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 ^ PORTB ^ Es di codifica: portb=portb^0x20 = PAROLA MASCHERA 0x20 N.B.: Osservare in seguito EX1 ed EX2 PROBLEMA 2: Si voglia testare il valore di uno o più bit di un byte, e porre i rimanenti bit che non interessano a 0. 0 BIT MASCHERA 0 0 1 0 1 0 0 1 1 1 A & 0 Basandoci sulle tabelle di verita` della porta AND e sulla definizione di operatore logico del C++ (AND &) si fa la AND con la parola maschera costituita da tanti 1 quanti e quali sono i bit da rilevare o testare, e tutti gli altri bit che non interessano vanno posti a 0 nella parola maschera. ES1. Dato il seguente byte 0A71A60A51A4 1A30A21A10A0 e si voglia conoscere se il bit A1 sia 1 o 0, in tal caso si fa la And con la parola maschera: 0000 0010 Parola maschera Infatti 0 1 0 1 1 0 1 0 0 0 0 0 0 0 1 0 PAROLA MASCHERA 0 0 0 0 0 0 1 0 ≠0 & Pagina 15 di 23 Si fa notare che se il bit A1 fosse stato 0 si sarebbe avuto il seguente risultato : 0 1 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 Questo ci consente di utilizzare questa tecnica per scrivere le espressioni nelle strutture tipo if e while ecc. (vedi EX successivi). Giacché il risultato del test è =0 oppure ≠0 a seconda che il bit in esame sia 0 oppure 1 =0 ES.: portb = portb & 0x01 ES2: Rilevare se uno o più bit (dei primi 4) del seguente byte 01011000 sono 1 o tutti uguali a zero; 0 1 0 1 1 0 0 0 & 0 0 0 0 1 1 1 1 = 0 0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 1 1 1 = 0 0 0 0 0 0 0 0 =0 portb = portb & 0x0E; PAROLA MASCHERA ≠0 & PROBLEMA 3: posizionare a 1 il bit di un byte, rimanendo gli altri bit invariati. Basandoci sulla tabella di verita` delle porte OR (|) del C++ si eseguono le OR con la parola maschera costituita da tutti 0 tranne il bit che si vuole posizionare a 1 . ES.: dato il byte 0A71A60A51A4 0A31A20A11A0 si voglia posizionare a 1 il bit A7 e rimanere gli altri inalterati, tale che: 0 1 0 1 0 1 0 1 + 1 0 0 0 0 0 0 0 = 1 1 0 1 0 1 0 1 portb = portb + 0x80; PAROLA MASCHERA Questa tecnica e` spesso utilizzata quando si vuole accendere il punto decimale in un display a 7 segmenti collegato al bit a7 di un PIC. Pagina 16 di 23 ESEMPI DI PROGRAMMI EX1: Lampeggio di un LED utilizzando la porta RB del PIC (definita come uscita) ed in particolare il bit RB0. void main () { portb = 0; //Pongo l’uscita di PORTB a 0000 0000 trisb = 0; //Definisco PORTB come uscita // loop infinito while (1) { portb = portb ^ 0b00000001 ; //Complemento il bit B0 delay_ms (500); //Pausa o memorizzazione per 500 ms } } EX2: Lampeggio di due LED in modo alternato uno su RB e l’altro su RB1. void main () { portb = 0b00000010; trisb = 0; while (1) { portb = portb ^ 0b00000011; //complementa entrambi I bit delay_ms (500); } } EX3: Provocare la seguente situazione di scorrimento dei LED : void main () { char n=0; char leds [14] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02}; // Inizializzazione porta B trisb = 0; // loop infinito while (1) { Portb=leds [n]; n++; if (n==14) n=0; delay_ms (100); } } N° 1 2 3 4 5 6 7 8 9 10 11 12 13 14 BINARIO HEX 00000001 01 00000010 02 00000100 04 00001000 08 00010000 10 00100000 20 01000000 40 10000000 80 01000000 40 00100000 20 00010000 10 00001000 08 00000100 04 00000010 02 Pagina 17 di 23 EX3.1: Con lo stesso programma realizziamo la seguente sequenza: (effetto super car) void main () { char n=0; char leds [14] = {0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42}; // Inizializzazione porta B trisb = 0; // loop infinito while (1) { Portb=leds [n]; n++; if (n==14) n=0; delay_ms (100); } N° 1 2 3 4 5 6 7 8 9 10 11 12 13 14 BINARIO HEX 10000001 81 01000010 42 00100100 24 00011000 18 00011000 18 00100100 24 01000010 42 10000001 81 01000010 42 00100100 24 00011000 18 00011000 18 00100100 24 01000010 42 Pagina 18 di 23 EX4: Pilotaggio di un display a 7 segmenti a catodo comune (CK) con cifre che vanno da 0 a 9. void main () { char n=0; char segs [16] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; // Inizializzazione porta B trisb = 0; // loop infinito while (1) { Portb=segs [n]; n++; if (n==10) n=0; delay_ms (1000); } } EX4.1: visualizzare il numero 1234 su 4 display con l’uso della multiplazione. 5 5 5 2 0 5 ms ms Pagina 19 di 23 void main () { char n,ds; char segs [16] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; char cifra [4] = {1,2,3,4} ; // Inizializzazione porte trisa = 0; trisb = 0; // loop infinito while (1) { ds=1; for (n=0;n<4;n++) { portb=segs [cifra [n]]; porta=ds; delay_ms (20); ds = ds << 1 ; } } } MULTIPLEXING – Occorre accendere i vari display in successione ad una velocità tale, da non far percepire all’occhio lo sfarfallio. Per ottenere questo effetto è sufficiente accendere ogni cifra ALMENO ogni 20ms. Dal momento che le cifre sono 4, dovremo tenere accese singolarmente meno di 5ms. ( vedi diagramma temporale ) • Sulla Porta B dovranno essere inviate ciclicamente i valori corrispondenti alle quattro cifre da visualizzare cioè 1234. • Sulla Porta A dovrà essere portato alto una sola linea alla volta, cioè quella corrispondente alla cifra da visualizzare, ciclicamente : (0b 0000 0001, 0b 0000 0010, 0b 0000 0100, 0b 0000 1000) P.S.: LA VARIABILE ds che è inizializzata a 1 (0000 0001) serve per lo shift, cioè per realizzare il multiplexing. SEGS [16] per convertire la cifra da decimale a 7 segmenti. Pagina 20 di 23 EX5: Utilizzare la porta Rb1 per accendere un led posto sulla porta Rb0 e utilizzare la porta Rb2 per spegnere il led. Le resistenze di pull-down (RA-RB) da 1KΩ posta tra i pulsanti e massa servono per fissare a livello basso (0V) i rispettivi piedini di I/O quando i pulsanti non sono premuti (in caso contrario , cioè senza le R da 1 KΩ, le tensioni sui pin Rb1 e Rb2, potrebbero essere influenzate da interferenze esterne). PULSANTE PREMUTO PULSANTE RILASCIATO IN = 5 V Ξ 1 IN = 0 V Ξ 0 void main () { // inizializzazione porta b trisb = 0x06; portb = 0; //loop infinito while (1) { if (portb&0X02) portb=1; // se il pulsante su Rb1 è premuto accendi il led if (portb&0X04) portb=0; // se il pulsante su Rb2 è premuto spegni il led } } NOTA SULL’INIZIALIZZAZIONE DELLA PORTA B Per leggere lo stato dei due pulsanti i piedini corrispondenti alla porta B sono stati configurati come ingressi scrivendo il valore nel registro TRIS B 0x06 che in binario è “0000 0110” in cui gli 1 rappresentano i pin configurati come ingressi cioè RB1 e RB2, e i bit che valgono 0 cioè RB0 vale come uscita. NOTA SOFTWARE: Il ciclo infinito mantiene il led sempre acceso o spento a seconda dello stato dei pulsanti; questo artificio software corrisponde alla funzione di memoria. Pagina 21 di 23 EX5.1: Fare in modo che alla pressione di uno dei due pulsanti il LED venga acceso ed alla successiva pressione venga spento. void main () { // inizializzazione porta b trisb = 0x06; // configura rb1 e rb2 come ingressi e rb0 come uscita portb = 0; //inizializzazione con azzeramento della porta b //loop infinito while (1) { if (portb&06) portb=portb^01; //inverti il bit su rb0 solo se trova rb1 o rb2 premuti altrimenti ripete. //Attesa rilascio while (portb&0x06) {}; delay_ms (50); Quando la condizione () è falsa quindi i due pulsanti sono rilasciati, il programma ritorna automaticamente al } “1° While” per l’accensione o lo spegnimento. } Meccanismo antirimbalzo. N.B.:Il motivo della scelta della parola maschera “06dec” è quella che: premendo il pulsante su RB1, o premendo il pulsante su RB2, la AND con 06 da come risultato un valore ≠0 cioè VERO (Vedi tabella) . In tutti gli altri casi il risultato è = 0 quindi FALSO. Caso con i pulsanti premuti: 0 0 0 0 & 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 PAROLA MASCHERA 0 0 0 0 0 0 0 1 0 0 ≠0 0 0 0 0 0 1 0 0 0 0 1 1 0 PAROLA MASCHERA 0 0 0 0 1 0 ≠0 & Caso con i pulsanti non premuti: 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 PAROLA MASCHERA 0 0 0 0 0 1 1 0 PAROLA MASCHERA 0 =0 0 0 0 0 0 0 0 0 =0 & & Pagina 22 di 23 EX6: Caso di antirimbalzo e contatore guidato da due pulsanti Up e Down con l’uso di un display a 7 segmenti, ad ogni pressione del tasto S1 e S2. void main () { signed char count = 0; char segs [16] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; // controllo pulsanti if (porta&0x02) count++; if (porta&0x01) count--; // correzione contatore // Inizializzazione porte trisa = 0x03; trisb = 0x00; porta= 0x08; //RA0 e RA1 rilasciati // loop infinito while (1) { portb= segs [count]; if (count > 9 ) count = 0; if (count < 0 ) count = 9; //attendere rilascio while (porta==0x03) {}; } } Pagina 23 di 23