Bsera a tutti, causa prolungata permanenza in casa mi è venuta voglia dell'ennesimo progetto: un lettore ed eventualmente scrittore di eeprom.
Ho cercato un pò, ma non essendo un tecnico del settore chiedo indicazioni.
Ho sottomano una eeprom da 8kbit (1kbyte) organizzata in 64 pagine da 16 bit. Ovviamente dispongo dal datasheet delle altre informazioni costruttive... frequenze, voltaggi ecc.
Mi chiedo se sia effettivamente possibile realizzare con Arduino un dispositivo atto a leggere il contenuto della eeprom, visualizzarlo (in che forma non lo so), consentire di salvarlo in file binario ed eventualmente riscriverlo nella eeprom.
Grazie.
Tutto si senza alcun problema.
...e già abbiamo fatto il primo passo. Dove posso studiare?
Sul datasheet che solo tu hai ;D
Claudio di sto passo quando avrò capito (qualcosa) avrò i capelli bianchi.
Non sono preparato a punto tale da saper da dove iniziare, soprattutto per progetti complessi (almeno per me) come questo. Di solito parto da qualche sketch similare e studio cercando di arrivare al mio obiettivo.
Il datasheet è quello del ST 9508 che la ST indica quale sostitutivo dell'obsoleto ST 5P08C3 che è quello sotto esame. Il processo è: leggere il 5P08C3 e copiarno il contenuto da trasferire poi nel 95080.
datasheet in allegato.
ST95P08.pdf (125 KB)
Intanto lo devi collegare. Da una lettura del datasheet oltre a 3 pin SPI ti serve un pin Select e uno per disabilitare la protezione di scrittura. I pin sono nominati C (clock), D (data in), Q (data out), S (chip select) e W (wite protect). data in e data out sono da interpretare immedesimandosi nel chip, quindi data in sono dati che entrano nel chip e out sono dati uscenti.
data in è formato da codici di comando seguiti da informazioni quali indirizzo e il dato da scrivere (se il comando è di scrittura), data out sono i dati presenti nella memoria oppure registri come ad esempio STATUS REG.
I comandi sono specificati in tabella 8 (pagina 8).
Fai i collegamenti e scrivi una funzione chip select S, che normalmente deve essere H, passando a L il chip e selezionato e si può iniziare la transazione.
Stessa cosa per W, ma W= LOW tutte operazioni permesse tranne scrittura, W=HIGH tutto permesso anche scrittura.
Se te la senti la prima cosa che farei e tentare di leggere il registro di stato.
Ciao.
Questo che vedete è il codice elaborato dall'autore (diviso in due meta per capienza). Lo sto leggendo per capire qualcosa e spero di riuscire. Ho però una domanda cui non sono in grado di rispondere, almeno al momento.
Questo codice sarà applicabile a TUTTE le eeprom (che indico genericamente) o vi sono dei comandi/istruzioni da personalizzare magari per la frequenza...oppure numero/grandezza pagine e così via?
Spiego a parole mie.
Il tizio ha lavorato su una SPI e si tratta di winbond 8 pin da 1/2/4 ed 8 Mbit con determinate caratteristiche (allego datasheet).
Io devo lavorare si su una eeprom SPI ma è una 8k (1kbyte) il cui datasheet ho già allegato.
Quindi mi chiedo se nel codice vi siano istruzioni specifiche esclusive per il modello su cui si intende lavorare oppure ciò che è nel codice è in un certo modo universale.
/* Author: Arpan Das
* Date: Fri Jan 11 12:16:59 2019 +0530
* URL: https://github.com/Cyberster/SPI-Based-EEPROM-Reader-Writer */
// pin configurations
#define CS_BAR 10 // SS EEPROM pin 1
#define DO 11 // MOSI EEPROM pin 2
#define DIO 12 // MISO EEPROM pin 5
#define CLK 13 // SCK EEPROM pin 6
// opcodes for winbond W25X10A, W25X20A, W25X40A, W25X80A EEPROMs
#define WREN 0x06 // write enable
#define WRDI 0x04 // write disable
#define RDSR 0x05 // read status register
#define WRSR 0x01 // write status register
#define READ 0x03 // read from memory
#define FREAD 0x0B // fast read from memory
#define FREAD2 0x3B // fast read dual output from memory
#define WRITE 0x02 // wribeginTransactionte to memory
#define BERASE 0xD8 // block erase (64KB)
#define SERASE 0x20 // sector erase (4KB)
#define CERASE 0xC7 // chip erase (0xC7/0x60)
#define PWRDWN 0xB9 // power down
#define RELPWR 0xAB // block erase (64KB)
#define INFO 0x90 // get manufacturer & device ID info
#define JEDEC 0x9F // get JEDDEC ID
byte clr;
char spi_transfer(volatile char data) {
SPDR = data; // Start the transmission
// https://www.avrfreaks.net/forum/how-does-while-spsr-1
while (!(SPSR & (1 << SPIF))) {}; // Wait the end of the transmission
return SPDR; // return the received byte
}
void setup() {
// Initialize serial and wait for port to open:
// 1000000 working for upload, not working for download
// 115200 working best for both upload and download
Serial.begin(115200);
// wait for serial port to connect. Needed for native USB port only
while (!Serial);
pinMode(DO, OUTPUT);
pinMode(DIO, INPUT);
pinMode(CLK, OUTPUT);
pinMode(CS_BAR, OUTPUT);
digitalWrite(CS_BAR, HIGH); // disable device
// SPCR = 01010000
//interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
//sample on leading edge of clk,system clock/4 rate (fastest)
SPCR = (1 << SPE) | (1 << MSTR);
clr = SPSR;
clr = SPDR;
delay(10);
byte data = read_eeprom(0x0000FF); // 0x000000 to 0x100000
Serial.println(data, HEX);
// // read data, block_size columns (bytes) in a row, block_count rows
// read_block(0x000000, 16, 10, true);
// // download entier rom into a file
// download_rom(true);
// // write data to the EEPROM
// byte buffer[256];
// for (int i = 0; i < 256; i++) {
// buffer[i] = i; // filling buffer with 0-255
// }
// buffer size must be 1 to 256
// EEPROM can only be written if empty i.e. filled with 1's
// write_eeprom(0x000000, buffer, 256);
// // erase 4kB from given address
// sector_erase(0x000000);
// // erase 64kB from given address
// block_erase(0x000000);
// // erase the entier EEPROM chip
// chip_erase();
// // write data to eeprom
// // fill buffer with data
// byte buffer[256];
// for (int I = 0; I < 256; I++) {
// buffer[I] = I;
// }
// write_eeprom(0x00010E, buffer, 256);
// // upload data from file to the EEPROM
// upload_rom();
// // read manufacturer id and device id
// byte manufacturer_id;
// byte device_id;
// get_device_info(manufacturer_id, device_id);
// Serial.println(manufacturer_id, HEX);
// Serial.println(device_id, HEX);
}
// read data from EEPROM
byte read_eeprom(long EEPROM_address) {
byte data;
digitalWrite(CS_BAR, LOW); // Write function
spi_transfer(READ); //transmit read opcode
spi_transfer((byte)((EEPROM_address >> 16) & 0x0000FF)); //send b2 address first
spi_transfer((byte)((EEPROM_address >> 8) & 0x0000FF)); //send b1 address
spi_transfer((byte)((EEPROM_address) & 0x0000FF)); //send b0 address last
data = spi_transfer(0xFF); //get data byte
digitalWrite(CS_BAR, HIGH); //release chip, signal end transfer
return data;
}
// read manufacturer id and device id
void get_device_info(byte &manufacturer_id, byte &device_id) {
// read manufacturer id and device id
digitalWrite(CS_BAR, LOW);
spi_transfer(INFO);
spi_transfer(0x00);
spi_transfer(0x00);
spi_transfer(0x00);
manufacturer_id = spi_transfer(0xFF); //get data byte
device_id = spi_transfer(0xFF); //get data byte
digitalWrite(CS_BAR, HIGH);
delay(10);
}
void read_block(long starting_address, int block_size, int block_count, boolean fastread) {
// read data, block_size columns (bytes) in a row, block_count rows
for (long i = starting_address; i < starting_address + (block_size * block_count); i += block_size) {
digitalWrite(CS_BAR, LOW);
if (fastread)
spi_transfer(FREAD);
else
spi_transfer(READ);
spi_transfer((byte)((i >> 16) & 0x0000FF));
spi_transfer((byte)((i >> 8) & 0x0000FF));
spi_transfer((byte)((i) & 0x0000FF));
if (fastread)
spi_transfer(0xFF); // adding dummy clock for fast read
byte data[block_size];
char buf[block_size * 4 + block_size + 8];
int length = 0;
length += sprintf(buf + length, "%06lX\t ", i);
seconda metà
for (int j = 0; j < block_size; j++) {
data[j] = spi_transfer(0xFF);
length += sprintf(buf + length, " %02X", data[j]);
}
length += sprintf(buf + length, "\t ");
for (int j = 0; j < block_size; j++) {
if (data[j] >= 32 && data[j] <= 127)
length += sprintf(buf + length, "%c", (char)data[j]);
else
length += sprintf(buf + length, ".");
}
digitalWrite(CS_BAR, HIGH);
Serial.println(buf);
}
}
void download_rom(boolean fastread) {
while (!Serial.available()) {}
while (Serial.read() != 'd'); // waiting for handshaking
// reading EEPROM 256 byte at a time for reliability
for (long i = 0x000000; i <= 0xFF0000; i += 256) {
Serial.write('W'); // response 1 byte of data write request
while (Serial.read() != 'G'); // wait for computer grant write request
// read EEPROM
digitalWrite(CS_BAR, LOW);
if (fastread)
spi_transfer(FREAD);
else
spi_transfer(READ);
spi_transfer((byte)((i >> 16) & 0x0000FF));
spi_transfer((byte)((i >> 8) & 0x0000FF));
spi_transfer((byte)((i) & 0x0000FF));
if (fastread)
spi_transfer(0xFF); // adding dummy clock for fast read
for (int j = 0; j < 256; j++) {
byte data = spi_transfer(0xFF);
Serial.write(data);
}
digitalWrite(CS_BAR, HIGH);
delayMicroseconds(1000);
}
Serial.println("ROM downloaded successfully.");
}
// erase 4kB from given address
void sector_erase(long address) {
digitalWrite(CS_BAR, LOW);
spi_transfer(WREN); //write enable
digitalWrite(CS_BAR, HIGH);
digitalWrite(CS_BAR, LOW);
spi_transfer(SERASE);
spi_transfer((byte) (address >> 16)); //send b2 address first
spi_transfer((byte) (address >> 8)); //send b1 address
spi_transfer((byte) address); //send b0 address last
digitalWrite(CS_BAR, HIGH);
delay(250); // tBE = 120-250ms
digitalWrite(CS_BAR, LOW);
spi_transfer(WRDI); //write disable
digitalWrite(CS_BAR, HIGH);
Serial.println("Operation SECTOR ERASE has been executed successfully.");
}
// erase 64kB from given address
void block_erase(long address) {
digitalWrite(CS_BAR, LOW);
spi_transfer(WREN); //write enable
digitalWrite(CS_BAR, HIGH);
digitalWrite(CS_BAR, LOW);
spi_transfer(BERASE);
spi_transfer((byte) (address >> 16)); //send b2 address first
spi_transfer((byte) (address >> 8)); //send b1 address
spi_transfer((byte) address); //send b0 address last
digitalWrite(CS_BAR, HIGH);
delay(1000); // tBE = 0.4-1s
digitalWrite(CS_BAR, LOW);
spi_transfer(WRDI); //write disable
digitalWrite(CS_BAR, HIGH);
Serial.println("Operation BLOCK ERASE has been executed successfully.");
}
// erase the entire EEPROM chip
void chip_erase() {
digitalWrite(CS_BAR, LOW);
spi_transfer(WREN); //write enable
digitalWrite(CS_BAR, HIGH);
digitalWrite(CS_BAR, LOW);
spi_transfer(CERASE);
digitalWrite(CS_BAR, HIGH);
delay(10000); // tCE = 6-10s for W25X80A in our case.
digitalWrite(CS_BAR, LOW);
spi_transfer(WRDI); //write disable
digitalWrite(CS_BAR, HIGH);
Serial.println("Operation CHIP ERASE has been executed successfully.");
}
// write data to the EEPROM
// max buffer size is 256
void write_eeprom(long address, byte data[], int data_size) {
digitalWrite(CS_BAR, LOW);
spi_transfer(WREN); //write enable
digitalWrite(CS_BAR, HIGH);
delayMicroseconds(5);
digitalWrite(CS_BAR, LOW);
spi_transfer(WRITE); //write instruction
spi_transfer((byte)((address >> 16) & 0x0000FF)); // send b2 address first
spi_transfer((byte)((address >> 8) & 0x0000FF)); // send b1 address
// send b0 address:
// If an entire 256 byte page is to be programmed, the last address
// byte (the 8 least significant address bits) should be set to 0.
if (data_size == 256)
spi_transfer(0x00); // as 0xFF
else
spi_transfer((byte)((address) & 0x0000FF)); // as it is
for (int i = 0; i < data_size; i++) {
spi_transfer(data[i]); //write data byte
}
digitalWrite(CS_BAR, HIGH); //release chip
//wait for eeprom to finish writing
delayMicroseconds(1500); // tpp = 1.5-3ms
digitalWrite(CS_BAR, LOW);
spi_transfer(WRDI); //write disable
digitalWrite(CS_BAR, HIGH);
}
// upload data from file to the EEPROM
void upload_rom() {
while (!Serial.available()) {}
while (Serial.read() != 'H'); // wait for handshake request from cmoputer
byte buff[256];
// 1 page at a time where page size = 256 byte
for (long address = 0; address <= 0x0FFFFF; address += 256) { //0x0FFFFF
Serial.write('R'); // requests 256 bytes of data
while (!Serial.available()); // wait for computer
Serial.readBytes(buff, 256);
write_eeprom(address, buff, 256);
}
// while (Serial.available()) {
// byte data = (byte)Serial.read();
// Serial.readBytes(buff, 256);
//
// buff[i++] = data;
// if (i == 256) {
// write_eeprom(address, buff, 256);
// address += 256;
// i = 0;
// }
// }
Serial.println("ROM uploaded successfully.");
}
void loop() {}
vince59:
Claudio di sto passo quando avrò capito (qualcosa) avrò i capelli bianchi.
E figurati noi senza neanche sapere a quale chip ti riferivi
Quindi mi chiedo se nel codice vi siano istruzioni specifiche esclusive per il modello su cui si intende lavorare oppure ciò che è nel codice è in un certo modo universale.
La logica di principio su come affrontare il problema è la stessa, ci saranno sempre byte e pagine, ma ogni chip potrebbe avere delle differenze, sui codici di accesso, sulla grandezza delle pagine, sui tempi di scrittura e modalità di verifica, sul modo di protezione dalla sovrascrittura. Questi sono appunto dettagli specifici da trovare sul datasheet. Quindi c'è un aspetto che riguarda strettamente l'hardware, i collegamenti, il protocollo SPI (e qui le differenze dovrebbero essere minime o nulle), e un altro che riguarda i dati/codici che la memoria vuole (o fornisce).
A un primo sguardo al codice mi sembra che usi la periferica SPI hardware agendo direttamente sui registri del processore, è sicuramente la comunicazione più veloce, ma forse potrebbe vincolare ad uno specifico micro, che dal codice non si capisce qual è. Poi ci sono tutti i codici di controllo della memoria associati a nomi di comodo (SERASE CERASE ecc), che potrebbero variare da un modello all'altro.
A margine, per fare strettamente quello che ti serve potrebbe bastare molto meno di tutto quel codice.
Grazie Claudio. Non so se a questo punto sia possibile modificare ed utilizzare lo sketch che ho trovato.
Realizzarlo ex novo è assolutamente al di fuori delle mia conoscenze. Tu che mi consigli?
Cmq...il chip utilizzato dall'autore è un winbond di cui allego il datasheet.
Al progetto sono acclusi due file in python che devono essere lanciati da cmd a seconda se si vuol leggere o scrivere.
Sto cercando di orientarmi nello sketch e nei due file python e cerco di capire ...non dico che è arabo ma sicuramente da quelle parti.
Mi soffermo su quei dati numerici che secondo me sono riferimenti alla grandezza della memoria del chip ed alle locazioni.
W25X80A_Winbond.pdf (1.41 MB)
Io consiglierei di capire i passaggi base come suggerito da Maurotec, altrimenti ci si perde in un codice scritto da altri e le cose incomprensibili sono due invece che una.
Partiamo con il collegare.
Dopo di che per leggere uno o più byte va realizzata la sequenza di figura 8 pagina 9 (datasheet post #5), sono tre uscite da comandare e un ingresso da leggere.
Instruction è il comando READ della tabella 8 pagina 8.
Se si vuole leggere la memoria partendo dalla prima cella, tutti i bit dell'indirizzo (A9:A0) vanno a zero.
Come spiegato nella sezione ReadOperation di pagina 8, o in SerialClock di pagina 2, i bit trasmessi alla memoria sul filo D vengono incamerati sul fronte di salita del clock (filo C), mentre i bit emessi dalla memoria sul filo Q cambiano sul fronte di discesa del clock, e tutti i byte sono trasmessi con il bit più significativo per primo (MSB first).
Si può partire con il crearsi qualche costante, configurare i pin scelti come ingressi e uscite, impostare i livelli di riposo (LOW per ST95_C e D, HIGH per ST95_S).
#define ST95_Q ...
#define ST95_D ...
#define ST95_C ...
#define ST95_S ...
#define ST95_READ 0b00000011;
A questo punto sono da scrivere due funzioncine piccole piccole che si occupano solo dell'invio e della ricezione di un singolo byte verso/da la memoria (nota: queste due funzioncine non si devono occupare di "cosa" trasmettere, ma solo di realizzare il protocollo SPI a basso livello per lo spostamento avanti e indietro di un generico byte attraverso i fili D Q, con l'uso del clock C, e in questo senso rappresentano la base comune per comunicare con ogni dispositivo SPI).
Argomenti da studiare: rappresentazione binaria di un byte, scorrimento bit in una variabile intera, operatori bitwise in genere (<< >> | &
).
Buongiorno, prima di tutto grazie per l'attenzione prestata.
Ci provo...e vado a studiare!
Purtroppo avendo preparazione di base molto diversa ed essendo uno "smanettone" avanzato porrò domande stupide. Pazientate!
PS: una curiosità, sempre per cercare di comprendere. Non se se tu abbia dato un occhiata allo sketch del tizio. Da quanto visto, mi sembra che lo abbia strutturato includendo nello sketch delle funzioni da attivare alla bisogna (rimuovendo gli slash).
Poi ho aperto gli script (?)/piccoli programmi python mi chiedo a livello di funzionamento del programma. Perchè questi prorammini devono essere fatti girare da cmd?...che senso ha nello logica dello sketch?
Grazie ancora
Gli script a dire il vero non li ho trovati.
L'uso della riga di comando è solo per semplicità.
...stavo studiando (cercando di studiare qualcosa) e rispondere.
Troppo complicato per me. Mi mancano gli specifici studi e quindi la conseguente preparazione di base per andare avanti. Non posso cercare di "azzeccare".
Quindi credo che cercherò di "capire" lo sketch trovato, a furia di scorrerlo e leggere i datasheet comincio a vedere la luce (ad esempio i set di comandi che sono specifici per il chip e quindi vanno cambiati e non sono tutti applicabili al mio chip) a meno di partire da uno sketch base che qualche esperto potrebbe buttare giù.
Allego gli script. (era rar ma ho dovuto cambiare estensione)
Grazie.
PS: per esempio non comprendo questo che trovo tra il set di istruzioni:
Istruzione Descrizione Formato Istruzione
WREN Set Write Enable Latch 000X X110 (che numero è questo?)
Le note dicono questo X = Don't care (non importa)
EEPROM-Reader-Writer-master.zip (1.48 KB)
ad esempio i set di comandi che sono specifici per il chip e quindi vanno cambiati e non sono tutti applicabili al mio chip
No, infatti, il tuo chip prevede solo i sei "comandi" della tabella 8 pagina 8 (e le rappresentazioni grafiche delle sequenze di ciascuno sono riportate nelle pagine successive).
WREN Set Write Enable Latch 000X X110 (che numero è questo?)
Vuol dire che per dare quel comando si invia quella sequenza di bit, dove X indica indifferente 0 o 1. Quindi si può definire un nome di comodo: #define ST95_WREN 0b00000110
Un esempio per leggere una cella di indirizzo 'addr' compreso tra 0 e 1023 potrebbe essere questo:
void leggiCella(int addr) // 1 byte Read Operation Sequence, fig.8 pag.9
{
digitalWrite(ST95_S, LOW);
byte a9a8 = (highByte(addr) << 3) & 0b00011000;
txByte(ST95_READ | a9a8);
txByte(lowByte(addr));
n = rxByte();
digitalWrite(ST95_S, HIGH);
return n;
}
Le operazioni bitwise servono per portare i bit A9:A8 dell'indirizzo dentro i bit 4:3 dell'istruzione da inviare come primo byte:
'leggiCella' si appoggia alle due funzioncine comuni che dicevo in precedenza:
void txByte(byte n)
{
for (byte i=0; i<8; i++)
{
digitalWrite(SR95_D, n & 0b10000000);
digitalWrite(SR95_C, HIGH);
digitalWrite(SR95_C, LOW);
n <<= 1;
}
}
byte rxByte()
{
byte n = 0;
for (byte i=0; i<8; i++)
{
byte n = (n << 1) | digitalRead(SR95_Q);
digitalWrite(SR95_C, HIGH);
digitalWrite(SR95_C, LOW);
}
return n;
}
Bgiorno e grazie, si dissipa la nebbia. Molto interessante. I tuoi esempi e chiarimenti sono di grande aiuto. Devo però ora metabolizzare alcuni concetti tra cui la struttura della memoria epprom che è ancora un pò vaga. Espongo alcune osservazioni.
Chiaro che gli indirizzi sono definiti da valori consecutivi. Ora, la memoria di cui parlo è una 8kbit (1Kbyte) con pagine (64) da 16 byte. Domanda: questa suddivisone in pagine, ancora un pò fumosa per me, impone vincoli software? ...ad esempio il software deve sapere sta cosa?
Probabilmente ci sono delle informazioni nel datasheet non essenziali per lo sketch su cui non vorrei andare a sbattere la testa, fermo restando il loro significato dal punto di vista tecnico.
Tu fai l'esempio di lettura di una cella e credo averlo compreso. In pratica si vanno a prendere quei valori e si appoggiano da un altra parte. Ovviamente io devo leggere tutte le celle...giusto?
Bene na volta che le ho lette dove appoggio la lettura?...in un file...nell'output a serial monitor?...da qui discende poi il discorso scrittura.
Un ulteriore domanda sulla parte HW. Il tizio nel suo esempio (che allego) aveva utlizzato dei partitori di tensione per abbassare i voltaggi da 5 a 3v. Dal datasheet del mio chip vedo che può lavorare tra 3 e 5.5 quindi ritengo che il tuo schema non necessiti di altro rispetto a quanto da te indicato.
Grazie.
vince59:
questa suddivisone in pagine, ancora un pò fumosa per me, impone vincoli software?
In lettura nessuna, l'organizzazione interna non interessa.
In scrittura conta solo se si vuole scrivere più di un byte alla volta, allora il blocco può essere lungo al massimo 16 byte e non deve sconfinare nella pagina successiva (Info a pagina 9: Page Write Operation).
Se si vuole scrivere un intero file nella memoria a partire dalla prima cella, si scrivono 16 byte a partire dall'indirizzo 0, poi altri 16 a partire dal 16 ecc.
Bene na volta che le ho lette dove appoggio la lettura?...in un file...nell'output a serial monitor?...da qui discende poi il discorso scrittura.
Dei byte letti ne fai quello che vuoi. La domanda è cosa vuoi farne? Ci stanno anche tutti in un array di 1024 elementi. Se si vuole ottenere un file andranno trasmessi sulla seriale così come sono (con write) e ricevuti sul PC (il come dipende dall'interazione tra sketch Arduino e programma/script su PC). Se invece vuoi visualizzare i byte sul monitor seriale, si trasmettono le stringhe dei loro valori (con print), rappresentandoli in binario, decimale o esadecimale come si preferisce.
Dal datasheet del mio chip vedo che può lavorare tra 3 e 5.5 quindi ritengo che il tuo schema non necessiti di altro rispetto a quanto da te indicato.
Suppongo non serva altro, anche le resistenze sono più per scrupolo.
Allego gli script. (era rar ma ho dovuto cambiare estensione)
Anche gli script (sono scritti in Python 2.x che è fuori supporto dal primo gennaio) si possono ridurre al minimo essenziale. Se si vuole solo fare il dump della memoria, allora basta un programma che apra la seriale, attenda magari un paio di secondi l'eventuale autoreset di Arduino, invii un byte di "pronto a ricevere" ad Arduino e riceva 1024 byte salvandoli su un file.
import serial, time
ser = serial.Serial(r"...nomeporta...", 115200, 8, 'N', 1, timeout=1)
time.sleep(2) ## attesa autoreset Arduino
ser.write(b'H') ## invio pronto a ricevere
dati = bytearray() ## buffer di ricezione
while True: ## ciclo senza fine, eventualm.uscire CTRL+C
if ser.inWaiting():
dati.append(ser.read(1))
if len(dati) == 1024: break
open(r"...nomefile...", "wb").write(dati)
Lato sketch si può attendere sulla seriale il "pronto" dal PC, supponiamo il carattere 'H', e iniziare a leggere tutte le celle trasmettendo i byte ottenuti.
if (Serial.available() && (Serial.read() == 'H'))
{
for (int addr=0; addr<1024; addr++)
{
Serial.write(leggiCella(addr));
}
}
Non è il modo più veloce, leggendo la memoria a blocchi ci si metterebbe meno tempo, ma anche usando questo metodo la lettura e trasmissione dei valori di tutte le 1024 celle impiega appena 0,38 secondi (ho calcolato 5µs ogni digitalRead o Write, e una velocità seriale di 115200bit/s).
Grazie per la pazienza e le precise e chiare risposte. UN mondo tutto nuovo per me.
Come mai nei comandi disponibili per il 95P08 non vi è il comando ERASE...si riscrive direttamente?...o magari si scrivono zeri o altro ?
vince59:
Come mai nei comandi disponibili per il 95P08 non vi è il comando ERASE...si riscrive direttamente?...o magari si scrivono zeri o altro ?
Uh, non so. Queste memorie quando sono cancellate contengono tutti 1. Se non c'è un erase esplicito potrebbe fare un autoerase (forse dell'intera pagina?) e una riscrittura.
Grazie Claudio....come vedi sto studiando ;D
Dimenticavo la parte seria della risposta.
I dati letti mi servono per un backup che una volta fatto sarà solo scritto più volte su chip diversi.
Mi piace la tua idea dell'inserire nello sketch le istruzioni per il "salvataggio" del dump in un file.
Allora, io ora, intanto con qualche idea più chiara, provo a smanettare sullo sketch originario provando a togliere tutto ciò di cui non ho bisogno ed integrare con i tuoi suggerimenti. Vediamo che succede.