Creative Commons BY-NC-ND 2.5Questo sito e tutto il suo contenuto sono distribuiti sotto la licenza Creative Commons Attribuzione - Non Commerciale - Non opere derivate 2.5 Italia e con le condizioni d'uso definite nel disclaimer: siete pregati di leggere entrambi questi documenti prima di usufruire dei contenuti di questo sito. Per alcuni contenuti è necessaria una registrazione gratuita: non è necessario pagare e non è necessario accumulare punteggi per accedere agli articoli e scaricare i sorgenti: basta solo essere onesti. Se volete che questo sito continui a rimanere attivo, a contribuire ogni giorno alla diffusione della cultura libera, non copiate il materiale per ripubblicarlo in altri luoghi. Se volete partecipare su settorezero e rendere le vostre idee, i vostri progetti, fruibili da tutti senza limitazioni potete farlo tranquillamente.

La codifica BCD e i display a 7 segmenti

Autore: Giovanni Bernardo | Data pubblicazione: 27 ottobre 2009
Categorie: Elettronica

display_7_segmentiBCD è un acronimo che sta per Binary Coded Decimal : Decimale codificato in binario. E’ un sistema utilizzato in informatica e in elettronica per rappresentare una singola cifra decimale con il suo equivalente in binario. La codifica, dovendo rappresentare soltanto le cifre (quindi da 0 a 9) richiede unicamente un nibble (4 bit) per ogni cifra.

Il numero 248, ad esempio, in BCD sarà codificato come 0010 – 0100 – 1000 (ogni cifra è rappresentata in formato binario: 0010 =2, 0100=4, 1000=8).

Utilizzando i normali sistemi ad 8 bit, ovviamente ci troveremo ad avere i primi 4 bit inutilizzati: per convenzione, quindi, ogni cifra espressa in BCD avrà i primi 4 bit posti a zero (altri usano posti a uno), seguiti quindi dai 4 bit che codificano la cifra (8 sarà quindi codificato come 00001000, come avviene normalmente per codificare ad 8 bit un numero decimale).

Dal momento che 4 bit vengono “sprecati”, a volte si utilizza la codifica packet BCD, ovvero vengono messe due cifre per ogni byte. Nella codifica packet BCD, inoltre, viene anche aggiunto alla fine un codice per indicare il segno del numero: 1100 per il + e 1101 per il -, il numero 248, quindi sarà rappresentato in packet BCD come: 00100100 – 10001100.

In realtà la codifica BCD, sebbene porti degli “sprechi” di informazioni, è molto utilizzata per vari motivi in elettronica. Prima di tutto perchè permette un facile utilizzo dei display a led a 7 segmenti: esistono numerosi circuiti integrati che permettono di pilotare direttamente un display a 7 segmenti, passandogli la codifica in BCD della cifra da visualizzare.

sn7447Immaginiamo di dover pilotare un display a 7 segmenti con un picmicro: avremo bisogno di 7 pin di I/O per visualizzare una cifra: uno per ogni segmento del display, questo può non essere un problema se abbiamo a disposizione molti I/O oppure se la nostra applicazione non necessita di molti I/O.

Ma se dobbiamo pilotare numerosi display? La cosa si complica: si ricorre sicuramente al multiplex (si abilitano i display uno alla volta, molto velocemente) e si preferisce utilizzare un integrato BCD-to-seven-segments-driver (come il CD4511 o l’SN7447 per citarne alcuni), in maniera tale che anzichè 7 I/O per cifra, ne dobbiamo utilizzare soltanto 4, risparmiando ben 3 pin (e questo ci permette, ad esempio, di utilizzare un display a 7 segmenti anche con un picmicro da 8 pin).

Nell’esempio affianco (che illustra il collegamento classico di un BCD-to-7-segment-driver), per visualizzare, ad esempio, la cifra 7, imposteremo gli ingressi dell’SN7447 (ABCD – scritti in maiuscolo!) sul valore 0111 (7 codificato in BCD), (A=0,B=1,C=1,D=1), per contro l’integrato manderà tensione ai segmenti contrassegnati come a,b e c (scritti in minuscolo) per visualizzare il numero 7 sul display.

