74HC165

Ho dei problemi nell'usare questo P/S shift register.
Sto facendo degli esperimenti con un chip di SRAM parallelo (no I2C, no ISP) collegato esternamente: uso 2 shift register S/P 74HC595 per l'invio dell'indirizzo e di un terzo 74HC595 per la gestione del bus dati. Il 74HC165 lo uso per leggere i dati dalla SRAM, convertendo il valore letto sul bus parallelo in dato seriale.
Letto il dato, lo salvo nella EEPROM del uC, per successivi controlli (per verificare se lo sketch e l'hardware stanno funzionando correttamente).

Il mio problema è che la lettura dell'EEPROM mi rivela che non riesco a leggere dalla SRAM (o forse non ci riesco a scrivere, devo ancora capirlo).

Per iniziare a circoscrivere il problema, volevo intanto capire come usare questo chip. Nel playground ho trovato un tutorial in cui si fa riferimento a del codice che a mio parere è datato dato che ho trovato l'istruzione ShiftIn per la lettura seriale di un byte di dati che nel tutorial non viene usato.

Iniziamo con i collegamenti. Questi sono i PIN del chip che ho utilizzato:
1: SH-/LD
2: CLK
3: D4
4: D5
5: D6
6: D7
7: /Q7
8: GND
9: Q7
10: Ds
11: D0
12: D1
13: D2
14: D3
15: /CE
16: Vcc

Ho messo il pin 16 collegato all'alimentazione e l'8 a massa. Anche il pin 15 è a massa.
Poi ho collegato i pin D0-D7 ai pin di I/O del chip SRAM.
Poi ho collegato 3 pin all'Arduino: pin 1, pin 2 e pin 9.

Se non ho capito male dal tutorial, per leggere i dati devo mandare in stato LOW il pin 1 ed in stato HIGH il pin 2. A questo punto il chip carica i valori presenti sul bus dati nei registri interni. Aspettato qualche ms, rimetto a HIGH il pin 1 ed a LOW il pin 2, creando uno stato di latch che mi mantiene i valori letti. Adesso dovrei leggere i dati dai registri. Per far ciò io eseguo ShiftIn( PIN9, PIN2, VALORE) e dovrei ritrovarmi in VALORE il contenuto dei registri. Ma così pare non sia.

La mia domanda è: è corretta questa procedura? Se sì, allora significa che il mio problema è nella parte relativa alla scrittura nella SRAM.

Per chiarezza allego lo schema del circuito.
Questo sotto è il codice usato:

/* TEST DI CONNESSIONE AD 1 CHIP DI RAM DA 8 KB
TRAMITE 2 SHIFT REGISTER 595 PER LA GESTIONE DELL'INDIRIZZO,
1 SHIFT REG. 595 PER LA GESTIONE DEI DATI IN SCRITTURA SU RAM
ED 1 SHIFT REG. 165 PER I DATI IN LETTURA DALLA RAM
*/
#include <EEPROM.h>

// CONNESSIONI DEI PIN
//1° e 2° chip 595
#define data1pin 0 //pin DS
#define latch1pin 1 //pin ST_CP
#define clock1pin 2 //pin SH_CP 

//3° chip 595
#define data2pin 8 //pin DS
#define latch2pin 9 //pin ST_CP
#define clock2pin 10 //pin SH_CP

//comune a tutti e 3 i chip 595
#define master_reset 3 //pin MR/ dei 3 chip

//Chip RAM
#define ram_we 4 //pin WE/
#define ram_ce2 5 //pin CE2
#define ram_oe 6 //pin OE/
#define ram_ce1 7 //pin CE1/

//chip 165
#define clock3pin 11 //pin CP
#define set_load 12 //pin PL/
#define load_data 13 //pin Q7

//pin LED
#define pinLed 0

/* FUNZIONAMENTO DELLA RAM
PER SCRIVERE:
CE1/ -> LOW
WE/ -> LOW
CE2 -> HIGH

PER LEGGERE:
WE/ -> HIGH
CE1/ -> LOW
OE/ -> LOW
CE2 -> HIGH
*/

#define LETTURA 2 //stato della RAM: prepara per la lettura
#define SCRITTURA 1 //stato della RAM: prepara per la scrittura
#define DISATTIVA 0 //stato della RAM: disattiva

void clear_shift_registers() {
    //routine per ripulire i contenuti dei registri interni
    //degli shift register, evitando così che possano inviare
    //dati vecchi
    digitalWrite(master_reset, LOW);
    delay(50);
    digitalWrite(master_reset, HIGH);
}

void set_ram(byte stato) {
    
    switch (stato) {
        case DISATTIVA:
            digitalWrite(ram_ce1, HIGH);
            digitalWrite(ram_oe, HIGH);
            digitalWrite(ram_ce2, LOW);
            digitalWrite(ram_we, HIGH);
            break;
        case SCRITTURA:
            digitalWrite(ram_ce1, LOW);
            digitalWrite(ram_ce2, HIGH);
            digitalWrite(ram_we, LOW);
            digitalWrite(ram_oe, LOW);
            break;
        case LETTURA:
            digitalWrite(ram_ce1, LOW);
            digitalWrite(ram_ce2, HIGH);
            digitalWrite(ram_oe, LOW);
            digitalWrite(ram_we, HIGH);
            break;
    }
}

void setup() {
    //impostazione iniziale dei pin
    //
    pinMode(master_reset, OUTPUT);
    //pin degli shift register 1, 2 e 3 tutti su OUTPUT
    pinMode(latch1pin, OUTPUT);
    pinMode(clock1pin, OUTPUT);
    pinMode(data1pin, OUTPUT);
    pinMode(data2pin, OUTPUT);
    pinMode(clock2pin, OUTPUT);
    pinMode(latch2pin, OUTPUT);
    
    //pin della RAM tutti su OUTPUT
    pinMode(ram_we, OUTPUT);
    pinMode(ram_ce1, OUTPUT);
    pinMode(ram_ce2, OUTPUT);
    pinMode(ram_oe, OUTPUT);
    
    //pin dello shift reg. 165
    pinMode(clock3pin, OUTPUT);
    pinMode(set_load, OUTPUT);
    pinMode(load_data, INPUT);
    
    //LED off
    analogWrite(pinLed, 0);
    
    
    //inizializza i dispositivi
    clear_shift_registers();
    
}

void loop() {
unsigned int indirizzo;
byte valore = 0;
int eeprom_pointer = 0;

    // azzera 10 locazioni di memoria nella RAM e ci scrive una sequenza di 0-1
    for (indirizzo = 0; indirizzo <10; indirizzo++) {
        scrivi_ram(indirizzo,valore);
        valore += 3;
        EEPROM.write(eeprom_pointer, valore);
        eeprom_pointer++;
        delay(10);
    }
    delay(1000);
    
    //legge i 10 byte e li scrive in EEPROM
    for (indirizzo = 10; indirizzo < 20; indirizzo++) {
        valore = leggi_ram(indirizzo);
        EEPROM.write(eeprom_pointer, valore);
        delay(10);
    }
    delay(5000);
    //ricomincia
    
}

void scrivi_ram(unsigned int indirizzo, byte valore) {
    byte hbyte, lbyte;
    
    //scrive l'indirizzo negli shift reg. n°1 e 2
    //prepara l'indirizzo
    clear_shift_registers();
    digitalWrite(latch1pin, LOW);
    digitalWrite(latch2pin, LOW);
    hbyte = highByte(indirizzo);
    lbyte = lowByte(indirizzo);
    shiftOut(data1pin, clock1pin, MSBFIRST, hbyte);
    shiftOut(data1pin, clock1pin, MSBFIRST, lbyte);
    //prepara il valore
    shiftOut(data2pin, clock2pin, MSBFIRST, valore);
    
    //scrive nella RAM
    set_ram(SCRITTURA);
    digitalWrite(latch1pin, HIGH);
    digitalWrite(latch2pin, HIGH);
    delay(10);
    
    //disattiva tutto
    set_ram(DISATTIVA);
    digitalWrite(latch1pin, LOW);
    digitalWrite(latch2pin, LOW);
}

byte leggi_ram(unsigned int indirizzo) {
byte valore, hbyte, lbyte;
    
    //legge il contenuto della cella "indirizzo"
    //prepara l'indirizzo
    clear_shift_registers();
    digitalWrite(latch1pin, LOW);
    digitalWrite(latch2pin, LOW);
    hbyte = highByte(indirizzo);
    lbyte = lowByte(indirizzo);
    shiftOut(data1pin, clock1pin, MSBFIRST, hbyte);
    shiftOut(data1pin, clock1pin, MSBFIRST, lbyte);
    
    //prepara la RAM
    digitalWrite(latch1pin, HIGH);
    digitalWrite(latch2pin, HIGH);
    
    set_ram(LETTURA);
    digitalWrite(clock3pin, HIGH);
    digitalWrite(set_load, LOW);
    delayMicroseconds(5);
    digitalWrite(set_load, HIGH);
    set_ram(DISATTIVA);
    shiftIn(load_data, clock3pin, valore);
    digitalWrite(latch1pin, LOW);
    digitalWrite(latch2pin, LOW);
    return valore;
    
}

Ciao leo72

Quando leggi i dati del SRAM devi mettere le uscite del 595 dei dati in alta impedenza; questo si fa mettendo il pin 13 a HIGH.

Perché lo fai con un SRAM paralella? Come alternativa usa un FRAM seriale tipo FM25256B-G . La RS prende prenotazioni e lo fornisce a breve. Mi danno previsto per il 24 marzo. È un SO8 percui ti serve un adattatore a dip8.

Ciao Uwe

Uso una RAM parallela perché voglio imparare ad usarla indipendentemente dall'Arduino (ho 2 Z80 ed 1 MOS 6502 nel cassettino che non sanno cosa fare :wink: ).

Proverò mettendo le uscite in alta impedenza.
Cmq non so se il problema deriva dall'165 o dai 595 oppure dalla RAM o ancora dal mio codice, perché è la prima volta che sperimento questo tipo di dispositivi. Sul forum internazionale, sezione "Storage", trovi il circuito completo che ho postato stanotte per chiedere altri pareri.

Ciao leo72
Il Tuo problema dipende dal 595 che é collegato al D0 fino D7, sullo schema in alto a destra.
Sul Bus dei dati (D0 a D7) tutti i dispoitivi ecetto quello attivo (in scrittura il processore e in lettura il dispositivo da cui vengono letti dei dati (RAM, ROM, I/O) devono avere le uscite in alta impedenza. Se non fosse cosí hai molto probabilmente un corto su almeno un segnale perche 2 uscite hanno dei stati diversi ( uno H e l' altro L).
Per il 165 non ci sono Problemi perché hai solo entrate che colleghi al bus dati. Tuttti i dispositivi collegati su Bus devono avere solo entrate oppure uscite tri state.
Ciao Uwe

Ok. Non avevo pensato a questo problema.
Proverò.

Non risolvo nulla. Non so se è il circuito o il codice.
Il circuito l'ho ricontrollato 50 volte da ieri... sono una sessantina di cablaggi e mi si incrociano gli occhi... :*
Però non capisco a questo punto se non riesco a scrivere o non riesco a leggere, non ho un modo per verificare se la RAM riceve i dati oppure non riesce a mandarli.

EDIT:
questa qui sotto è la situazione in cui lavoro.... :cold_sweat:

Ciao leo72

Purtroppo dalla foto non riesco a controllare se hai fatto i collegamneti giusti. :wink:
puoi mettere un driver tipo ULN2803 sul bus dati e metterne 8 LED con relative resistenze. cosí se metti un indirizzo e metti i segnali per leggere i dati dovresti leggere il numero.
Questo Ti elimina errori di lettura col 165 e vedi se arriva qualcosa sul 959 dei Dati.
Un errore sugli indirizzi non é grave perché scrivi e leggi sulla stessa cella di memoria anche se non é quella che pensavi che fosse.

Ciao Uwe

Difatti stavo ragionando sulla stessa idea. Mettere dei LED per verificare almeno "ad occhio" che ci sia transito di dati....
Adesso ero sul forum internazionale con un gentilissimo utente che mi stava aiutando a semplificare il codice.
Ma nonostante le sue dritte, non riesco a venirne a capo. E senza strumenti di verifica credo che i LED siano l'unica maniera per capire se le cose sono fatte bene.