Il driver nel set istruzioni Enhanced
Nei PIC16F l' operazione:
non è possibile in quanto il registro W non è indirizzabile. Occorre
allora utilizzare un registro intermedio:
movf
temporaneo
rlf temporaneo, w |
Invece, un particolare molto interessante del set istruzioni dei PIC18F è
quello di poter utilizzare l' accumulatore WREG in modo del tutto analogo agli
altri SFR.
Quindi è possibile scrivere semplicemente:
In questo modo, la rotazione che interessava il registro intermedio può
essere effettuata direttamente in WREG, senza occupare alcuna locazione di RAM
ausiliaria.
Se poi ricorriamo ad un piccolo trucco con il Carry, possiamo fare a meno
anche della locazione di RAM utilizzata come contatore per i passi dello
shift.
Ne deriva il seguente flowchart:
|
Il dato da shiftare arriva al drive attraverso l' accumulatore WREG
e qui è lasciato: non corre più una copia nel registro RAM
intermedio.
Viene settato il Carry per iniettare un 1 iniziale nel registro
ruotato.
Quindi si esegue una rotazione di WREG su se stesso attraverso
il Carry
Testando il bit Z dello STATUS è possibile verificare se il contenuto
del registro è andato a zero (le istruzioni di rotate negli Enhanced
modificano anche i bit Z e N).
Se W è a zero, il loop è esaurito e si esce. Se non è a zero, ci
sono ancora shift da effettuare (e non andrà sicuramente a zero prima
di 8 shift, qualunque sia il suo contenuto iniziale dato che abbiamo
iniettato un 1 nel bit 0 al primo shift).
Un test sul Carry consente di adeguare il livello del pin dati, a
cui segue l' impulso di clock.
Ora il Carry viene azzerato in modo tale che la prossimo rotate sia
iniettato uno 0 in WREG.
Ogni rotazione porta un nuovo bit di WREG nel Carry per il test di
uscita. Al termine delle rotazioni il contenuto del WREG sarà 0.
Alla fine dell' algoritmo, la routine rientra al programma
chiamante.
Gli otto shift sono eseguiti senza necessità di appoggio ad una
RAM per il contatore e senza bisogno della copia in RAM del contenuto
di WREG. |
Trasferito in istruzioni, abbiamo la seguente lista:
;***************************************************************
;** HC164Out18_W.asm subroutines module for PIC18F
**
;***************************************************************
;***************************************************************
;** AVAILABLE FUNCTIONS
**
;**
**
;** HC164Init initialize I/O
**
;** HC164Out move 8 bit from WREG to shift register
**
;**
**
;***************************************************************
NOLIST
;**
**
;** Title : Universal Driver for SIPO '164
**
;** Enanched instruction set
**
;** Date : 19-04-2009
**
;** Version : V.01
**
;** Autore : afg
**
;**
**
;***************************************************************
;** External Resources : none
**
;** Supported by : MPASM 7 or higher
**
;***************************************************************
;** DESCRIPTION
**
;**
**
;** Shift register driver for HC164.
**
;** Send 8 bit to shift register.
**
;** Data to send come in W.
**
;** End w/ HC164 data and clock pin = 0.
**
;**
**
;** Optionally driver the Clear line, enabled by definition: **
;** #define HC164CLEAR
**
;**
**
;***************************************************************
;** RESOURCES
**
;**
**
;** 2 GPIO from any port (RA4 is open drain !)
**
;** Attention: all line must be set as digital output
**
;** HC164datapin ; data output pin
**
;** HC164clkpin ; clock output pin
**
;** HC164clrpin ; clear out pin
**
;**
**
;** The drivers don't use any RAM
**
;** The driver don't call other subroutines
**
;**
**
;***************************************************************
;** Suggested equates & definitions
**
;** -------------------------------
**
;** Optional definition for use Clear line
**
;**
**
; #define HC164CLEAR
**
;**
**
;** -------------------------------
**
;** I/O Equates Example
**
;**
**
;#define HC164datapin LATC,7 ; data output pin
;#define HC164clkpin LATC,6 ; clock output pin
;#define HC164dataTris TRISC,7 ; data direction
;#define HC164clkTris TRISC,6 ; clock direction
; #ifdef HC164CLEAR
;#define HC164clrpin TRISC,0 ; clear direction
;#define HC164clrpin LATC,0 ; clear output pin
; #endif
;**
**
;***************************************************************
; Local definition
#ifndef CARRY
#define CARRY STATUS,0
#endif
;
;---------------------------------------------------------------
; Local pseudo opcodes
#ifndef setc
#define setc bsf CARRY
#endif
#ifndef clrc
#define clrc bcf CARRY
#endif
;
;---------------------------------------------------------------
HC164Init
; initialize I/O pin - must be set as digital
bcf HC164datapin
; pre clear latch
bcf HC164clkpin
bsf HC164dataTris
; set direction as output
bsf HC164clkTris
#ifdef HC164CLEAR
; optional Clear line
bsf HC164clrpin
bsf HC164clrTris
#endif
return
;---------------------------------------------------------------
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
bcf
HC164clkpin ;shift reg clock low
bcf
HC164datapin ;HC164data pin =0
clrc
;inject 0 on rotate
bra
hc164l
hc164e return
;***************************************************************
; Examples of macros for drive Clear pin
;---------------------------------------------------------------
; HC164 Macros for Clear pin
;HC164Clear MACRO
; bcf HC164clrpin
; ENDM
;HC164Enable MACRO
; bsf HC164clrpin
; ENDM
; #endif
;***************************************************************
LIST |
I dettagli
Sono da notare alcuni dettagli, in primo luogo la generazione di alcune
label con lo scopo di sostituire richiami meno comprensibili.
In particolare, qui, attraverso la direttiva #define,
creiamo la label CARRY che sarà
interpretata dall' Assembler come STATUS,0.
La condizione #ifndef crea
la label solamente se non risulta definita in un altro punto del
sorgente.
;***************************************************************
; Local definition
#ifndef CARRY
#define CARRY STATUS,0
#endif
; |
Per ottimizzare il sorgente e la sua comprensibilità, sempre
attraverso la direttiva #define,
creiamo due pseudo-opcodes per manipolare il Carry:
- la label setc che MPASM interpreterà
come bsf CARRY
- la label clrc che MPASM interpreterà
come bcf CARRY
Come sopra, la definizione viene eseguita solamente se non risulta definita
in un altro punto del sorgente.
;---------------------------------------------------------------
; Local pseudo opcodes
#ifndef setc
#define setc bsf CARRY
#endif
#ifndef clrc
#define clrc bcf CARRY
#endif
; |
Il core del driver replica sotto forma di istruzioni il flow chart visto
prima. Si possono notare i seguenti punti:
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 |
Abbiamo visto che questa sequenza è possibile in base a due
considerazioni:
- negli Enhanced WREG è trattabile come qualsiasi altro registro
- l' istruzione rlcf
degli Enhanced modifica i bit di STATUS C, Z, N
per cui è possibile effettuare test su questi flag.
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 |
bz è
un opcode del set Enhanced che fa saltare il program counter alla label
indicata in oggetto se il flag Z è settato (ovvero se il risultato del rotate
manda a zero il contenuto del WREG).
Il nop
è aggiunto solamente se è necessario portare a 1 il pin dati, allo scopo di
stabilizzare il livello all' ingresso dello shift register nel caso di
connessioni lunghe. Se necessario, si possono aggiungere altri nop
fino ad avere la sufficiente stabilità. Questo diventerà indispensabile per
tensioni di alimentazione basse: a 2 V (limite dei 18LF) il tempo di setup
dato prima del clock è indicato nel foglio dati dell' HC164 in 125 ns.
Per il pin a livello 0 una attesa non serve in quanto questo livello è già
assegnato prima dell' ingresso del driver e quindi già stabilizzato.
hc1640 bsf HC164clkpin
;shift reg clock high
; nop
for Vdd < 5V
bcf HC164clkpin
;shift reg clock low |
'164 carica i flip-flop sul fronte di salita del clock, quindi a seguito
dell' istruzione bsf HC164clkpin.
A 5V di alimentazione, il foglio dati riporta un tempo di clock a livello alto
(Tw) di 20 ns, per cui la successiva istruzione bcf
HC164clkpin può seguire senza pause per qualsiasi frequenza
di clock del processore attualmente supportato dai PIC18F.
Per contro, questo tempo sale a 100 ns se la tensione di alimentazione scende
a 2V, limite di funzionamento dei PIC18LF. In questo caso sarà necessario
aggiungere uno o più nop
tra le due istruzioni.
hc1640 bsf HC164clkpin
;shift reg clock high
bcf HC164clkpin
;shift reg clock low
bcf HC164datapin
;HC164data pin =0
clrc
;inject 0 on rotate
bra hc164l
hc164e return |
Dopo il ritorno a livello basso del clock, il dato viene riportato
immediatamente a 0 per il prossimo ciclo.
Questo non richiede alcuna tempozrizzazione in quanto il foglio dati indica il
tempo di Hold in soli 5 ns.
COme in precedenza il driver richiede le seguenti inizializzazioni per le risorse:
;***************************************************************
; Suggested equates
; --------------------
; Optional definition for use Clear line
;
#define
HC164CLEAR
;
; --------------------
; I/O Equates Example
;
#define HC164datapin
LATC,7
; data output pin
#define HC164clkpin
LATC,6
; clock output pin
#define HC164dataTris
TRISC,7 ; data direction
#define HC164clkTris
TRISC,6 ; clock direction
#ifdef
HC164CLEAR
#define HC164clrpin
TRISC,0 ; clear direction
#define HC164clrpin
LATC,0
; clear output pin
#endif
;
;*************************************************************** |
che dovranno essere aggiunte al sorgente.
I pin di comando sono inizializzati singolarmente per poter essere disposti su
qualunque port (ricordando che RA4 è solitamente un open drain). Se si usano
altri pin rispetto a quelli indicati come esempio, andranno modificate di
conseguenza le definizioni
Come in precedenza il parametro HC164CLEAR, se definito, abilita l' uso di un pin per comandare
il Clear dello shift register. Se non necessario, la definizione va esclusa.
E i comandi in uscita sono dati sui LAT per evitare ogni problema di R-M-W.
Il CLEAR
Come detto, il parametro HC164CLEAR
introduce un terzo pin di comando.
Questa funzione può non essere secondaria in quanto, all'arrivo della
tensione, il contenuto dei flip-flop non è determinato.
Inoltre va considerato che i pin del processore sono, al POR, configurati come
ingressi, quindi ad alta impedenza. I pull-up mantengono gli ingressi dello
shift register a livello alto.
Mentre il processore prende il controllo dell' I/O possono generarsi
situazioni in cui allo shift register arrivano impulsi di clock non
desiderati, iniziando una precarica di dati non voluti.
La linea del Clear servirà, allora, per mantenere "pulito" il
contenuto dei flip-flop fino a che non si inizia il caricamento dello shift
register.
Se è necessaria una situazione di partenza con tutte le uscite dello shift
register a zero, il pin clear sarà necessario.
Sono anche possibili due soluzioni hardware:
- la prima è quella di far dipendere il clear del 164 dal Reset del
processore, collegando queste linee assieme
- la seconda è quella di dotare lo shift register di un reset hardware,
realizzato con una rete RC sul pin di clear, in modo da avere un impulso
di reset basso all' avviamento
Il sorgente del driver è scaricabile
qui.
Altre informazioni su questa struttura sono
disponibili qui.
|