I segmenti di un display vengono generalmente identificati con le lettere come da disegno:

7_segment_display_labeled

Quindi per visualizzare il numero 2, si accenderanno i segmenti a,b,g,e,d.

Un altro motivo per cui la codifica BCD è così utilizzata sta nel fatto che ha una corrispondenza quasi diretta con il codice ASCII: basta difatti sostituire le prime 4 cifre binarie della codifica BCD con 0011 per ottenere il corrispondente valore ASCII della cifra che si vuole rappresentare!

Prendiamo ad esempio il numero 8: in BCD sarà scritto come 1000 o meglio 0000 1000. Sostituendo le prime  4cifre binarie, inutilizzate, con 0011 otteniamo 0011 1000,  ovvero 56 in decimale, che è proprio il codice ASCII del numero 8!

Datasheet CD4511 (BCD to 7 segment driver) (72)
Datasheet SN7447 (BCD to 7 segment driver) (2504)

L'articolo ti è piaciuto o ti è stato utile per risolvere un problema? SettoreZero è realizzato soltanto con contenuti originali: tutti gli articoli sono curati con passione dagli autori e nulla viene copiato da altri siti. Supporta e mantieni in vita SettoreZero con una donazione: basta soltanto un caffè o una birra. Puoi supportare SettoreZero anche con uno dei progetti elencati nella sezione servizi o partecipare anche tu con un tuo articolo/progetto personale.

Se desiderate che SettoreZero continui a rimanere gratuito e fruibile da tutti, non copiate il nostro materiale e segnalateci se qualcuno lo fa.

