Progetti - PIC

 

999s countdown timer


Un temporizzatore è senz'altro utile in molte applicazioni. In laboratorio, ad esempio, per il bromografo o per reazioni chimiche.

Vediamo come realizzarne uno, supportato da un microcontroller PIC.


Linee guida del progetto.

Si vuole ottenere un oggetto semplice, economico e facile da utilizzare.
Questa ultima caratteristica è solitamente quella chiave per tutte le apparecchiature che devono prevedere una interfaccia che sia maneggiata da un utente. Però, è normale che una facile manovrabilità da parte dell'utilizzatore richieda una certa complessità dell'interfaccia.

Nel caso del nostro timer, il problema principale è quello di permettere l'impostazione del tempo, in modo quanto più possibile intuitivo.

In questa direzione, l' uso di commutatori genere Contraves (nella foro un componente Cherry, distribuito da Conrad) consente una impostazione del contatore immediata e nello stesso tempo mantiene la selezione anche a sistema spento. E' la soluzione classica adottata nei circuiti a logica cablata TTL/CMOS.

La gestione di questi commutatori non è problematica, anche se richiede almeno quattro I/O più uno per ogni elemento. Avrebbero inoltre il sensibile vantaggio che non occorre neppure un display ad indicare il tempo; bastano un paio di LED.

A fronte di questi vantaggi, l'inciampo principale è costituito dal costo assai elevato (8-10€ al pezzo). Se non ne avete in casa, recuperati da qualche apparecchiatura, sicuramente la spesa di una trentina di euro per tre di questi oggetti è eccessiva.

Possiamo anche considerare l' uso di un tastierino a 12 tasti, ma anche in questo caso abbiamo contro il costo e la necessità di disporre di un certo numero di I/O, almeno 7 per la configurazione classica a matrice, il che fa lievitare le dimensioni del microcontroller; non che ci siano problemi in tal senso: usando un package SMD, anche un 64 pin occupa un paio di centimetri quadrati, ma diventa difficile saldarlo in un laboratorio amatoriale, mentre il circuito stampato richiede una precisione anche questa raggiungibile da pochi hobbisti.

Dobbiamo, allora, ripiegare sull'uso di pulsanti, complicando un poco la vita all'utente.
E va considerato che meno pulsanti ha l' apparecchiatura, più complessa sarà la gestione dell' interfaccia con l' utente.

Per quanto riguarda la presentazione del conteggio, ci orientiamo verso l'impiego di tre display a sette segmenti; sarebbe possibile utilizzare anche un piccolo LCD a caratteri, ma, se permette una messaggistica estesa, ha costo e dimensioni non minimali.

Optiamo dunque per tre digit a 7 segmenti, comandati in multiplex per ridurre il numero di pin del microcontroller

L'uscita sarà un relè con contatto di scambio (SPDT) o quant' altro serve alla nostra applicazione, ad esempio un SSR.

Durante la definizione delle specifiche del timer sono state via via aggiunti altri "optionals", non indispensabili al funzionamento, ma utili nella pratica.
Così abbiamo un cicalino per avvertire dello scadere del tempo e un certo numero di funzioni ausiliarie, come il test del carico collegato, una modalità di hold per sospendere il conteggio, un pulsante di stop per annullarlo e qualche memoria per salvare valori di conteggio di uso comune.

Tutto questo risulta gestibile senza eccessive complicazioni con solo quattro pulsanti, a cui aggiungiamo LED di segnalazione.
Per cui le caratteristiche finali saranno queste:

  • Countdown fino a 999s
  • 3 display a 7 segmenti
  • 4 pulsanti di programmazione
  • 4 led indicatori, corrispondenti ad ogni pulsante
  • Uscita con relè SPDT
  • Cicalino di avviso fine conteggio
  • 6 funzioni: - START/HOLD 
                    - STOP/TEST
                    - ReCallMemory
                    - SETUP
  • Alimentazione 12V cc/ca o 230Vca

 


Hardware.

