Progetti - PIC

 

Simulatore di logica booleana


Una semplice applicazione didattica che permette di verificare visivamente le principali funzioni della logica binaria.

Nell' algebra di Boole abbiamo alcune funzioni fondamentali, ben note a chiunque operi con la programmazione dei dispositivi digitali, che sono:

  • AND
  • OR
  • XOR

con i loro opposti (NAND, NOR, XNOR), determinati dalla funzione invertente NOT.  Possiamo tracciare per ognuna di esse la "tabella della verità" che lega gli ingressi con lo stato dell' uscita.  Per due bit in ingresso abbiamo:

NOT

A A
0 1
1 0

AND

B A AB
0 0 0
0 1 0
1 0 0
1 1 1
NAND
B A AB
0 0 1
0 1 1
1 0 1
1 1 0
OR
B A A+B
0 0 0
0 1 1
1 0 1
1 1 1
NOR
B A A+B
0 0 1
0 1 0
1 0 0
1 1 0
XOR
B A AB
0 0 0
0 1 1
1 0 1
1 1 0
XNOR
B A A B
0 0 1
0 1 0
1 0 0
1 1 1

Possiamo realizzare un circuito che presenti su LED i risultati di queste truth tables.
Utilizziamo un microcontroller a 14 della famiglia Baseline; dato che non ci occorre alcuna funzione speciale possiamo puntare su un semplice 16F505, anche se può essere utilizzato 16F506/526 o qualsiasi altro PIC con un numero sufficiente di pin.

A e B sono due interruttori, che forniscono gli stati 1 e 0 di ingresso alla logica; ognuno è associato ad un LED che ne replica lo stato.  Sette LED indicano il risultato delle varie funzioni.
Allo scopo di minimizzare il consumo e il numero dei componenti necessari, non vengono utilizzati pull up esterni sugli ingressi, in quanto sono abilitati quelli integrati, che risultano presenti su RB0,1 e 3.
RES è un pulsante collegato al pin MCLR; può essere anche non utilizzato (vedere più avanti).

Il dispositivo può essere alimentato da 3 a 5V. Nella realizzazione del prototipo viene usata una coppia di batterie AA.
Anche se è stato previsto un circuito stampato ad hoc, è comodo utilizzare la LPCuB per sviluppare il programma:

Essendoci solamente 8 LED nella fila superiore LED0-7, utilizziamo anche uno dei LED  relativi alla interfaccia di comunicazione. 
Gli interruttori di ingresso sono simulati con i pulsanti PB3 e PB4.  Non occorre inserire pull up dato che vengono abilitati quelli interni al chip.


  AVVERTENZA: dato che i pulsanti sono collegati a PB1:0 che sono anche PGC e PGD della programmazione, occorre assicurarsi che essi non siano premuti durante questa operazione che, altrimenti, sarebbe impossibile.

Il prototipo finale, nella versione proposta, dispone di presa ISCP, come visibile dallo schema elettrico: se si programma il chip on board, occorre assicurarsi con certezza che gli interruttori collegati a PB1:0 non siano premuti durante questa operazione, per non danneggiare il Pickit.

Volendo inserire una protezione, si useranno delle resistenze da 1k in serie tra interruttore e pin, come è previsto sulla LPCuB. Queste, però, non sono indispensabili se si cura quanto detto sopra.


Il programma


Il sorgente è estremamente semplice, dato che utilizziamo una "scorciatoia": anche se nel set di istruzioni del microcontroller esistono opcodes che realizzano le funzioni booleane (iorwf, xorwf, andwf) è molto più semplice utilizzare delle lookup table.

La scelta dei collegamenti è dettata da alcune considerazioni:

  • i pin RB0,1 e 3 sono dotati di weak pull up integrati. Quindi sarà più pratico usare questi come ingressi.
  • inoltre la posizione iniziale nel byte dei due pin di ingresso della logica è molto comoda per passare il loro stato direttamente come indice di una tabella