Puoi andare alla fine dell'articolo e lasciare un commento. I trackback e i ping non sono attualmente consentiti.

  1. #1 da S.D.R. il 27 novembre 2009

    Ciao ;
    In questi giorni mi sono costruito una schedina per pilotare 4 display 7 seg ,mi piacerebbe fare qalche esperimento e visto che hai già introdotto l’argomento …
    Lo so che sono un rompi scatole , presto ti offrirò un altro caffè ;-)

    • #2 da Giovanni Bernardo il 27 novembre 2009

      Caro SDR tu mi leggi nel pensiero!! E’ incredibile!! Sto difatti preparando la lezione 8 appunto sul pilotaggio dei display a led a 7 segmenti in modalità multiplex! Nell’articolo farò riferimento a solo due display, poi aggiungere gli altri, capito bene il meccanismo, è una cosa semplicissima. Avevo detto che avrei parlato dell’eeprom interna ma poi ho cambiato idea dal momento che sfrutterò lo stesso circuito della lezione sui display a 7 segmenti anche per fare l’esempio con l’eeprom.

    • #3 da Giovanni Bernardo il 27 novembre 2009

      Suppongo tu abbia realizzato il progetto di Sergio Fiocco. Io però in questa lezione non userò il 4511 ma piloterò i 7 segmenti direttamente senza frapporre un decoder BCD. Non mi va di proporre cose già proposte e comunque ho fatto questa scelta per non complicare ulteriormente le cose: usando difatti un pic16F84 o 628 puoi benissimo realizzare il circuito senza ricorrere al 4511, rendendo il circuito più compatto: questo è essenziale in progetti miniaturizzati. Ho difatti realizzato giorni fa un bel timer 1-99 minuti per 220V con un 16F84 e due display a 7 segmenti in una scatola davvero molto piccola che ospita il tutto: alimentatore per la logica, 2 normali prese di corrente della Vimar (che funzionano una normalmente aperta e una normalmente chiusa), relè per il pilotaggio delle 2 prese e due pulsanti per il settaggio e lo start/stop, con memoria e incremento a velocità variabile. Un altro integrato li dentro veramente non ci sarebbe mai stato e comunque non ne avevo la necessità dal momento che tutte le porte che avevo a disposizione erano sufficienti. Spero al piu presto di poterlo pubblicare ma renderò disponibile il codice sorgente solo a chi ha già fatto una donazione e me lo richieda, sarà comunque disponibile il codice già compilato.

  2. #4 da S.D.R. il 28 novembre 2009

    Hehe , hai scoperto i miei super poteri ! :-)

    Si, ho scopiazzato lo schema elettrico di sergio fiocco , invece ho seguito la guida di FareElettrinica per le istruzioni in ANSIC .
    Il primo esempio che mi faceva apparire un numero fisso sui 4 display”1234″ mi ha funzionato mentre questo no :

    void main(void)
    {
    char n,ds,val;
    char segs[16]={0x3F,0x06,0X5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
    char cifra[4];
    val=-47
    TRISA=0b00000000;
    TRISB=0b00000000;
    TRISC=0b00000000;
    PORTA=0;
    PORTB=0;
    PORTC=0;
    ShortToStr(val, cifra);
    while(1) //ripete il ciclo all’infinito
    {
    ds=1;
    for(n=0;n<4;n++)
    {
    PORTB=segs[cifra[n]-48];
    if (cifra[n]==32)
    {
    PORTB=0x00;
    }
    if (cifra[n]==45)
    {
    PORTB=0x40;
    }
    PORTA=ds;
    DelayMs(1);
    ds=ds<<1;
    }
    }
    }

    Mi da errore di sintassi su "ShortToStr(val, cifra);" , non è che questa istruzione esiste solo nella libreria di istruzioni di mikroC ?

    • #5 da Giovanni Bernardo il 28 novembre 2009

      Il codice è semplice ma ci sono 2 cose che non capisco: una è sicuramente questa funzione ShortToStr, che ovviamente devi avere definita, adesso se fa parte del MikroC non te lo so dire perchè non lo uso, ma è di sicuro una funzione che converte un numero short (8bit) in stringa (in questo caso in una stringa da 4 caratteri, ovvero in un array di 4 elementi ciascuno da 8 byte). Poi a val da il valore -47 ma lo definisce come char, quando andrebbe definito come signed char se intende dargli un valore col segno… boh non ti so dire, non vedo nemmeno la necessità di convertire un numero in stringa per questa applicazione… non ha senso, tutto quello che si vuole fare in questa applicazione può essere risolto con due divisioni senza ricorrere a conversioni di tipo che, tra l’altro, sono onerose in termini di memoria programma.

  3. #6 da S.D.R. il 28 novembre 2009

    Dimenticavo , non ho usato il decoder BCD 4511 .

  4. #7 da S.D.R. il 29 novembre 2009

    Suppongo che le divisioni servano per scomporre il numero in unità e decine ma se faccio diviso 10 mi viene un numero con la virgola e come faccio a prendere solo il numero prima della virgola !?
    E con il segno come faccio ?

    • #8 da Giovanni Bernardo il 29 novembre 2009

      Esatto. In C la divisione tra interi restituisce un numero intero. Se fai, ad esempio, 10 diviso 3, il risultato che ottieni è 3, senza decimali. Se avevi dichiarato le variabili che contengono 10 e 3 come float, allora ottieni anche il decimale, ma avendoli dichiarati come interi ottieni un intero privo dei decimali.

      Vuoi ad esempio ottenere dal numero 23 le due cifre separate per farle apparire una sul primo display e l’altra sul secondo.
      Fai 23/10 e ottieni 2.
      Poi ti memorizzi il 2 che hai ottenuto prima e fai 23-(10*2) e ottieni il 3 che fai apparire sul secondo display. Il concetto si applica ovviamente anche alle centinaia e alle migliaia, come vedi è molto semplice.

      Il segno lo ottieni nel caso che le variabili le hai definite come signed, in quel caso controlli che la variabile sia <0, se vero fai apparire il segno sul display. Se analizzi direttamente il numero negativo per farlo apparire sul display, ti appare il numero senza segno, per far apparire il segno devi fare questa operazione e quindi far apparire il segno manualmente.

  5. #10 da S.D.R. il 1 dicembre 2009

    Ciao ;
    Allora ho fatto questo e funziona , sicuramente può essere scritto meglio , suggerimenti !?

    void main(void)
    {
    char segs[16]={0x3F,0x06,0X5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
    unsigned int unita;
    unsigned int decine;
    unsigned int centinaia;
    unsigned int migliaia;
    unsigned int val;
    val=1234;
    TRISA=0b00000000;
    TRISB=0b00000000;
    TRISC=0b00000000;
    PORTA=0;
    PORTB=0;
    PORTC=0;

    while(1)
    {
    {
    migliaia=val/1000;
    centinaia=(val-(migliaia*1000))/100;
    decine=((val-(migliaia*1000))-(centinaia*100))/10;
    unita=((val-(migliaia*1000))-(centinaia*100)-(decine*10));
    PORTA=0B00000001;
    PORTB=segs[migliaia];
    DelayMs(1);
    PORTA=0B00000010;
    PORTB=segs[centinaia];
    DelayMs(1);
    PORTA=0B00000100;
    PORTB=segs[decine];
    DelayMs(1);
    PORTA=0B00001000;
    PORTB=segs[unita];
    DelayMs(1);
    }
    }
    }

    Ho 4 display quindi la cosa è stata un po’ complicata poi all’inizio avevo dichiarato le variabili char per cui mi venivano fuori numeri che non c’entravano nulla poi usando unsigned int ha funzionato .

    • #11 da Giovanni Bernardo il 1 dicembre 2009

      Va bene come esempio, ma non vedo perchè non funziona con char, char è a 8 bit e deve andare per forza, cosa intendi che uscivano numeri che non centravano? tipo impostavi 1234 e invece ti usciva 5678, oppure si accendevano dei segmenti a caso, magari piu sbiaditi degli altri?

  6. #12 da Giovanni Bernardo il 1 dicembre 2009

    Non capisco perchè dopo il while hai messo due graffe, ne bastava una sola. Comunque hai afferrato appieno il concetto che si utilizza.

  7. #13 da S.D.R. il 2 dicembre 2009

    Si ,me ne sono accorto pure io delle doppie parentesi , poi ho corretto .
    Con char mi viene fuori 0210 .
    Aveveo persino fatto la prova di collegare 8 led sulla porta C e con quella(moidificando il programma , PORTC=migliaia … ) ho controllato uno alla volta migliaia , centinaia , decine e unità in binario per vedere se i calcoli li faceva giusti e mi risultava sempre 0210 .
    Mai una volta che le cose mi funzionino bene subito porca miseria , da char a int camia solo che la prima è a 8 bit e la seconda a 16 ma perchè non funziona anche char !? :-S

    • #14 da Giovanni Bernardo il 2 dicembre 2009

      ah no… ho detto una fesseria è giusto così, non puoi usare char… char lo puoi usare fino a 255… dato che tu lavori con un numero superiore a 255 (8bit) devi utilizzare int… è tutto corretto così.

  8. #15 da Giovanni Bernardo il 2 dicembre 2009

    dato che val è 1234, devi utilizzare int, di conseguenza tutti i calcoli che farai con questo numero devono trovarsi in variabili int

Devi essere collegato per lasciare un commento.

  1. Ancora nessun trackback
settorezero.com e il logo Zroid™ ©2007÷2015 Giovanni Bernardo - E' vietata la copia e la distribuzione anche parziale dei contenuti di questo sito web senza l'esplicito consenso dell'autore.
I contenuti di settorezero.com sono distribuiti sotto una licenza Creative Commons Attribuzione-Non Commerciale-Non Opere derivate 2.5 Italia a cui vanno aggiunte le condizioni d'uso definite nel disclaimer.
settorezero.com e tutti i suoi contenuti sono tutelati dalla legge sul diritto d'autore per cui i trasgressori sono perseguibili a norma di legge. Settorezero fa uso dei cookie leggi l'informativa estesa.
Creative Commons BY-NC-ND 2.5
Il tema di questo sito è basato sul tema Fusion per wordpress, realizzato originariamente da digitalnature e fa uso del plugin Wassup per il computo delle statistiche. Per contattare l'autore siete pregati di utilizzare la sezione contatti.
Per essere aggiornato con tutte le novità di settorezero.com seguici anche anche su Facebook Twitter Tumblr Blogspot Youtube.