Forum: Mikrocontroller und Digitale Elektronik SPI - 16MBit Flash-Speicher lässt sich nicht beschreiben bzw. auslesen


von H. G. (ledi)


Lesenswert?

Hallo,

ich versuche einen 16MBit Flash-Speicher von ST (SST25VF016B)über die 
SPI-Schnittstelle meines ATMega88 zu beschreiben bzw. auszulesen.

Datenblatt: http://www.farnell.com/datasheets/1669413.pdf

Das Statusregister auszulesen funktioniert! Das geschriebene Byte (wenn 
es denn geschrieben wurde) kann ich nicht auslesen!


Meine vorgehensweise beim Schreiben und Lesen eines Datenbytes ist 
folgende:

1.) Ein Byte auf Adresse 000000h schreiben:

CE auf low
  command 06h senden (write enable)
CE auf high

CE auf low
  command 02h senden (program one data byte)
  send addressbyte 00h (1. Adressbyte senden)
  send addressbyte 00h (2. Adressbyte senden)
  send addressbyte 00h (3. Adressbyte senden)
  send databyte AAh (datenbyte AAh senden)
CE auf high

CE auf low
  command 04h senden (write disable)
CE auf high


2.) Den Inhalt von Adresse 000000h auslesen:

CE auf low
  command 03h senden (read memory)
  send addressbyte 00h (1. Adressbyte senden)
  send addressbyte 00h (2. Adressbyte senden)
  send addressbyte 00h (3. Adressbyte senden)
  send dummybyte 00h (dummybyte 00h senden)
CE auf high

data = SPI_Receive();


hier der zugehörige Code:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
#define WP    (1<<PC5)  // Write Protect disable @PC5
5
#define HOLD  (1<<PC4)  // Stop serial communication disable @PC4
6
#define CE    (1<<PB2)  // Chip Enable @PB2
7
#define MOSI  (1<<PB3)  // Master Out Slave In @PB3
8
#define MISO  (1<<PB4)  // Master In Slave Out @PB4
9
#define SCK    (1<<PB5)  // Clock @PB5
10
11
uint8_t data, status_register=0;
12
13
void SPI_MasterInit(void)
14
{
15
  DDRB = MOSI|SCK|CE;            // Set MOSI, SCK, CE output
16
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1);  // Enable SPI, Master, set clock rate fck/64
17
}
18
void SPI_MasterTransmit(uint8_t data)
19
{
20
  SPDR = data;              // Start transmission
21
  while(!(SPSR & (1<<SPIF)));        // Wait for transmission complete
22
}
23
24
uint8_t SPI_SlaveReceive(void)
25
{
26
  while(!(SPSR & (1<<SPIF)));        // Wait for reception complete
27
  return SPDR;              // Return SPI-Dataregister
28
}
29
30
int main(void)
31
{
32
  DDRC |= WP | HOLD;            // Set WP, HOLD output
33
  PORTC |= WP|HOLD;            // Set WP, HOLD high 
34
  
35
    while(1)
36
    {
37
        SPI_MasterInit();            // Init SPI Master
38
    PORTB &= ~CE;              // CE = low (start communication)
39
    SPI_MasterTransmit(0x05);        // Send command 0x05 (Read the status register)
40
    SPI_MasterTransmit(0x00);        // Send one dummy byte             
41
    status_register = SPI_SlaveReceive();  // Store the value of the status register
42
    PORTB |= CE;              // CE = high (end of communication)
43
    status_register=0;            // set the variable to 0  
44
    _delay_us(10);
45
    
46
    PORTB &= ~CE;              // CE = low (start communication)
47
    SPI_MasterTransmit(0x06);        // Send command 0x06 (Set write enable WREN)
48
    PORTB |= CE;              // CE = high (end of communication)
49
    _delay_us(10);
50
    
51
    PORTB &= ~CE;              // CE = low (start communication)
52
    SPI_MasterTransmit(0x02);        // Send command 0x02 (program one data byte)
53
    SPI_MasterTransmit(0x00);        // Send 1. Addressbyte (MSB first)  
54
    SPI_MasterTransmit(0x00);        // Send 2. Addressbyte   
55
    SPI_MasterTransmit(0x00);        // Send 3. Addressbyte 
56
    SPI_MasterTransmit(0xAA);        // Send Databyte        
57
    PORTB |= CE;              // CE = high (end of communication)
58
    _delay_us(10);
59
    
60
    PORTB &= ~CE;              // CE = low (start communication)
61
    SPI_MasterTransmit(0x04);        // WRDI (write disable) Send command 0x04       
62
    PORTB |= CE;              // CE = high (end of communication)
63
    _delay_us(10);
64
    
65
    PORTB &= ~CE;              // CE = low (start communication)
66
    SPI_MasterTransmit(0x03);        // Send command 0x03 Read
67
    SPI_MasterTransmit(0x00);        // Send 1. Addressbyte (MSB first)  
68
    SPI_MasterTransmit(0x00);        // Send 2. Addressbyte   
69
    SPI_MasterTransmit(0x00);        // Send 3. Addressbyte 
70
    SPI_MasterTransmit(0x00);        // Send Dummybyte      
71
    PORTB |= CE;              // CE = high (end of communication)
72
    data = SPI_SlaveReceive();
73
    data = 0;
74
    }
75
}