La disposizione degli altri pin, che sono tutti dedicati al comando di LED, è indifferente, dato che la costruzione delle tabelle potrà essere adeguata con facilità alle più diverse combinazioni.

Il sorgente è estremamente semplice, dato che utilizziamo una "scorciatoia": anche se nel set di istruzioni del microcontroller esistono opcodes che realizzano le funzioni booleane (iorwf, xorwf, andwf) è molto più semplice utilizzare delle lookup table.
Per come è realizzato il circuito stampato e le indicazioni sul pannello, per PORTC, tra i LED di indicazione del risultato e i pin di I/O c'è la seguente equivalenza:

Bit RC5 RC4 RC3 RC2 RC1 RC0
LED !A AND NAND XOR NOR OR

e per PORTB:

Bit RB5 RB4 RB3 RB2 RB1 RB0
LED LEDA LEDB - XNOR - -

La lookup table mette in relazione lo stato dei pin di ingresso A e B con le uscite sul PORTC:

RC5 RC4 RC3 RC2 RC1 RC0
B A !A AND NAND XOR NOR OR
0 0 1 0 1 0 1 0
0 1 0 0 1 1 0 1
1 0 1 0 1 1 0 1
1 1 0 1 0 0 0 1

e sul PORTB:

RB5 RB4 RB3 RB2 RB1 RB0
B A LEDA LEDB - XNOR - -
0 0 0 0 0 1 0 0
0 1 1 0 0 0 0 0
1 0 0 1 0 0 0 0
1 1 1 1 0 1 0 0

Dato che un port è composto da soli 6 bit, i due più alti (bit 7 e bit 6), non implementati, saranno a 0. Ne derivano le due lookup tables:

; Lookup table per PORTC
bltbl  addwf PCL,f       ; punta PC
                         ;          bit
                         ; in  76 5 4 3 2 1 0

                         ; BA  00 ! A N X N O
       retlw b'00101010' ; 00  00 A N A O O R
       retlw b'00001101' ; 01  00   D N R R 
       retlw b'00101101' ; 10  00     D  
       retlw b'00010001' ; 11  00

; Lookup table per PORTB

bltbl1 addwf PCL,f       ; punta PC
                         ;          bit
                         ; in  76 5 4 3 2 1 0

                         ; BA  00 A B 0 X 0 0
       retlw b'00000100' ; 00  00     0 N 0 0
       retlw b'00100000' ; 01  00     0 O 0 0
       retlw b'00010000' ; 10  00     0 R 0 0
       retlw b'00110100' ; 11  00

Non importa il valore attribuito ai bit configurati come ingressi, dato che la scrittura non avrà effetto.
Non serve neppure una limitazione del numero in ingresso alla tabella, dato che è già limitato ai primi due bit dalle operazioni precedenti.

Ovviamente il contenuto delle tabelle dipende dal rapporto tra pin e LED; se utilizzate un qualsiasi altro layout, basterà semplicemente adeguare le tabelle.

Quindi, basta applicare il dato in uscita dalla tabella al relativo port:

mainlp movf  lastport,w   ; stato precedente
       call  bltbl        ; maschera per LED
       movwf PORTC
       movf  lastport,w
       call  bltbl1
       movwf PORTB

Con queste poche righe il programma è completato!  

Però è possibile applicare alcuni miglioramenti.

Per prima cosa il sorgente è reso compilabile per diversi processori, col solito sistema degli #ifdef.
Si ricorda, comunque, che non vengono usate periferiche speciali o interrupt, per cui il sorgente, scritto per il set minimale dei Baseline, può essere riportato senza problemi su qualsiasi altro PIC.

