Progetti - PIC

 

Demo board per SIPO '164 

 


Il driver nel set istruzioni Enhanced

Nei PIC16F l' operazione:

     rlf  WREG, w         

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:

     rlcf  WREG, w         

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.


 

Copyright © afg. Tutti i diritti riservati.
Aggiornato il 21/04/11.