LO SCAFFALE DEGLI HOBBY

Appunti On Line

AVVERTENZE da leggere attentamente


ELETTRONICA

Shift register 8 bit


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

schema schema

schema
Collegamento in serie di due CD4094



CD4021 (PISO) Parallel Input Serial Output

schema schema



Scrittura su shift register con Arduino

Con il seguente schema verifichiamo se la funzione ‘shiftOut’ è adatta a comandare uno shift register CD4094.

schema

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. Su altri tipi di Arduino l'autoreset si evita collegando un condensatore elettrolitico da 10µF tra il reset e GND.

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).
foto



Lettura da shift register con Arduino

Prova per verificare se la funzione ‘shiftIn’ è adatta a leggere uno shift register CD4021.

schema

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:

img

//_________________________________________________________
//
// Visualizzatore dato binario da seriale
// By C.Fin 2012
//_________________________________________________________
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.





All'indice principale | Al vecchio sito