- Messaggi: 43
- Ringraziamenti ricevuti 0
Memoria Flash di un pic12F617 per memorizzare (ESEMPI cercasi disperatamente)
9 Anni 5 Mesi fa - 9 Anni 5 Mesi fa #6
da Elby
Risposta da Elby al topic Memoria Flash di un pic12F617 per memorizzare (ESEMPI cercasi disperatamente)
Intanto grazie 1000 per il codice. non riesco tuttavia a capire la dinamica della scrittura perchè sembra quasi che se ho i miei 14 bit da memorizzare nei registri PMDATH e PMDATL che magari sono all'indirizzo 0200h (quindi PMADRH a 01h e PMADRL a 00h...credo!), devo memorizzare con dati vuoti anche i tre indirizzi successivi.
Queste sono le due parti di codice scritte fino ad ora prendendo spunto da programmi trovati in rete:
PER LA LETTURA:
unsigned int read_flash (int adrs_hi, int adrs_lo)
{PMADRL=adrs_lo; //imposta il registro degli indirizzi memoria basso al dato address low
PMADRH=adrs_hi; //imposta il registro degli indirizzi memoria alto al dato address hight
PMCON1bits.RD=1; //inizializza la lettura della memoria
NOP();
NOP();
int adrs_hi_value =PMDATH; //immetti il dato contenuto nel registro dati memoria alto nella variabile address hight value
int adrs_lo_value =PMDATL; //immetti il dato contenuto nel registro dati memoria basso nella variabile address low value
adrs_lo_value=bin2dec(adrs_lo_value);
return adrs_lo_value; //restituisci il valore dell'address low value
return adrs_hi_value; // MA LE FUNZIONI POSSONO SOLO RESTITUIRE UN DATO !!!!
}
A questo punto le domande su questa parte sono:
1) se devo leggere un dato memorizzato nell'allocazione 0200h, dovrò richiamare la funzione di lettura come:
read_flash (0x02 , 0x00) ;
2) dato che vado a leggere sia il registro PMDATH che PMDATL, come faccio a farmi restituire un solo dato in uscita dalla funzione?
3) il dato in uscita sarà binario, esiste un modo per farlo restituire in decimale dato che è quello che mi interessa (devo memorizzare o leggere un numero intero di ciclo del timer per gestire dei tempi) ?
PER LA SCRITTURA:
void write_flash(char address, int data0,int data1, int data2,int data3){
unsigned char contscr=0; //this variable is a counter
unsigned int vector[4]; //vector storage of data
vector[0]=data0; //load data0 in vector
vector[1]=data1; //load data0 in vector
vector[2]=data2; //load data0 in vector
vector[3]=data3; //load data0 in vector
while(contscr<4){
PMADRL=address+contscr; //Load initial data address
PMADRH=0x00; //Load initial data address
PMDATH=(char)(vector[contscr]>>; //Load second data byte into upper
PMDATL=(char)vector[contscr]&(0x00FF); //Load first data byte into lower
PMCON1bits.WREN=1; //enabling the write
PMCON2=0x55; //required write sequence
PMCON2=0xAA; //required write sequence
PMCON1bits.WR=1; //begin write
asm("NOP"); //Required to transfer data to the buffer
asm("NOP"); //registers
contscr++; //Increment address
PMCON1bits.WREN=0; //disabling the write
}
contscr=0; //erase the counter
}
Questa parte l'ho copiata pari pari ma non ho capito nulla dello spirito con cui è stata scritta dato che l'indirizzo PMADRH resta sempre a 0x00h
Queste sono le due parti di codice scritte fino ad ora prendendo spunto da programmi trovati in rete:
PER LA LETTURA:
unsigned int read_flash (int adrs_hi, int adrs_lo)
{PMADRL=adrs_lo; //imposta il registro degli indirizzi memoria basso al dato address low
PMADRH=adrs_hi; //imposta il registro degli indirizzi memoria alto al dato address hight
PMCON1bits.RD=1; //inizializza la lettura della memoria
NOP();
NOP();
int adrs_hi_value =PMDATH; //immetti il dato contenuto nel registro dati memoria alto nella variabile address hight value
int adrs_lo_value =PMDATL; //immetti il dato contenuto nel registro dati memoria basso nella variabile address low value
adrs_lo_value=bin2dec(adrs_lo_value);
return adrs_lo_value; //restituisci il valore dell'address low value
return adrs_hi_value; // MA LE FUNZIONI POSSONO SOLO RESTITUIRE UN DATO !!!!
}
A questo punto le domande su questa parte sono:
1) se devo leggere un dato memorizzato nell'allocazione 0200h, dovrò richiamare la funzione di lettura come:
read_flash (0x02 , 0x00) ;
2) dato che vado a leggere sia il registro PMDATH che PMDATL, come faccio a farmi restituire un solo dato in uscita dalla funzione?
3) il dato in uscita sarà binario, esiste un modo per farlo restituire in decimale dato che è quello che mi interessa (devo memorizzare o leggere un numero intero di ciclo del timer per gestire dei tempi) ?
PER LA SCRITTURA:
void write_flash(char address, int data0,int data1, int data2,int data3){
unsigned char contscr=0; //this variable is a counter
unsigned int vector[4]; //vector storage of data
vector[0]=data0; //load data0 in vector
vector[1]=data1; //load data0 in vector
vector[2]=data2; //load data0 in vector
vector[3]=data3; //load data0 in vector
while(contscr<4){
PMADRL=address+contscr; //Load initial data address
PMADRH=0x00; //Load initial data address
PMDATH=(char)(vector[contscr]>>; //Load second data byte into upper
PMDATL=(char)vector[contscr]&(0x00FF); //Load first data byte into lower
PMCON1bits.WREN=1; //enabling the write
PMCON2=0x55; //required write sequence
PMCON2=0xAA; //required write sequence
PMCON1bits.WR=1; //begin write
asm("NOP"); //Required to transfer data to the buffer
asm("NOP"); //registers
contscr++; //Increment address
PMCON1bits.WREN=0; //disabling the write
}
contscr=0; //erase the counter
}
Questa parte l'ho copiata pari pari ma non ho capito nulla dello spirito con cui è stata scritta dato che l'indirizzo PMADRH resta sempre a 0x00h
Ultima Modifica 9 Anni 5 Mesi fa da Elby.
Si prega Accedi o Crea un account a partecipare alla conversazione.
- Elby
- Autore della discussione
- Senior Member
Riduci
Di più
9 Anni 5 Mesi fa #7
da Pascolo
Risposta da Pascolo al topic Memoria Flash di un pic12F617 per memorizzare (ESEMPI cercasi disperatamente)
qui forse trovi la risposta ad alcune domande
www.settorezero.com/wordpress/gli-operat...o-in-c-per-picmicro/
www.settorezero.com/wordpress/gli-operat...o-in-c-per-picmicro/
Si prega Accedi o Crea un account a partecipare alla conversazione.
- Pascolo
- Junior Member
Riduci
Di più
- Messaggi: 22
- Ringraziamenti ricevuti 6
9 Anni 5 Mesi fa #8
da Elby
Risposta da Elby al topic Memoria Flash di un pic12F617 per memorizzare (ESEMPI cercasi disperatamente)
Effettivamente a quel link ho trovato molte risposte...e devo dire che mi serviva proprio
Da uno studio del codice per il 1572 mi sono reso conto che i due pic hanno un funzionamento differente.
Il 1572 infatti pare necessiti della cancellazione da parte del programma mentre il 617 automaticamente cancella l'intero blocco da 16 indirizzi appena avviene la scrittura. Dal datasheet del 617 mi sono poi reso conto che in pratica la scrittura andrebbe fatta per un blocco di 4 parole e quindi di 16 indirizzi in totale ed è d'obbligo che il primo degli indirizzi (del blocco da cancellare e riscrivere) del registro PMDATL finiscano per 00.
Detto questo quindi vuol dire che se per esempio devo stoccare quattro dati differenti, ciascuno in un blocco di memoria separato dall'altro, dovrò utilizzare 16 indirizzi per dato da memorizzare (due registrati dal dato stesso nei registri PMDATH:PMDATL e gli altri 12 vuoti). Quindi per esempio potrei utilizzare i registri da 0x200h in poi per stoccare dati flash e le 4 word sarebbero collocate come:
DATO 1: in 0x0200h
PMADRH=02;PMADRL=00
PMDATH=world1 >> 8 PMDATL=world1 && (0x00FF)
ed in successione quelli vuoti
PMADRH=02;PMADRL=01
PMDATH=00 PMDATL=00
PMADRH=02;PMADRL=02
PMDATH=00 PMDATL=00
PMADRH=02;PMADRL=03
PMDATH=00 PMDATL=00
DATO 2: in 0300h
PMADRH=03;PMADRL=00
PMDATH=world2 >> 8 PMDATL=world2 && (0x00FF)
ed in successione quelli vuoti
PMADRH=03;PMADRL=01
PMDATH=00 PMDATL=00
PMADRH=03;PMADRL=02
PMDATH=00 PMDATL=00
PMADRH=03;PMADRL=03
PMDATH=00 PMDATL=00
e così per word2 in 0x0400h e word3 in 0x500h
In questo modo pur predendo celle di memoria non devo memorizzare in un array i dati presenti nelle 12 allocazioni del blocco da scrivere.
Se i presupposti fino ad ora sono corretti, il codice dovrebbe essere questo:
void FLASH_WriteWord(unsigned int flashAddr, unsigned int word)
{unsigned int GIEBitValue = INTCONbits.GIE; // salva la condizione degli interrupt generali
INTCONbits.GIE = 0; // disabilita gli interrupt
unsigned char conteggio_parole=0;
unsigned int vettore[4];
vettore[0]=word;
vettore[1]=0x0000; //vuoto
vettore[2]=0x0000; //vuoto
vettore[4]=0x0000; //vuoto
PMCON1bits.WREN = 1; // abilita la scrittura
while (conteggio_parole<4)
{PMADRL = (flashAddr & 0xFF);
PMADRH = ((flashAddr & 0xFF00) >> ;
PMDATL = vettore[conteggio_parole];
PMDATH = ((vettore[conteggio_parole] & 0xFF00) >> ;
PMCON2 = 0x55;
PMCON2 = 0xAA;
PMCON1bits.WR = 1; //scrivi il dato
NOP();
NOP();
conteggio_parole++;
}
PMCON1bits.WREN = 0; // disabilita la scrittura
INTCONbits.GIE = GIEBitValue; // ripristina la condizione degli interrupt
}
Da uno studio del codice per il 1572 mi sono reso conto che i due pic hanno un funzionamento differente.
Il 1572 infatti pare necessiti della cancellazione da parte del programma mentre il 617 automaticamente cancella l'intero blocco da 16 indirizzi appena avviene la scrittura. Dal datasheet del 617 mi sono poi reso conto che in pratica la scrittura andrebbe fatta per un blocco di 4 parole e quindi di 16 indirizzi in totale ed è d'obbligo che il primo degli indirizzi (del blocco da cancellare e riscrivere) del registro PMDATL finiscano per 00.
Detto questo quindi vuol dire che se per esempio devo stoccare quattro dati differenti, ciascuno in un blocco di memoria separato dall'altro, dovrò utilizzare 16 indirizzi per dato da memorizzare (due registrati dal dato stesso nei registri PMDATH:PMDATL e gli altri 12 vuoti). Quindi per esempio potrei utilizzare i registri da 0x200h in poi per stoccare dati flash e le 4 word sarebbero collocate come:
DATO 1: in 0x0200h
PMADRH=02;PMADRL=00
PMDATH=world1 >> 8 PMDATL=world1 && (0x00FF)
ed in successione quelli vuoti
PMADRH=02;PMADRL=01
PMDATH=00 PMDATL=00
PMADRH=02;PMADRL=02
PMDATH=00 PMDATL=00
PMADRH=02;PMADRL=03
PMDATH=00 PMDATL=00
DATO 2: in 0300h
PMADRH=03;PMADRL=00
PMDATH=world2 >> 8 PMDATL=world2 && (0x00FF)
ed in successione quelli vuoti
PMADRH=03;PMADRL=01
PMDATH=00 PMDATL=00
PMADRH=03;PMADRL=02
PMDATH=00 PMDATL=00
PMADRH=03;PMADRL=03
PMDATH=00 PMDATL=00
e così per word2 in 0x0400h e word3 in 0x500h
In questo modo pur predendo celle di memoria non devo memorizzare in un array i dati presenti nelle 12 allocazioni del blocco da scrivere.
Se i presupposti fino ad ora sono corretti, il codice dovrebbe essere questo:
void FLASH_WriteWord(unsigned int flashAddr, unsigned int word)
{unsigned int GIEBitValue = INTCONbits.GIE; // salva la condizione degli interrupt generali
INTCONbits.GIE = 0; // disabilita gli interrupt
unsigned char conteggio_parole=0;
unsigned int vettore[4];
vettore[0]=word;
vettore[1]=0x0000; //vuoto
vettore[2]=0x0000; //vuoto
vettore[4]=0x0000; //vuoto
PMCON1bits.WREN = 1; // abilita la scrittura
while (conteggio_parole<4)
{PMADRL = (flashAddr & 0xFF);
PMADRH = ((flashAddr & 0xFF00) >> ;
PMDATL = vettore[conteggio_parole];
PMDATH = ((vettore[conteggio_parole] & 0xFF00) >> ;
PMCON2 = 0x55;
PMCON2 = 0xAA;
PMCON1bits.WR = 1; //scrivi il dato
NOP();
NOP();
conteggio_parole++;
}
PMCON1bits.WREN = 0; // disabilita la scrittura
INTCONbits.GIE = GIEBitValue; // ripristina la condizione degli interrupt
}
Si prega Accedi o Crea un account a partecipare alla conversazione.
- Elby
- Autore della discussione
- Senior Member
Riduci
Di più
- Messaggi: 43
- Ringraziamenti ricevuti 0
9 Anni 5 Mesi fa #9
da Pascolo
Risposta da Pascolo al topic Memoria Flash di un pic12F617 per memorizzare (ESEMPI cercasi disperatamente)
Mi sembra strano che il 617 cancelli automaticamente, comunque non ti resta che provare.
Si prega Accedi o Crea un account a partecipare alla conversazione.
- Pascolo
- Junior Member
Riduci
Di più
- Messaggi: 22
- Ringraziamenti ricevuti 6
9 Anni 5 Mesi fa #10
da Elby
Risposta da Elby al topic Memoria Flash di un pic12F617 per memorizzare (ESEMPI cercasi disperatamente)
Dopo giorni di prove e tentativi ancora non sono riuscito ad accedere alla memoria flash. In lettura non dovrei avere problemi con la funzione:
unsigned int FLASH_ReadWord(unsigned int flashAddr)
{unsigned char GIEbitsValue=INTCONbits.GIE; //salva la condizione degli interrupt generali
INTCONbits.GIE=0; //disabilita gli interrupt generali
PMADRL= (flashAddr && 0x00FF) ; // estrai il blocco indirizzo basso
PMADRH= ((flashAddr & 0xFF00) >> ; //scifta di 8 posizioni ed estrai l'indirizzo alto
PMCON1bits.RD=1; //Inizializza la lettura
NOP();
NOP();
INTCONbits.GIE=GIEbitsValue; //ripristina la condizione di interrupt presente
Word_memoria=(PMDATH << 8 | PMDATL);
return (Word_memoria); // ricongiungi il dato di 16 bit e restituiscilo
}
il problema lo tengo in scrittura con la funzione:
void FLASH_WriteWord(unsigned int flashAddress, unsigned int word)
{unsigned char GIEBitValue = INTCONbits.GIE; // salva la condizione degli interrupt generali
INTCONbits.GIE = 0; // disabilita gli interrupt
unsigned int vettore[16];
vettore[0]=word;
for (x=1; x<16;x++)
{vettore[x]=0x3FFF;
}
PMCON1bits.WREN = 1; // abilita la scrittura
for (x=0;x<16;x++)
{PMADRL = (flashAddress & 0x00FF);
PMADRH = ((flashAddress & 0xFF00) >> ;
PMDATL = vettore[x] & 0x00FF ;
PMDATH = ((vettore[x] & 0xFF00) >> ;
PMCON2 = 0x55;
PMCON2 = 0xAA;
PMCON1bits.WR = 1; //scrivi il dato
NOP();
NOP();
flashAddress++;
}
PMCON1bits.WREN = 0; // disabilita la scrittura
INTCONbits.GIE = GIEBitValue; // ripristina la condizione degli interrupt
}
Provando con la cella 0x07F0h a scrivere e leggere il dato 0x010F utilizzo i comandi:
FLASH_WriteWord(0x07F0, 0x010F);
FLASH_ReadWord(0x07F0);
Ma senza esito positivo.
Confermo che questo pic non necessita di cancellazione (dovrebbe funzionare come il 16F84), anche perchè non vi è alcun bit da impostare, quindi fa la cancellazione di 16 blocchi prima della scrittura. Dal data sheet non riesco però a capire quante celle vanno scritte (attualmente ne ho messe 16 ma anche con 4 è la stessa cosa...non riesco proprio a comprendere il corretto meccanismo
Dal Datasheet:
".. A block consists of four words with sequential
addresses, with a lower boundary defined by an
address, where PMADRL<1:0> = 00. All block writes to
program memory are done as 16-word erase by fourword
write operations...To write program data, it must first be loaded into the
buffer registers (see Figure 3-2). This is accomplished
by first writing the destination address to PMADRL and
PMADRH and then writing the data to PMDATL and
PMDATH. After the address and data have been set
up, then the following sequence of events must be
executed:
1. Write 55h, then AAh, to PMCON2 (Flash
programming sequence).
2. Set the WR control bit of the PMCON1 register.
All four buffer register locations should be written to
with correct data. If less than four words are being
written to in the block of four words, then a read from
the program memory location(s) not being written to
must be performed. This takes the data from the
program location(s) not being written and loads it into
the PMDATL and PMDATH registers. Then the
sequence of events to transfer data to the buffer
registers must be executed.
To transfer data from the buffer registers to the program
memory, the PMADRL and PMADRH must point to the
last location in the four-word block (PMADRL<1:0> =
11). Then the following sequence of events must be
executed:
1. Write 55h, then AAh, to PMCON2 (Flash programming
sequence).
2. Set control bit WR of the PMCON1 register to
begin the write operation.
The user must follow the same specific sequence to
initiate the write for each word in the program block,
writing each program word in sequence (000, 001,
010, 011). When the write is performed on the last
word (PMADRL<1:0> = 11), a block of sixteen words is
automatically erased and the content of the four-word
unsigned int FLASH_ReadWord(unsigned int flashAddr)
{unsigned char GIEbitsValue=INTCONbits.GIE; //salva la condizione degli interrupt generali
INTCONbits.GIE=0; //disabilita gli interrupt generali
PMADRL= (flashAddr && 0x00FF) ; // estrai il blocco indirizzo basso
PMADRH= ((flashAddr & 0xFF00) >> ; //scifta di 8 posizioni ed estrai l'indirizzo alto
PMCON1bits.RD=1; //Inizializza la lettura
NOP();
NOP();
INTCONbits.GIE=GIEbitsValue; //ripristina la condizione di interrupt presente
Word_memoria=(PMDATH << 8 | PMDATL);
return (Word_memoria); // ricongiungi il dato di 16 bit e restituiscilo
}
il problema lo tengo in scrittura con la funzione:
void FLASH_WriteWord(unsigned int flashAddress, unsigned int word)
{unsigned char GIEBitValue = INTCONbits.GIE; // salva la condizione degli interrupt generali
INTCONbits.GIE = 0; // disabilita gli interrupt
unsigned int vettore[16];
vettore[0]=word;
for (x=1; x<16;x++)
{vettore[x]=0x3FFF;
}
PMCON1bits.WREN = 1; // abilita la scrittura
for (x=0;x<16;x++)
{PMADRL = (flashAddress & 0x00FF);
PMADRH = ((flashAddress & 0xFF00) >> ;
PMDATL = vettore[x] & 0x00FF ;
PMDATH = ((vettore[x] & 0xFF00) >> ;
PMCON2 = 0x55;
PMCON2 = 0xAA;
PMCON1bits.WR = 1; //scrivi il dato
NOP();
NOP();
flashAddress++;
}
PMCON1bits.WREN = 0; // disabilita la scrittura
INTCONbits.GIE = GIEBitValue; // ripristina la condizione degli interrupt
}
Provando con la cella 0x07F0h a scrivere e leggere il dato 0x010F utilizzo i comandi:
FLASH_WriteWord(0x07F0, 0x010F);
FLASH_ReadWord(0x07F0);
Ma senza esito positivo.
Confermo che questo pic non necessita di cancellazione (dovrebbe funzionare come il 16F84), anche perchè non vi è alcun bit da impostare, quindi fa la cancellazione di 16 blocchi prima della scrittura. Dal data sheet non riesco però a capire quante celle vanno scritte (attualmente ne ho messe 16 ma anche con 4 è la stessa cosa...non riesco proprio a comprendere il corretto meccanismo
Dal Datasheet:
".. A block consists of four words with sequential
addresses, with a lower boundary defined by an
address, where PMADRL<1:0> = 00. All block writes to
program memory are done as 16-word erase by fourword
write operations...To write program data, it must first be loaded into the
buffer registers (see Figure 3-2). This is accomplished
by first writing the destination address to PMADRL and
PMADRH and then writing the data to PMDATL and
PMDATH. After the address and data have been set
up, then the following sequence of events must be
executed:
1. Write 55h, then AAh, to PMCON2 (Flash
programming sequence).
2. Set the WR control bit of the PMCON1 register.
All four buffer register locations should be written to
with correct data. If less than four words are being
written to in the block of four words, then a read from
the program memory location(s) not being written to
must be performed. This takes the data from the
program location(s) not being written and loads it into
the PMDATL and PMDATH registers. Then the
sequence of events to transfer data to the buffer
registers must be executed.
To transfer data from the buffer registers to the program
memory, the PMADRL and PMADRH must point to the
last location in the four-word block (PMADRL<1:0> =
11). Then the following sequence of events must be
executed:
1. Write 55h, then AAh, to PMCON2 (Flash programming
sequence).
2. Set control bit WR of the PMCON1 register to
begin the write operation.
The user must follow the same specific sequence to
initiate the write for each word in the program block,
writing each program word in sequence (000, 001,
010, 011). When the write is performed on the last
word (PMADRL<1:0> = 11), a block of sixteen words is
automatically erased and the content of the four-word
Si prega Accedi o Crea un account a partecipare alla conversazione.
- Elby
- Autore della discussione
- Senior Member
Riduci
Di più
- Messaggi: 43
- Ringraziamenti ricevuti 0
Moderatori: Mauro Laurenti, Pinna, StefA, Matteo Garia
Registrati al sito
Accedi a tutte le risorse e articoli non visibili pubblicamente, puoi registrarti con pochi passi.