Dopo aver definite le specifiche del progetto, scegliamo il microcontroller. Occorrono 8 + 3 I/O per il multiplex del display, a cui vanno aggiunti altri due I/O per relè e cicalino ed almeno un altro per i pulsanti. Un totale di almeno 14 pin, il che permetterebbe l'impiego di un chip a 18 pin.
Ne scegliamo, invece, uno a 20 pin per avere un margine di sicurezza nel caso si aggiunga qualche altra funzione durante lo sviluppo. La differenza di costo e dimensioni è minima.

Ma quale PIC?  Escludiamo decisamente qualsiasi chip obsoleto. Intendiamoci: nulla vieta di utilizzare 16F84 o 16F876, ma non ha alcun senso iniziare un nuovo progetto con i vecchi chip, che, tra l' altro, finiscono per costare parecchie volte di più di un chip più recente (e più performante). Inoltre, è molto opportuno non fossilizzarsi su alcuni componenti e considerare quello che risulta dal continuo sviluppo della tecnologia, in modo da essere costantemente aggiornati.

Occorre senz'altro la disponibilità di interrupt per la gestione di varie task, oltre alla disponibilità di EEPROM per mantenere i tempi programmati anche in mancanza di alimentazione.
La scelta si dirige sui PIC18FxxK, economici e potenti, oppure sui recenti Enhanced Midrange, che hanno prestazioni notevoli e costi quanto mai limitati.
Ci indirizziamo su questi ultimi, anche per metterli alla prova in una applicazione reale. Possiamo usare 16F1507/8/9, tre chip analoghi a 20 pin, appartenenti ad un gruppo uniforme assieme a 12F1501 (8 pin) e 16F1503 (14 pin).
Date le caratteristiche simili, è possibile scrive un sorgente unico per i tre chip, osservando che si differenziano per quantità di memoria integrata. In effetti, 16F1507 è privo di USART e MSSP, ma queste funzioni non sono previste nel progetto; la loro assenza e la ridotta quantità di memoria ne fanno il chip meno costoso del gruppo, per cui è la scelta ottimale.

A questo punto possiamo stendere il disegno del circuito elettrico. Questa è "l'unità centrale":

