Esercitazioni ASM - PIC18

 


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.

 

 

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