Hallo..
ich versuche mich gerade daran mit einem AT89S52 testweise Daten auf den
den seriellen Baustein 23LCV1024 zu schreiben und danach wieder
auszulesen.
Folgender Ablauf sollte hierfür eigentlich richtig sein:
Ablauf Schreiben :
- WRITE : MODE REGISTER INSTRUCTION (00000001_b)
- WRITE : BYTE MODE (00000000_b)
- WRITE : WRITE DATA INSTRUCTION (00000010_b)
- WRITE : Address
- AddressByte1
- AddressByte2
- AddressByte3
- WRITE : Data (1Byte)
Ablauf Lesen:
- WRITE : READ DATA INSTRUCTION (00000011_b)
- WRITE : Address
- AddressByte1
- AddressByte2
- AddressByte3
- READ : Data (1Byte)
Vor jedem Schreibe und Lese-Zyklus muss CS auf LOW gezogen werden (bzw.
auf HIGH da der Pin invertiert ist), danach entsprechen wieder auf HIGH
(bzw. auf LOW). Die Daten werden beim Schreiben in den Speicher jeweils
bei der steigende Taktflanke übernommen und beim Lesen aus dem Speicher
bei der fallenden Taktflanke herausgegeben. Ansonsten ist eigentlich
alles recht trivial.
Allerdings habe ich jetzt mehrere male getestet und der Speicher gibt
einfach keine Daten zurück. Ich habe das ganze auch mal mit dem
Logikanalysator untersucht und bin eigentlich der Meinung, dass alles
soweit richtig läuft, bis auf dass der Speicher das Byte halt nicht
wieder auf SO legt.
Mein Code sieht folgendermaßen aus:
Ich nutze hierbei testweise die Adresse 00000000 00000000 00000000 und
das Datenbyte 55h (01010101_b)
Momentan ist mein einziger Ansatz, dass der Pin SO beim Schreiben
Hochohmig sein soll, laut Logikanalysator jedoch auf High liegt. (High
ist der Default wert auf allen Pins beim AT89S52)
Allerdings habe ich keine Ahnung wie ich den Pin auf Hochohmig schalten
kann..
ich glaube Sofwareseitig mit dem µC geht das garnich oder?
1. !CS
!CS separat steuern und in read/write nicht anfassen.
!CS muss vor jedem Befehl auf Low gesetzt werden, und nach jedem Befehl
wieder auf High, sonst wird der Befehl nicht ausgeführt.
2. SCK
SCK am Anfang des Programms auf low setzen. Sicherstellen, dass SCK low
ist, wenn der Zustand von !CS geändert wird. Im Ruhezustand ist SCK low.
3. Datenbits
erst Bit senden, dann SCK High, dann SCK low. Nicht anders. Setup-Zeiten
beachten.
Frank K. schrieb:> !CS muss vor jedem Befehl auf Low gesetzt werden, und nach jedem Befehl> wieder auf High, sonst wird der Befehl nicht ausgeführt.
Mit Befehl meinst du aber nicht jedes Schreiben und lesen eines
einzelnen Bytes, sondern so wie im Bild, dass ich angehängt hab:
- !CS LOW
- Dann alles was mit dem Schreiben zu tun hat
- danach !CS wieder HIGH oder ;)
Die anderen Sachen probiere ich mal aus :)
Danke für deine Antwort!
Anon Anon schrieb:> Mit Befehl meinst du aber nicht jedes Schreiben und lesen eines> einzelnen Bytes, sondern so wie im Bild, dass ich angehängt hab:> - !CS LOW> - Dann alles was mit dem Schreiben zu tun hat> - danach !CS wieder HIGH oder ;)
"Befehl" umfasst das Befehlsbyte am Anfang und die dazugehörigen Daten.
Also:
!CS Low - Set Mode Command - Set Mode Data - !CS High -
!CS Low - Write Command - Write Address (3x) - Write Data - !CS High
...
Frank K. schrieb:> 3. Datenbits> erst Bit senden, dann SCK High, dann SCK low. Nicht anders. Setup-Zeiten> beachten.
bist du dir da sicher?
weil im Datenblatt etwas davon steht, dass die Daten beim Schreiben
immer bei der steigenden Flanke übernommen werden.
1
3.2 Serial Output (SO)
2
The SO pin is used to transfer data out of the
3
23LCV1024. During a read cycle, data is shifted out on
4
this pin after the falling edge of the serial clock.
5
6
3.3 Serial Input (SI)
7
The SI pin is used to transfer data into the device. It
8
receives instructions, addresses, and data. Data is
Anon Anon schrieb:> Frank K. schrieb:>> 3. Datenbits>> erst Bit senden, dann SCK High, dann SCK low. Nicht anders. Setup-Zeiten>> beachten.>> bist du dir da sicher?> weil im Datenblatt etwas davon steht, dass die Daten beim Schreiben> immer bei der steigenden Flanke übernommen werden.
Ja, passt doch:
neues Bit senden
SCK HIGH
SCK LOW
und beim Lesen:
SCK HIGH
SCK LOW
neues Bit lesen
fchk
Soo.. jetzt läuft es :)
Danke euch allen für eure Hilfe.
Ich habe noch mal eine neue Messung und den Programmcode angehängt.
Das einzige was mich noch stört, ist dass die LEDs, die die gelesenen
Daten ausgeben gelegentlich falsche oder auch gar keine Werte anzeigen
und das auch teilweise für ein zwei Sekunden am Stück..
Ich frage mich nun ob ich noch einen Programmierfehler gemacht habe,
oder obs einfach an meinem Steckbrett und der relativ hohen Frequenz
liegt (Wackelkontakt und co. ...)
Was meint ihr?
Ich hab gerade festgestellt, dass ich damals den falschen code
hochgeladen hab.
!cs muss nämlich genau anders herum angesteuert werden.
also hier nochmal der richtige code und ein screenshot vom logik
analysator
Pin 0 NOT(CS)
Pin 1 SO
Pin 2 SI
Pin 3 SCK
Es gab noch einen Fehler im Taktsignal.
Zu beachten ist nämlich, dass
- Bits, die in den Chip geschrieben werden sollen, immer bei der
STEIGENDEN Flanke übernommen werden
- Nits, die aus dem Chig gelesen werden sollen, immer bei der
FALLENDEN Flanke vom Chip ausgegeben werden.
Der angehängte Quellcode sollte nun stimmen.
Falls jemand den 23LC1024 mit BASCOM programmiert, muss er den CS des
RAMs auf einen separaten Pin des uP legen, denn der SS-Ausgang, der mit
config spi = hard definiert wird, ergibt beim Read-Befehl eine
Fehlfunktion.
SPI_RAM: 'schreibt
Test-Daten in das RAM und liest diese wieder aus
spi_ram_cs = 0 'CS true des
SPI_RAM ohne SS-Pin (SPI = hard)
sdc_cmd(1) = &B00000001 'Mode
Register Instruction
sdc_cmd(2) = &B00000000 'Byte
Operation Mode
Spiout sdc_cmd(1), 2 '2 Bytes
ausgeben
spi_ram_cs = 1 'CS false
des SPI_RAM ohne SS-Pin (SPI = hard)
spi_ram_cs = 0 'CS true des
SPI_RAM ohne SS-Pin (SPI = hard)
sdc_cmd(1) = &B00000010 'Write Data
Instruction
sdc_cmd(2) = &B00000000 '1. Adress
Byte MSB, first 7 Bits don't care
sdc_cmd(3) = &B00000000 '2. Adress
Byte
sdc_cmd(4) = &B00000000 '3. Adress
Byte LSB
sdc_cmd(5) = &B01010101 'Test Data
Spiout sdc_cmd(1), 5 '5 Bytes
ausgeben
spi_ram_cs = 1 'CS false
des SPI_RAM ohne SS-Pin (SPI = hard)
spi_ram_cs = 0 'CS true des
SPI_RAM ohne SS-Pin (SPI = hard)
sdc_cmd(1) = &B00000011 'Read Data
Instruction
sdc_cmd(2) = &B00000000 '1. Adress
Byte MSB, first 7 Bits don't care
sdc_cmd(3) = &B00000000 '2. Adress
Byte
sdc_cmd(4) = &B00000000 '3. Adress
Byte LSB
Spiout sdc_cmd(1), 4 '4 Bytes
ausgeben
'Achtung:
hier wuerde der SS-Pin den CS kurz high schalten, was verboten ist
'deswegen
muss dafür spi_ram_cs eingesetzt werden
Spiin temp_byte, 1 '1 Byte
lesen
spi_ram_cs = 1 'CS false
des SPI_RAM ohne SS-Pin (SPI = hard)
Locate 1,1
LCD " "; 'LCD löschen
Locate 1,1
LCD hex(temp_byte); 'Data
Return
Der EAGLE-Stromlauf zeigt die Kombination des 23LC1024 und anderer
externer Speichermedien mit einem Atmel MEGA1284.
Guten Abend,
leider muss ich das Thema mit dem SPI-RAM Baustein 23A1024/23LC1024
nochmal aufgreifen. Folgendes Problem:
Für eine zeitkritische Anwendung möchte ich Daten, die ich zuvor in
diesem RAM eingelegt habe möglichst schnell noch einmal auslesen. Dazu
bietet sich der sequenzielle Auslesemodus an. Leider lese ich aber in
diesem Modus immer nur das erste Byte, sprich das Byte der zuvor
übermittelten Adresse aus, der Adresszeiger inkrementiert also nicht.
Deswegen lese ich derzeit Byte für Byte nach der jeweiligen
Adressübermittlung aus, was aber auf Dauer nicht die Lösung sein kann.
Anmerkung. Der SPI wird unter anderem auch für die Kommunikation mit
einer SD-Karte genutzt, er funktioniert auch für das byteweise Schreiben
in den RAM tadellos.
Hier der Code zur SPI-Konfiguration:
Hallo foobar,
vielen Dank für deine schnelle Antwort.
Schande über mich! Du hast natürlich vollkommen Recht. Ich war der
Meinung, dass ich ein Read-Mode und ein Write-Mode Register separat
setzen muss. Ein genauerer Blick ins Datenblatt hätte das verhindern
können.
Problem gelöst!:-)