ESERCITAZIONE # 8
Comandare uno shift register
con le istruzioni di Rotate
e utilizzare un driver modulare.
In questa esercitazione comandiamo un registro a scorrimento (shift register)
del tipo SIPO (serial input-parallele output).
Vedremo inoltre l' innesto nel programma, con la direttiva #include di un driver
specifico per comandare lo shift register scelto.
Esistono diversi componenti che svolgono la funzione di registro di
scorrimento e qui proviamo ad
utilizzare il comune e diffuso 164, nella versione HC164.
L' esercitazione impiega la scheda SIPO164, descritta
qui
La sequenza dei segnali di lavoro è identificata in questo diagramma
La procedura di trasferimento di un dato dal microcontroller al registro a
scorrimento è la seguente:
- azzeriamo il contenuto dei flip-flop portando a livello basso il terminale
di clear
- iniziamo con il porre il primo bit da trasferire su un pin configurato
come uscita del microcontroller e collegato all' ingresso dello shift
register
- applichiamo ora un impulso di clock ai flip-flop. Il loro collegamento a
catena fa si che il dato contenuto in ogni flip-flop passi al successivo,
quindi il dato applicato all' ingresso sarà immagazzinato nel primo latch.
- poniamo ora il secondo dato e ripetiamo l' impulso di clock: il dato
precedentemente inserito scorre dal primo al secondo flip-flop mentre nel
primo sarà immagazzinato il dato ora caricato
- ripetiamo l' operazione fino ad esaurimento degli 8 bit del dato: ora ogni
flip-flop contiene uno dei bit del dato ed essi sono accessibili ai pin di
uscita dello shift register.
Questo trasferimento di dati dal processore alla periferica è di tipo
seriale, in sincronia con il clock, quindi richiede le linee dato+clock
(similmente alla comunicazione SPI. Però dato+clock è meno formale di SPI e
non prevede un segnale di uscita dalla periferica. Quindi, comunicazioni di
questo genere possono anche essere trattate dal modulo MSSP presente nei PIC18,
ma, data la semplicità dell' algoritmo, solitamente risulta più pratica la
soluzione di scrivere qualche istruzione ad hoc.
Il flow chart del programma è questo.
|
Dopo la necessaria inizializzazione del processore e del port
utilizzato per i comandi allo shift register, il dato da inviare viene
posto in WREG.
Quindi viene chiamata una subroutine che si occupa di inviare bit per
bit il dato al 164.
Questa subroutine si configura come un vero e proprio driver software
per il comando di quella determinata periferica SIPO che l' HC164.
Va considerato che esistono altri SIPO che possono essere impiegati
in questa applicazione (ad esempio CD4094) che hanno caratteristiche
differenti.
Il creare un modulo con la funzione di uscita relativo al componente
SIPO utilizzato permetterà di mantenere invariato tutto il resto del
programma sostituendo solamente il drive in relazione al componente
usato.
Per questa ragione si utilizza la semplice tecnica di
"passare" il dato in uscita attraverso l' accumulatore WREG.
|
Il programma, poi, eseguito lo shift degli 8 bit, si arresta con il già
visto loop di blocco.
|
Il drive vero e proprio è schematizzato nel flowcharf qui a lato.
Per prima cosa il dato viene passato dall' accumulatore WREG ad un
registro RAM intermedio (a cui è applicata la label SerialData).
Poi viene caricato un contatore (un' altra locazione RAM con label
HC164Cntr) con il numero dei bit da shiftare.
E' buona norma che i pin usati per una simile applicazione siano
lasciati, all' uscita del driver, in una condizione determinata. In
questo caso si è scelto di portare sia la linea del clock che quella
dei dati a livello basso. Questo permette di sapere con certezza lo
stato di quelle linee all' inizio e al termine dell' esecuzione del
driver.
La funzione chiave di comando dell' uscita è legata al test dello
stato del bit 7 del dato.
Questo è possibile in quanto nel set Enhanced ci sono istruzioni per la
rotazione senza interessare il Carry.
Lo stato del pin di uscita è presettato a 0: se il bit 7 del dato è
a 0, l' uscita non sarà modificata; se invece il bit 7 è a 1 l' uscita
sarà posta anch'essa a 1.
Segue subito la generazione di un impulso di clock, portando a
livello alto e popi riabbassando il pin del clock seriale. Esclusa la
versione CMOS (C164) tutte le altre versioni hanno la possibilità di
lavorare con clock di almeno 20 MHz, il che rende inutile una
temporizzazione (stretch) della durata dell' impulso di clock.
terminato l' impulso del clock, si riporta a 0 il pin di dato e si
effettua un decremento del contatore: se il contatore è arivato a 0
vuol dire che sono stati shiftati tutti i bit del dato. Altrimenti si
ripete il loop.
Da notare che la rotazione, avvenendo sul file SerialData stesso,
porta ad ogni passo un nuovo bit nella posizione 7 per il test di
uscita. Al termine delle rotazioni il contenuto del registro sarà
quello di inizio algoritmo.
Alla fine dell' algoritmo, la routine rientra al programma chiamante. |
Con una rotazione a sinistra iniziamo a shiftare il bit di peso maggiore,
che, al termine della routine si troverà posizionato all' uscita Q7 dello shift
register, con il bit 0 del dato corrispondente all' uscita Q0.
Ovviamente, eseguendo una rotazione a destra e analizzando il bit 0 invece
del 7 avremmo una uscita dei bit a specchio.
Questo è ottenibile senza variare il programma principale, ma solo
realizzando un diverso driver, che è in effetti un "modulo
software", ovvero un blocco funzionale autonomo progettato per svolgere un
certo compito e che comunica con il programma chiamante attraverso una
interfaccia definita.
Il driver avrà quindi:
- una funzione di uscita e una di ingresso
- un certo impiego di memoria RAM
- la possibilità di chiamare altri moduli
La documentazione relativa permetterà di inserire il modulo nel proprio
programma senza creare interferenze con il resto del programma stesso (ad
esempio, conflitti nell' uso di registri, overflow dello stack, ecc).
Come visto in precedenza per un altro modulo, anche questo può essere
collezionato in una libreria ed utilizzato in qualsiasi altra situazione dove s
renda necessario, senza riscrivere nulla.
Per quanto riguarda la connessione con il PIC, basteranno 3 conduttori,
ovvero 3 pin di un port:
- un segnale per i dati
- un segnale per il clock
- un segnale per il clear
Inoltre sarà necessario alimentare l' interfaccia, collegandola alla Vdd/Vss.
Il Pickit è inserito direttamente nella spina ICSP/ICD e permette un debug passo passo delle
istruzioni.
Per chi non avesse chiare le connessioni, qui trova di seguito una pagina dedicata.
L' esercizio richiede le seguenti risorse:
- MPLAB IDE installato
- Pickit3 (o Pickit2)
- 28-40pin UniBoard con PIC18F2321
0 4321 (o 2221 o 4221 o altro hardware similare)
- 5 cavetti jumper da 14-15 cm
- il modulo SIPO164
con il suo modulo LED (oppure l' hardware che realizza lo schema
equivalente).
Il listato sorgente è una estensione di quello già visto negli altri
esercizi e che fa da base per tutti i seguenti, aggiungendo gli elementi
necessari al nuovo lavoro.
Analogamente ai precedenti sorgenti, iniziamo con una configurazione del
processore.
;---------------------------------------------------------------------
; Configurazione
;---------------------------------------------------------------------
CONFIG LVP = OFF
CONFIG OSC = INTIO1
CONFIG MCLRE = ON
CONFIG WDT = OFF
CONFIG BOR = ON
CONFIG DEBUG = ON
CONFIG PWRT = OFF
CONFIG BORV = 1
|
E' pratico assegnare label ai pin di controllo dello shift register
;---------------------------------------------------------------------
; Equates
;---------------------------------------------------------------------
#define HC164datapin
PORTC,6 ; shift dato a RC7
#define
HC164clkpin PORTC,7 ; clock a RC6
#define
HC164clrpin PORTC,2 ; clear a RC0 |
Il programma vero e proprio è assai semplice e ricalca il flow chart appena
visto:
;----------------------------------------------------------------------
; Inizio programma
; vettore di RESET
ORG
0x00
Main nop
; per debug
clrf
LATC
; preset POTC a 0
clrf
TRISC
; tutto PORTC come uscita
; liberiamo il Clear dello shift register
bsf PORTC, 0
; bit 0 di PORTC = 1
; tutti i LED collegati alle uscite dello shift register sono spenti
; carichiamo un valore da
presentare sui LED
movlw
b'10101010'
; AAh
; chiamiamo la routine di shift
call
HC164Out
; loop di stop
lock bra
lock
|
Il drive è prelevato da una libreria e inserito nel programma con un
include. Trattandosi di una subroutine, può essere piazzata in coda al template,
nell' area dei driver
;---------------------------------------------------------------------
; Drivers
;---------------------------------------------------------------------
#include
"C:\PIC\Library\Drivers\HC164Out18_W.asm" |
In particolare, il modulo driver usato è il seguente:
;**********************************************************
; Shift register generic driver for HC164
; Send 8 bit to shift register
; Data to send come in W
; End w/ HC164 data and clock pin = 0
;**********************************************************
;---------------------------------------------------------------
HC164Out: ; move 8 bit from WREG to shift register
bcf
HC164clkpin ;and HC164 clock = 0
setc
;carry=1 for first rotate
hc164l bcf HC164datapin ;preset HC164 data = 0
rlcf
WREG,w ;rotate data to carry
bz
hc164e ;if data=0, loop's end
bnc
hc1640 ;if not, check carry
bsf
HC164datapin ;y - HC164data = 1
nop
;stabilization wait
hc1640 bsf HC164clkpin ;shift reg clock high
;nop
;only if Vdd < 5V
bcf
HC164clkpin ;shift reg clock low
bcf
HC164datapin ;HC164data pin =0
clrc
;inject 0 on rotate
bra
hc164l
hc164e return |
Per una descrizione particolareggiata dell' algoritmo, trovate maggiori
informazioni qui.
Va notato che il driver utilizza solamente label e nessun valore assoluto:
questo è indispensabile per permettere di cambiare la configurazione hardware
del pin di comando semplicemente cambiando le
label fissate degli equates iniziali, senza nessuna necessità di modificare il
driver.
Il sorgente termina con lo statement END.
Se si incontrano errori nella compilazione è opportuno verificarli con la
lista di descrizione degli errori e correggere dove si è sbagliato.
Il file compresso di questa esercitazione è scaricabile dall'
area di download.
|