In secondo luogo, esiste un'altra questione: i LED accesi hanno un consumo che non è marginale per le piccole batterie AA; a 10mA per LED, abbiamo un massimo di 90mA, a cui va aggiunta la corrente assorbita dal micro, con tutti i LED accesi. 
Con LED a bassa corrente (2mA) la situazione sarebbe molto migliore, ma, per evitare la ricerca e l' acquisto di questi componenti a volte poco reperibili, possiamo utilizzare LED comuni, ricorrendo ad un PWM.
Il programma fa si che essi siano accesi per 5ms ogni 20ms: la corrente media si riduce a circa 7mA, senza presentare sfarfallio e con una luminosità visibile anche alla luce del giorno.
Per ottenere questo, inseriamo una temporizzazione di circa 5ms per i LED on ed una di 15ms per lo stato off:

timeon movlw time5ms ; attesa 5ms
       movwf TMR0
tlp1   movfw TMR0
       skpz
        goto tlp1
       DISPLAYOFF    ; spegni display

; attesa 15 ms
       movlw time15ms
       movwf TMR0
tlp2   movfw TMR0
       skpz
        goto tlp2

; leggi stato ingressi ogni 20ms

Variando i tempi on/off, possiamo adattare il firmware a LED con differenti caratteristiche; elementi a bassa luminosità necessiteranno di maggiore tempo on.

Lo stato degli ingressi viene letto ogni 20ms circa allo scopo di minimizzare l'influenza dei rimbalzi; da notare che, anche quando presenti, nell'applicazione non hanno conseguenze sulla visualizzazione; quindi non è implementata alcuna altra azione di debounce.

Una volta minimizzata la corrente a riposo, è possibile, volendo, eliminare l'interruttore di accensione, sostituito dal solo pulsante che agisce sul pin MCLR.
Alla prima applicazione della tensione di alimentazione (POR), il circuito resta attivo per 1 minuto; se non viene premuto nessuno dei due interruttori, viene conteggiato un timeout allo scadere del quale si passa in modalità sleep a basso consumo (1uA o meno); ogni volta che viene cambiato lo stato degli ingressi, il timeout viene resettato, permettendo di mantenere acceso con continuità l'apparecchio.  Dalla condizione di sleep, la pressione del tasto collegato a MCLR risveglia il processore e riavvia il ciclo:

; verifica del timeout
ontime movf   minutcntrl,f
       skpz
        decf  minutcntrh,f
       decfsz minutcntrl,f
        goto  mainlp        ; torna al loop

; timeout - va in sleep
sleepin DISPLAYOFF

       sleep

Variando i valori pre caricati nei contatori, si potrà variare il timeout a piacere.

Volendo, è possibile anche eliminare il tasto del reset ed utilizzare per il wakeup la funzione di pin change, azionando uno dei due interruttori. In tal caso occorre abilitare al funzione:

; setup OPTION: RB5, RBPU, Timer0 1:256
         ; b'11010111'
         ;   0------- RBWU abilitato
         ;   -0------ RBPU abilitato
         ;   --0----- clock interno
         ;   ---1---- falling
         ;   ----0--- prescaler al Timer0
         ;   -----111 1:256

    movlw  b'00010111'
    OPTION

Inoltre è necessario leggere lo stato del port prima di passare in sleep per cancellare il flag relativo:

; timeout - va in sleep
sleepin DISPLAYOFF
        movf   PORTB,w

        sleep

Utilizzando lo stato di sleep è possibile realizzare un apparecchio tascabile alimentato a battere, con una autonomia consistente.


Un prototipo.

Nelle immagini, come è stato realizzato un prototipo. Il circuito è racchiuso in una scatoletta che contiene anche le due batterie AA di alimentazione.

Con i LED utilizzati, le resistenze in serie sono da 56-68 ohm.
Il circuito stampato prevede una connessione ICSP per poter programmare il chip direttamente on circuit. Se non pensate di utilizzarla, potete escluderla.

La realizzazione non è critica e può essere eseguita in qualsiasi altro modo che risulti sufficientemente ordinato.



 

 

Copyright © afg. Tutti i diritti riservati.
Aggiornato il 07/04/15.