PORTC è dedicato ai segmenti dei display (7 + il dp), mentre gli RB sono utilizzati per comandare i catodi comuni (ovviamente è possibile implementare anche display ad anodo comune, variando opportunamente il circuito).
I LED addizionali sono collegati anch'essi a catodo comune  sul multiplex, come "quarto" digit. Questo consente di minimizzare i pin richiesti.
Occorrono, quindi, quattro step, per comandare i 4 elementi.
Gli RB sono bufferati con transistor NPN (generici, tipo BC237, BC547, 2N4401, 2N3904, ecc). Le basi hanno la corrente limitata da resistenze in serie (dipendente dal guadagno dei transistor, ma, in generale, 4k7 è un valore adeguato). Si possono sostituire i transistor BJT con MOSFET genere 2N7000, riducendo a 10 ohm o eliminando le resistenze di gate. Oppure, usando display a bassa corrente (2mA/segmento, ovvero 16mA per gli otto LED contemporaneamente accesi, il che non supera i 25mA limite dell' I/O) si potranno collegare i catodi comuni direttamente agli I/O, con un ulteriore risparmio di componenti.
Resistenze di limitazione sono poste in serie ai pin che comandano i LED (220-820 ohm a seconda della loro sensibilità). 

I tasti sono collegati tra i pin di comando delle basi e un pin comune (in questo caso RA3 o RA4), mantenuto a livello basso con un pull-down (10k). Se un tasto è premuto nel momento in cui il relativo RB va a livello alto per accendere il transistor collegato, questo livello si trova su RA3 e può essere letto. Se il tasto non è premuto, si leggerà 0. I diodi in serie evitano problemi nel caso in cui si premessero più pulsanti contemporaneamente.

Un connettore a 7 poli consente di collegare alimentazione, relè e cicalino, posti su un'altra scheda, mentre, usato solamente per i primi sei poli è un ingresso ICSP per collegare il Pickit (da osservare che per i 16F150x occorre il Pickit3).
In questo modo è possibile modificare il firmware senza togliere il chip dalla scheda.

Ma non solo questo.
Il PIC utilizzati hanno il motore ICD integrato: questo consente il debug in circuit direttamente attraverso il Pickit3, cosa estremamente utile durante lo sviluppo e anche per la didattica e l' apprendimento.

La sezione di alimentazione è separata per varie ragioni: il circuito può essere alimentato con una tensione già esistente e relè di uscita e cicalino possono assumere forme diverse a seconda delle necessità dell'applicazione.
Quindi, come base generica, è stato realizzato un supporto del tutto tradizionale, facilmente modificabile a seconda delle proprie esigenze:

Un  piccolo trasformatore EI30 da 1.5/2VA con secondario 9V alimenta un comune regolatore 7805 che produce la tensione stabilizzata di 5V per l' unità centrale. La tensione non stabilizzata viene usata per alimentare un relè SPDT.
Un jack coassiale consente di collegare in alternativa una tensione esterna, cc o ca, da 9 a 12V, disponibile da una qualsiasi fonte in grado di fornire la corrente necessaria al circuito (circa 30mA + il consumo del relè), ad esempio un wall plug o una batteria veicolare.
Il cicalino è collegabile sia alla tensione del relè che a quella stabilizzata, in modo da poter usare una ampia gamma di modelli.
I componenti sono del tutto comuni e per nulla critici. 

TR1 EI30 9V R1,R2 4k7
D2 ponte 1A R3/R4 22K
C1 1000uf/25V D1 1N4148, 1N4001
C2,C3 100nf JP1 pinhead 2.54, 7 poli
C4  100uf/10V CN1 5 poli passo 5.08
VR1 7805 BZ Cicalino
Q1,Q2 NPN Ry Relè 12V

Potranno essere aggiunti condensatori spegni arco sui contatti del relè

Dal punto di vista costruttivo, entrambi i circuiti sono realizzati su circuiti stampati a singola faccia, con un numero limitato di ponticelli, ma facilmente riproducibili in casa:

e questo è il risultato:

Sull'unità centrale sono stati usati componenti SMD per i transistore e per il condensatore da 100nF
Per l' alimentatore gli unici componenti SMD sono i due condensatori da 100nf tra i pin del regolatore.

I due circuiti sono sovrapponibili, ottenendo un pacchetto molto compatto:

 


Le specifiche di funzionamento.

Il timer conta a ritroso per un massimo di 999 secondi, visualizzabili su un display a tre cifre a sette segmenti, ben leggibili in qualsiasi condizione di luce.
Un relè con contatto di scambio (SPDT) viene acceso all’ avvio del conteggio e spento al termine. Un cicalino avvisa l’ utente al termine del conteggio.

Sono disponibili quattro pulsanti di controllo:

Alcuni pulsanti possono assumere diverse funzioni a seconda della modalità richiamata.
Ogni pulsante è associato ad un LED. 

Il timer di dispone di alcune funzioni di base:

  • START - il conteggio viene avviato. Al termine, il cicalino si attiva, avvisando l' utente
  • STOP - in qualsiasi momento il conteggio può essere annullato

Sono disponibili anche varie funzioni ausiliarie:

  • HOLD – il conteggio è arrestato, mentre il relè è attivo; il timer rimane in stato di HOLD fino a che non viene premuto il tasto START o il tasto STOP.
    Con il tasto START il conteggio riparte dal punto in cui era stato arrestato e con il tasto STOP il conteggio è annullato.
     
  • TEST – a conteggio inattivo, la pressione di questo tasto consente si accendere il relè per verificare il carico collegato. Il relè è attivato fino a che il tasto è premuto.
     
  • SET – consente di modificare il valore del conteggio
     
  • RCM - consente di richiamare tre valori memorizzati

Operatività.

All’accensione, il display riporta il valore della memoria corrente. 
Durante il conteggio il valore presentato si riduce di una unità ogni secondo.

I tasti possono avere più funzioni, a seconda della modalità attivata al momento.
La pressione dei tasti non attivi durante una determinata fase ha come effetto l’ emissione di un beep.

Il led relativo al tasto START, durante il conteggio,  indica lo stato del relè: se acceso, anche il relè è acceso.

Al termine del conteggio, il cicalino è attivato e può essere tacitato con la pressione di un qualsiasi tasto.

All’ avviamento sono attivi i tasti:
- START – punto 1.
- TEST – punto 2.
- SET – punto 5.
- RCM – punto 6.


Funzione dei tasti.


1. AVVIO TEMPORIZZAZIONE – Tasto START
Se il valore presentato sul display è 000, premendo il tasto START si ottiene un beep; occorre passare al punto 5 e caricare un valore diverso da 0 per poter avviare il timer.
Se il valore presentato sul display è diverso da 0, premendo START il led relativo si accende, il relè viene attivato e inizia il conteggio alla rovescia.
Esaurito il conteggio, il display presenta 000, il relè viene disattivato e il cicalino inizia a suonare una volta al secondo.
Il cicalino viene tacitato premendo qualsiasi pulsante. Questo fa ricaricare il contatore con il valore iniziale, che appare sul display, mentre il timer è pronto ad una nuova operazione.
Durante il conteggio, qualsiasi tasto che non sia HOLD o STOP ha come solo effetto un beep.



2. TEST – Tasto TEST
Il suo scopo è quelle di azionare il relè per verificare il funzionamento del carico collegato.
Se il conteggio non è avviato, il tasto STOP/TEST, quando premuto, porta in modalità test:
- il relè viene attivato
- si accende il led sul tasto START che indica l’ attivazione del relè
- il led sul tasto TEST lampeggia
- il display presenta il messaggio “tSt”
Questa condizione permane fino a che si mantiene premuto il tasto TEST. Al rilascio, i led si spengono e il relè viene disattivato. 
Il display torna a presentare il valore della memoria di conteggio corrente.



3. SOSPENSIONE DEL CONTEGGIO – Tasto HOLD
La sua funzione è quella di sospendere momentaneamente il conteggio, mantenendo il carico acceso.
Una volta avviato il conteggio (punto 1.), premendo il tasto START/HOLD, il timer entra in modo HOLD:
- il conteggio si arresta 
- il led del tasto lampeggia una volta al secondo
- il relè resta attivato
Premendo ancora il tasto START/HOLD, il conteggio riparte dal punto in cui era stato arrestato e il led del tasto è acceso fisso. Se non si interviene ancora sui tasti, il conteggio si esaurisce come al punto 1.
Premendo, invece, il tasto STOP/TEST, il conteggio viene annullato, il relè è disattivato e tutti i led sono spenti. Il contatore si riposiziona con il valore iniziale, che appare sul display, mentre il timer è pronto ad una nuova operazione.



4. ANNULLAMENTO DEL CONTEGGIO – Tasto STOP
La sua funzione è quella di terminare il conteggio prima dell' esaurimento del tempo.
Una volta avviato il conteggio (punto 1.), premendo il tasto STOP/TEST, il conteggio viene annullato, il relè è disattivato e tutti i led sono spenti. Il contatore si riposiziona con il valore iniziale, che appare sul display, mentre il timer è pronto ad una nuova operazione.



5. SETUP DEL CONTATORE – Tasto SET
La sua funzione è quella di consentire l' impostazione del tempo.
Se il conteggio non è attivo, la pressione del tasto SET porta il timer alla modalità di impostazione del valore del contatore.
Sono attivi i tasti:
- START/HOLD, corrispondente al display a sinistra (più significativo)
- STOP/TEST, corrispondente al display centrale
- RCM, corrispondente al display a destra (meno significativo)

Premendo uno di questi tasti, il punto decimale del display corrispondente si accende e il valore contenuto si decrementa di una unità. In questo modo è possibile aggiustare ogni singola cifra assai rapidamente.
Una volta eseguita la modifica, la pressione del tasto SET consente di uscire dalla modalità di setup, mentre il nuovo valore viene memorizzato e sarà richiamato alla prossima accensione.



6. GESTIONE MEMORIE – Tasto RCM
Il timer dispone di tre tempi memorizzati che sono richiamabili quando il conteggio non è attivo. Uno di questi valori viene utilizzato come memoria corrente e sarà utilizzato ad ogni riavvio fino ad una diversa programmazione.
Le memorie sono accessibili premendo il tasto RCM; tutti i led dei tasti vengono accesi.
Sono attivi i tasti:
- START , corrispondente alla memoria 3
- STOP, corrispondente alla memoria 2
- RCM, corrispondente alla memoria 1
Premendo questi tasti, viene richiamato a display il valore della memoria relativa, mentre il led del tasto lampeggia. E’ possibile premere successivamente i tasti per visualizzare i valori salvati nelle memorie.
Una volta scelto il valore voluto, premendo il tasto SET due volte si copia questo valore nella memoria corrente ed esso viene trasferito al contatore e al display.
Se si desidera modificare questo valore, premere il tasto SET una sola volta: questo porta in modalità setup, come al punto 5.
Se si desidera modificare più di un valore, ripetere la procedura.
I valori modificati sono conservati nella memoria non volatile del processore anche quando il timer è spento.


Il firmware.

Per varie ragioni, diversamente dallo stile di questo sito, viene rilasciato solamente il file .hex per programmare un PIC16F1507.

Nonostante questo, ci siamo impegnati a fornire comunque una serie di linee guida e informazioni per consentire la creazione di un proprio sorgente.

Innanzitutto va detto chiaramente che questo è uno dei moltissimi casi in cui, prima di scrivere una qualsiasi riga di istruzioni, occorre avere ben chiaro cosa si vuole ottenere.
Occorre, pertanto, stendere il flow chart che descrive cosa il programma dovrà fare; senza questo preliminare, scrivere istruzioni è del tutto insensato.

Questo è il flow chart dell' interrupt:

Abbiamo a che fare con un programma di complessità non elementare, in cui un interrupt viene utilizzato come elemento di tempo che ha lo scopo di condizionare sia il ciclo de multiplex, ma anche l'intervento del cicalino, la scansione dei tasti ed il loro debounce e il conteggio principale.
Il resto del programma dovrà gestire le funzioni legate ai tasti.

Come elemento di tempo è stato utilizzato il Timer0, con un ciclo di interrupt a 4ms. Questo fa si che ogni digit e i LED ausiliari siano accesi per 4ms ogni 16ms. La stessa cadenza è utilizzata per identificare i pulsanti premuti. Dato che ogni pulsante è verificato ogni 16ms, questo tempo è anche quello di debounce, che è più che adeguato per pulsanti di buona qualità. Se proprio dove introdurre componenti scadenti con tempi di rimbalzo maggiori, occorrerà allungare il tempo di debounce, ad esempio ad un doppio ciclo (32ms) o più.

Non viene gestita la pressione di tasti multipli, che, comunque, nella realizzazione fisica del pannello frontale, non facilmente ottenibile per errore. 

L' interrupt a 4ms alimenta un contatore da 100ms (25 x 4ms), usato per il lampeggio dei LED e per il cicalino.
Inoltre, alimenta un contatore da 1s (250x4ms) per il countdown principale. Alcuni flag hanno funzione di switch per attivare conteggio, lampeggio, buzzer.

La precisione del tempo dipende dalla precisione del clock interno, che il foglio dati dichiara all'1%, il che è più che adeguato per l' applicazione, senza ricorrere a cristalli esterni (nel peggior caso si tratta 10s su 16 minuti). Se si desidera una precisione maggiore, è possibile agire in due modi:

  • agire sul punto della routine di interrupt dove si collocano le istruzioni di ricarica del TMR0. Spostandole in avanti si rallenterà, aggiungendo cicli non compensati. Dovendo accelerare si userà un valore minore di carica del contatore del timer e si sposteranno le istruzioni fino a compensare il giusto valore di cicli.
  • usare Timer1, che, essendo a 16 bit, consente un aggiustamento più fine nel valore di carica di TMR1

Il ciclo relativo al programma principale consiste essenzialmente nell' analisi dei tasti.

Ogni tasto, se premuto dopo la fine del conteggio, cancella il cicalino e riporta al display il contatore corrente.
Il tasto START è attivo se il conteggio non è avviato. In tal caso, se il contatore non è a zero, viene avviato il countdown e acceso il relè. Il LED del tasto START è acceso.
Se il conteggio è attivo, il tasto assume la funzione HOLD, arrestando il conteggio, senza spegnere il relè.  Il LED del tasto START lampeggia.
Il conteggio riprende appena premuto ancora il tasto START oppure viene annullato (e il relè spento) con il tasto STOP.
Una serie di flag è usata per identificare per ogni fase, quali LED accendere, lampeggiare, ecc.

Il tasto STOP, se premuto al di fuori del conteggio, ha funzione di TEST: fino a che è premuto, il relè è attivato e il display presenta il messaggio "tSt". Il LED del tasto START è acceso, quello del tasto STOP lampeggia.
Rilasciando il tasto, il relè e i LED si spengono e il display riprende and indicare il contatore corrente.

Il tasto SET, ha, come gli altri, il compito di cancellare il cicalino a fine conteggio e ripristinare il contatore.
Se premuto durante il conteggio, genera un beep.
Se premuto al di fuori del conteggio, introduce la funzione di setup.
Questa si ottiene con i tasti START, STOP e RCM che corrispondono ognuno ad un digit. Quando premuti, il punto decimale del digit corispondente si accende, per identificarlo con chiarezza, mentre il valore viene decrementato di uno ad ogni pressione. In questo modo è possibile variare il contatore in pochi istanti. 
una nuova pressione del tasto SET memorizza il valore.
Il contatore è direttamente in BCD; questo permette di evitare la conversione BIN->BCD e viceversa.

La funzione del tasto di richiamo della memoria è analoga, a fine conteggio, a quella degli altri.
Se premuto durante il conteggio genera un beep.
Se premuto al di fuori del conteggio attiva la modalità di richiamo delle memorie.
Si tratta di tre valori che sono conservati nella EEPROM. Ognuno corrisponde ad uno dei tre tasti START/STOP/RCM.
Iil LED relativo al tasto premuto lampeggia e il display presenta il valore della memoria. 
Premendo SET, si passa alla fase di setup di questo valore. Se premiamo due volte consecutive SET il valore diventa quello della memoria corrente in uso nel contatore primario.


Enhanced Midrange.

Trasformare i flowchart in istruzioni e semplice, ma può esserlo meno se si affrontano per la prima volta gli Enhanced Midrange, che creano subito disorientamento negli utenti poco esperti, a causa di fogli dati di 400 e più pagine.

Dispongono di un set impressionante di periferiche integrate, tra cui le nuove, non presenti neppure nei PIC18F, oltre ad un set di istruzioni che contiene opcodes che pure non esistono negli altri PIC a 8 bit.
L' elevato numero delle periferiche e delle funzioni fa si che l'area RAM sia distribuita su ben 32 banchi, cosa che, di nuovo, mette a disagio il principiante.

Va detto che si tratta di PIC come gli altri, da affrontare con le stesse cautele e sicurezze del resto degli 8 bit: hanno i loro punti oscuri, ma presentano anche diversi vantaggi.

Tra i problemi iniziali, il primo che i programmatore arriva ad affrontare è quello del config iniziale, che, dato l' elevato numero di periferiche, è suddiviso su due registri:

;####################################################################
;             CONFIGURAZIONE

   errorlevel -303     ; suppress bogus CONFIG wordsize warning
; Oscillatore interno, no Clkout, no WDT, no CP, no MCLR

__config _CONFIG1,_FOSC_INTOSC & _CLKOUTEN_OFF & _WDTE_OFF & _MCLRE_OFF & _PWRTE_OFF & _BOREN_ON & _CP_OFF 
; no WRT, no LVP, no STVREN, BOR LP
__config _CONFIG2,_WRT_OFF & _STVREN_OFF & _BORV_LO & _LPBOR_ON & _LVP_OFF 
   errorlevel +303     ; reenable wordsize warning

A causa di un bug dell' Assembler, è probabile che la compilazione generi un errore di oversize del dato di configurazione. Poco male: basta disabilitare il messaggio di errore, riabiltandolo poi in uscita.
E' uno dei pochi casi in cui errorlevel- è utilizzabile sensatamente.

Mentre, invece, non va assolutamente inserito il famigerato errorlevel-302. Questo farebbe perdere i messaggi (che non impediscono la compilazione !) di segnalazione relativi a registri che non sono in banco 0 e quindi si rischia, per una qualsiasi piccola distrazione, di avere un programma che funziona in modo insensato, problema difficile da debuggare senza le segnalazioni del banco.
Se proprio vi danno fastidio i warning nel listato e nella finestra di output, prima ottenete un programma perfettamente funzionante, poi potrete inserire l' errorlevel-302.

Un altro particolare che può impressionare è il numero di funzioni concorrenti su uno stesso pin e, memori dei tranelli tesi da altri chip, ci si può aspettare una dura lotta per arrivare alle semplici funzioni digitali:

Fortunatamente la situazione è meno grave del previsto: tutte le nuove funzioni (CWG, CLC, NCO, PWM) e anche DAC e Vref non sono abilitate al POR. PEr abilitarle occorre programmare i relativi registri. Quindi le possiamo tranquillamente ignorare.

Restano le funzioni analogiche e in particolare gli ingressi del modulo ADC, che vanno disabilitati agendo sui registri relativi:

; azioni in bank3
  banksel ANSELA          ; bank3
  clrf    ANSELA          ; no input analogici
  clrf    ANSELB
  clrf    ANSELC

Da considerare che i registri sono in banco 3.

Invece, lieta sorpresa, il comparatore (finalmente) NON è abilitato al POR e quindi può essere ignorato.

Un particolare da considera, invece, è la frequenza dell' oscillatore interno, che, per default al POR è 500kHz. Occorre modificare il default se si desidera un diverso valore (anche se il programma può funzionare a 500kHz):

; clock 4MHz
  movlw b'01101011'
  movwf OSCCON
  btfss OSCSTAT, HFIOFS  ; wait for oscillator stable
   bra $-1

OSCCON è in banco 1.
 
Il Timer0 è gestito dal solito OPTION_REG:

; azioni in bank1
  banksel OPTION_REG   ; bank1
; disabilita T0CKI da RB5, prescaler 1:16 al Timer0
;       b'11111111'
;         1------- !WPUEN siailitato
;         -1------ INTEDG rising
;         --0----- clock interno
;         ---1---- falling
;         ----0--- prescaler al Timer0
;         -----011 1:16

  movlw b'11010011'
  movwf OPTION_REG
; per 500kHz TMR0=4(6) prescaler 1 -> option 01010000

Gli Enhanced Midrange hanno il registro LAT dei port accessibile come i PIC18F: questo permette di eliminare il problema R-M-W che affligge Baseline e Midrange. Purtroppo i LAT stanno in banco2 e se il programma opera normalmente al di fuori, occorre agire sullo switch di banco, il che è un aggravio per l' esecuzione. Si potrebbe pensare di mantenere l' esecuzione sul banco 2, ma i registri PORT sono in banco 0 e dove è necessaria una lettura degli I/O, il problema della commutazione dei banchi si ripresenta.

Nel nostro programma la soluzione è quella classica delle shadow, che, nello stesso tempo, fungono da registri dei flag.

Lo stato dei tasti è analizzato durante la routine di interrupt, nello step del relativo digit.
Ad esempio, per il digit 0, a cui è associato il tasto 0 (RCM):

; ---------------------------------------------------------
; display prima cifra LSdigit

Int_0:                 ; LSdigit
     movf  bcd1,w      ; low middle counter
     call  SegTable    ; converti in segmenti
     btfss dp0         ; check for dp
      bra  i_01        ; =0 - no dp
     iorlw b'10000000' ; =1 - add dp
i_01 movwf segmport    ; in uscita
     bsf   digk0       ; accendi digit
     nop
     bcf   key0        ; preset key flag
     btfsc keyin       ; key input=0?
     bsf   key0        ; n - set flag
; reload digit counter
     movlw digitnumber
     movwf digitcntr
     bra   Int_end

Il contatore principale è in BCD (2 bytes packed) e questo evita la necessità di avere una conversione BIN>BCD e viceversa per passare il contatore la display.
Occorre, invece, la solita lookup table:

; segment data table - display catodo comune
SegTable
  andlw 0x0F        ; solo nibble basso
  brw
  retlw b'00111111' ; "0" -|-|F|E|D|C|B|A
  retlw b'00000110' ; "1" -|-|-|-|-|C|B|-
  retlw b'01011011' ; "2" -|G|-|E|D|-|B|A
  retlw b'01001111' ; "3" -|G|-|-|D|C|B|A
  retlw b'01100110' ; "4" -|G|F|-|-|C|B|-
  retlw b'01101101' ; "5" -|G|F|-|D|C|-|A
  retlw b'01111101' ; "6" -|G|F|E|D|C|-|A
  retlw b'00000111' ; "7" -|-|-|-|-|C|B|A
  retlw b'01111111' ; "8" -|G|F|E|D|C|B|A
  retlw b'01101111' ; "9" -|G|F|-|D|C|B|A
  retlw b'00000000' ; " " -|-|-|-|-|-|-|- Ah = blank
  retlw b'01111000' ; "t" -|G|F|E|D|-|-|- Bh = t
  retlw b'01010100' ; "n" -|G|-|E|-|C|-|- Ch = n
  retlw b'01110001' ; "H" -|G|F|E|-|C|B|- Dh = H
  retlw b'01111001' ; "E" -|G|F|E|D|-|-|A Eh = E
  retlw b'01101101' ; "S" -|G|F|-|D|C|-|A Fh = S

che permette di presentare sia le cifre decimali cha alcuni caratteri.
Da notare l' uso dell'opcode brw al posto del solito addwf PCL,f.

I contatori sono salvati in HEF, la EEPROM dei PIC più recenti. Sull'argomento, trovate maggiori informazioni qui.

L'unico neo della HEF è il fatto che costringa a lavorare su una intera riga (in questo  caso di 32 bytes) anche se ne vanno salvati solo 8. Comunque, i meccanismi di scrittura e di movimentazione di array di dati sono efficienti e nel chip è comunque disponibile una discreta quantità di risorse dei memoria.

Ad esempio, il trasferimento di n bytes da un punto ad un altro della memoria dati è realizzabile con una semplice macro, che fa uso dell' indirizzamento indiretto post indicizzato e delle istruzioni  moviwmovwi .
Ricordiamo che l' uso dei puntatori indiretti consente di accedere all' intera RAM senza preoccuparsi dei banchi.

; Copy n bytes da source a target
COPYMEM MACRO source, target, nbyte
   local c_0
    movlw  nbyte
    movwf  temp
    movlw  low(source)
    movwf  FSR0L
    movlw  high(source)
    movwf  FSR0H
    movlw  low(target)
    movwf  FSR1L
    movlw  high(target)
    movwf  FSR1H
c_0 moviw  FSR0++
    movwi  FSR1++
    decfsz temp,f
     bra   c_0
       ENDM

Dato che la macro può essere richiamata più volte, occorre utilizzare per il branch bra o il simbolo $- o, come in questo caso, una label, condizionata come local.

Nel caso del 16F1507 il programma, non particolarmente ottimizzato, data la sua originale destinazione per didattica, impiega circa il 45% della memoria programma e il 25% della RAM dati. 
Volendo scrive il sorgente con un compilatore C, si potrà optare inizialmente per 16F1509, che ha risorse di memoria molto più ampie, per poi passare, una volta ottimizzato l'eseguibile, al chip "minore".


ICD.

16F1507/08/09 hanno il motore ICD integrato, il che è di grandissima utilità durante il debug ed è un elemento essenziale per una attività di apprendimento dei meccanismi di funzionamento del microcontroller.
Quindi, è possibile eseguire il debug in circuit direttamente con il Pickit3.

Va specificato che occorre l'ambiente MPLAB-X, dato che MPLAB-IDE, fermatosi alla versione 8.92, non supporta correttamente i nuovi processori.

Per chi volesse utilizzare questa funzione, consigliamo di spostare il pin di ingresso dei pulsanti su RB4, dato che RB3 serve all'ICD per il debug.

Segnaliamo comunque che esiste un header, AC 244051, molto interessante, dato che permette il debug in circuit, senza alcuna perdita di pin, per 12F1501, 16F1503 e 16F1507/8/9.

Per ultimo, ricordiamo che questi chip esistono anche nella versione LF, con un range di alimentazione da 1.8 a 3.6V.


 


 

Copyright © afg. Tutti i diritti riservati.
Aggiornato il 21/06/15.