>>> LINK A PAGINA AGGIORNATA <<<
- .
- .
- .
- .
- .
- .
- .
- .
- .
- .
- .
- .
- .
- .
- .
- .
- .
- .
- .
- .
Shift register
Gli shift register (registri a scorrimento) possono essere usati per estendere virtualmente senza limiti gli ingressi e le uscite di sistemi a microprocessore/microcontrollore. Ad esempio collegando in serie 12 registri di tipo PISO come il CD4021, è possibile leggere 96 ingressi usando solo tre terminali di una periferica SPI, oppure di una porta di I/O opportunamente pilotata da software con tecnica bit-bang.
CD4094 (SIPO) Serial Input Parallel Output
- Se OUT ENABLE = 0 le uscite Q1..Q8 sono in HI-Z.
- I segnali in ingresso devono essere ben squadrati e l’impulso di clock non deve durare meno di 200 nanosecondi.
- I bit vengono shiftati sul fronte di salita del CLOCK.
- Il primo bit che entra da SER IN finisce su Q8, l’ultimo su Q1.
- Il valore di Q1 viene memorizzato con l’8° impulso di clock e in questo momento su SER OUT appare il valore di Q8.
- SER OUT serve per connettere in serie più SIPO.
- I dati caricati nello shift register vengono portati sulle uscite con l’impulso di strobe.
CD4021 (PISO) Parallel Input Serial Output
- Con l’impulso a 1 di LOAD vengono acquisiti gli ingressi P1..P8, e su SER OUT diventa già disponibile il valore di P8.
- Il valore di P1 è disponibile su SER OUT dopo il 7° impulso di clock.
- Con l’8° impulso di clock su SER OUT è disponibile il valore di SER IN.
- SER IN serve per collegare in serie più PISO.
Scrittura su shift register con Arduino
Con il seguente schema verifichiamo se la funzione ‘shiftOut’ è adatta a comandare uno shift register CD4094.
NOTA: la resistenza sul reset serve per disabilitare l’autoreset di Arduino2009, che avviene ogni volta che la porta seriale emulata su USB viene aperta. L’autoreset serve per mettere il bootloader in ricezione. Se entro poco tempo il bootloader non riceve dati allora avvia il programma (sketch) attualmente caricato. È un sistema molto comodo durante lo sviluppo, ma diventa deleterio quando con un altro programma si vuole comunicare con un’ applicazione già in funzione su Arduino, perché ad ogni apertura della porta seriale si causerebbe il reset.
Sketch per testare la trasmissione di un numero binario crescente da visualizzare sui led (Q8 è il bit più significativo, chiamato anche MSB). All’inizio si associano dei nomi significativi ai terminali di Arduino, e si inizializza una variabile globale di tipo byte. Seguono le due funzioni principali obbligatorie in ogni programma per Arduino: ‘setup’ viene eseguita solo una volta all’inizio e serve appunto per i settaggi iniziali, mentre ‘loop’ viene eseguita in continuazione e rappresenta il mainloop, cioè il ciclo principale del programma.
//_________________________________________________________ // // Test funzione shiftOut su shift register CD4094 // By C.Fin 2012 //_________________________________________________________ #define sipo_strobe 2 #define sipo_data 3 #define sipo_clock 4 //_________________________________________________________ byte counter = 0; //_________________________________________________________ void setup() { pinMode(sipo_strobe, OUTPUT); pinMode(sipo_data, OUTPUT); pinMode(sipo_clock, OUTPUT); digitalWrite(sipo_strobe, LOW); digitalWrite(sipo_clock, LOW); } //_________________________________________________________ void loop() { shiftOut(sipo_data, sipo_clock, MSBFIRST, counter); digitalWrite(sipo_strobe, HIGH); digitalWrite(sipo_strobe, LOW); counter += 1; delay(100); } //_________________________________________________________
Il codice prodotto dalla compilazione occupa 1202 byte dei quasi 32k disponibili. Ha funzionato al primo colpo, e togliendo la funzione delay (che ha il solo scopo di rallentare il processo per poter osservare comodamente il movimento dei led) i risultati sono stati i seguenti: il mainloop dura 130us, effettua cioè 7694 scritture complete al secondo sullo shift register, equivalenti a più di 61kbit/s di velocità. Questo vuol dire ad esempio poter aggiornare 770 volte al secondo 80 uscite digitali ottenute da una serie di 10 shift register.
Per determinare il numero di scritture al secondo è stato sufficiente misurare la frequenza del segnale ‘sipo_strobe’ con un frequenzimetro (questo segnale infatti è la “conferma” che trasferisce sulle uscite dello shift register gli 8 bit appena ricevuti).
Lettura da shift register con Arduino
Prova per verificare se la funzione ‘shiftIn’ è adatta a leggere uno shift register CD4021.
Sketch per testare la lettura da shift register e ritrasmissione su porta seriale (P8 è il bit più significativo).
//_________________________________________________________ // // Test funzione shiftIn su shift register CD4021 // By C.Fin 2012 //_________________________________________________________ #define piso_load 2 #define piso_data 3 #define piso_clock 4 int n; //_________________________________________________________ void setup() { pinMode(piso_load, OUTPUT); pinMode(piso_data, INPUT); pinMode(piso_clock, OUTPUT); digitalWrite(piso_load, LOW); Serial.begin(38400); } //_________________________________________________________ void loop() { digitalWrite(piso_clock, HIGH); digitalWrite(piso_load, HIGH); digitalWrite(piso_load, LOW); n = shiftIn(piso_data, piso_clock, MSBFIRST); Serial.write(n); delay(100); } //_________________________________________________________
Non ha funzionato al primo colpo per una questione di polarità del clock: il CD 4021 shifta i dati in corrispondenza del fronte di salita del clock. Le soluzioni sono due, o si inverte il livello di piso_clock con un transistor, oppure, come in questo sketch, si predispone ogni volta il livello di piso_clock alto prima dell’impulso di acquisizione piso_load.
Il funzionamento è stato verificato tramite un programma ricevente scritto in Python, e si è di nuovo misurata la velocità massima togliendo la trasmissione seriale e il delay. I risultati sono stati molto simili a quelli precedenti: 7480 letture al secondo.
Programma ricevente su PC in Python (2 e 3), il numero binario viene visualizzato in una piccola finestra:
try: import tkinter as tk except ImportError: import Tkinter as tk import serial import struct //_________________________________________________________ def ricevi(): try: n = struct.unpack("B", ser.read(1))[0] testo.configure(text='{:08b}'.format(n)) except: testo.configure(text="No ricezione") gui.after(20, ricevi) //_________________________________________________________ PORTA = "..." ser = serial.Serial(PORTA, 38400, 8, "N", 1, timeout=1) gui = tk.Tk() gui.resizable(False, False) testo = tk.Label(gui, width=20, font=("monospace", 20)) testo.pack() ricevi() gui.mainloop() ser.close()
Un utilizzo “inusuale”: interfaccia seriale->parallela di emergenza
Per aumentare il numero di ingressi uscite di un sistema si possono usare anche i port expander i2c.
(4/8/2018)