: Bearbeitet durch User
von Takao K. (takao_k) Benutzerseite


Lesenswert?

/CE eingeschaltet lassen

von H. G. (ledi)


Angehängte Dateien:

Lesenswert?

Takao K. schrieb:
> /CE eingeschaltet lassen

Das sollte ich aber lt. Beschreibung im Datenblatt NICHT tun!

*** Write-Enable (WREN)***
The Write-Enable (WREN) instruction sets the Write-Enable-Latch bit in 
the Status Register to 1 allowing Write operations to occur. The WREN 
instruction must be executed prior to any Write (Program/Erase) 
operation.

Oder verstehe ich da etwas falsch?

von Takao K. (takao_k) Benutzerseite


Lesenswert?

Zufaellig habe ich diese chips hier und auch mal verwendet.

Ich schau mir jetzt mal das Datenblatt an.

Aber grundsaetzlich, solange du mit dem chip arbeitest, /CE = 0.

Wenn du mit dem Schreiben fertig bist, wieder auf 1, oder einfach auf 0 
lassen. Das wird hauptsaechlich beutzt, wenn du mehr als einen seriellen 
chip parallel an den gleichen Leitungen hast, und teilweise auch, um 
Strom zu sparen.

von Takao K. (takao_k) Benutzerseite


Lesenswert?

Ja teilweise ist es richtig, /CE wird wieder auf 1 gesetzt, wenn ein 
neues Kommando uebertragen werden soll.

du musst auch noch "End of Write" abfragen, also ob der chip mit dem 
Schreiben fertig ist. Oder du verlaesst dich auf die 10uS Angabe aus dem 
Datenblatt...

PORTC wuerde ich auch erstmal auf 0 setzen, dann den Tristate bus 
einschalten.

vielleicht erst einmal mit "Bitbang" versuchen, wenn es fuktionert, den 
Hardware serial port verwenden.

Anstatt 10uS 100uS versuchen.
PORTC auf 0 setzen.
Bitbang verwenden zum Testen.

: Bearbeitet durch User
von Arc N. (arc)


Lesenswert?

Da müssen einige Sachen vorher passieren, damit das klappt.
Hier ist es bspw. so implementiert:
(Pseudocode)
1
ProgStart
2
  /CE = 0 
3
  Transmit(EWSR)
4
  /CE = 1
5
  /CE = 0
6
  Transmit(WRSR)
7
  // WEL = 1, BPx = 0, da das Flash nach dem PowerOn/Reset 
8
  // alle Speicherblöcke vor Schreibzugriffen schützt (Table 3 und 4 im DB)
9
  Transmit(0b00000010); 
10
  /CE = 1
11
  ...
12
13
MemWrite
14
  /CE = 0
15
  Transmit(WREN)
16
  /CE = 1
17
18
  /CE = 0
19
  // jetzt der eigentliche Schreibvorgang
20
  /CE = 1

von Dominic A. (neo123)


Lesenswert?

Mit den Speichertypen habe ich auch lange gekämpft. Bis ich 
herausgefunden habe das bei jedem Start der Flash zuerst unlockt werden 
muss.
Probier also mal vor dem Schreiben eine Unlock Sequenz durchzuführen.

von Bastler (Gast)


Lesenswert?

Hallo ich hänge am gleichen Problem.

Ich habe das Beispiel von ST verwendet.
Die CHIP-ID kann ich auslesen, von daher steht meine SPI Verbindung.
Aber ich kann nichts schreiben oder lesen.
Sogenau weiß ich es nicht, da ich beim lesenn immer 0xFF empfange.
Der leere Baustein ist ja mit 0xFF gefüllt.

Ich vermute ein Fehler im Schreibvorgang.

Ist im Beispiel ein Fehler?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.