Problem mit seriellem Speicher 25LC640!
Mittwoch, 23. Mai 2012
 
 

PIC Mikrocontroller Forum  |  PIC Mikrocontroller  |  CCS Compiler  |  Schnittstellen (CCS)  |  Problem mit seriellem Speicher 25LC640! « vorheriges nächstes »
Seiten: [1] 2 Nach unten Drucken
Autor Thema: Problem mit seriellem Speicher 25LC640!  (Gelesen 3093 mal)
 
dewey
Jr. Member
**
Offline Offline

Beiträge: 62


Profil anzeigen
« am: Januar 24, 2010, 19:37:30 »

Hallo

Ich möchte mit einem PIC16F877a über das SPI Interface Daten in den Speicher schreiben und dann wieder auslesen und auf einem Display anzeigen. (einfach nur mal für Testzwecke).

Die Display Ansteuerung (Nokia 3310 Display) funktioniert einwandfrei. Somit funktioniert auch die Datenübertragung per SPI.

So ich habe 2 Funktionen geschrieben um Daten aus dem 25LC640 auszulesen und zu beschreiben.

Hier die Funktion um Daten auszulesen:

Ich übergebe der Funktion die Speicher Adresse von der ich die Daten auslesen möchte.
Code:
unsigned int read_eeprom(unsigned int l_addr, unsigned int h_addr) {
   unsigned int data = 0;
   ECS = 0; //Chipselect -> enabled
   DelayUs(100);
   write_spi(READ); // READ ist eine Konstante mit dem Wert 0x03 ->laut Datenblatt
   write_spi(h_addr); // High Byte der 16bit Adresse
   write_spi(l_addr); // Low Byte der 16Bit Adresse
   data = read_spi(); // gelesenen Daten in der variable data abspeichern
   ECS = 1;      // Chipselect -> disabled
   DelayUs(100);
   return data; 
}

Hier die Funktion um Daten in den Speicher zu schreiben
Adresse und Daten werden übergeben
Code:
void write_eeprom(unsigned int data, unsigned int l_addr, unsigned int h_addr) {
   ECS = 0;  //Chipselect -> enabled
   DelayUs(100);
   write_spi(WREN); // Write enable bit setzen; hat den wert 0x06 laut Datenblatt
                       muss dieses Write enable Latch vor jedem Schreibzyklus
                       gesetzt werden
   ECS = 1;  // Chipselect -> disabled
   DelayUs(100);

   DelayMs(20);

   ECS = 0;  // Chipselect -> enabled
   DelayUs(100);
   write_spi(WRITE); //WRITE ist eine Konstante mit dem Wert 0x02->laut Datenblatt
   write_spi(h_addr); // High Byte der 16bit Adresse
   write_spi(l_addr); // Low Byte der 16Bit Adresse
   write_spi(data);  // Daten schreiben
   ECS = 1;  // Chipselect -> disabled
   DelayUs(100);
}

Ich habe die Funktionen so aufgebaut wie es im Datenblatt beschrieben ist.
Leider tut sich gar nichts. Im Main Programm schreibe ich ein Byte 0xFF an die Speicheradresse 0x0000 und 2 Sekunden später sollte diese Speicheradresse ausgelesen werden und die Daten auf dem Display angezeigt werden. Leider wird mir nichts angezeigt.

Kann mir hier jemand helfen??? Habe ich vielleicht irgendwelche Delays vergessen oder sogar irgendwelche Initialisierungs-Maßnahmen für den Speicher vergessen?

Den HOLD Pin habe ich auf die Versorgungsspannung gelegt. Was soll ich mit dem WP Pin machen, oder stört es nicht wenn ich diesen Pin nicht angeschlossen habe?

Ich danke euch schon im Voraus,

mit freundlichen Grüßen
dewey
Gespeichert
Coltfisch
Sr. Member
****
Offline Offline

Beiträge: 496



Profil anzeigen WWW
« Antworten #1 am: Januar 25, 2010, 10:58:14 »

Hallo dewey,

Zitat
Leider wird mir nichts angezeigt.
Huch Also doch eher ein Problem mit dem LCD als mit dem EEPROM?  Grinsend

Spaß beiseite. Ich habe Deinen Code jetzt (noch) nicht im Detail geprüft, denn mir ist etwas anderes aufgefallen:
Es steht zwar nicht explizit im Datenblatt, aber ich würde den WP-Pin auf keinen Fall floaten lassen. Du solltest den definiert auf VDD legen, sonst ist das EEPROM womöglich schreibgeschützt.
Versuch das erstmal.

Gruß
Daniel
Gespeichert
dewey
Jr. Member
**
Offline Offline

Beiträge: 62


Profil anzeigen
« Antworten #2 am: Januar 25, 2010, 13:07:36 »

Hallo

Ok danke für die schnelle Antwort werde ich gleich mal machen und noch mal versuchen.

 Grinsend jaaa das Thema LCD ist zum Glück erledigt. Das funktioniert jetzt einwandfrei ohne Probleme.

mfg

soooo habe jetzt mal den WP PIN auf VDD gelegt. doch leider hat sich nichts geändert.
« Letzte Änderung: Januar 25, 2010, 13:22:18 von dewey » Gespeichert
Coltfisch
Sr. Member
****
Offline Offline

Beiträge: 496



Profil anzeigen WWW
« Antworten #3 am: Januar 26, 2010, 14:42:26 »

Hallo dewey,

der Code sieht - bis auf das 20ms-Delay, welches mir etwas lang erscheint - gut aus und sollte eigentlich so funktionieren. Was ich nicht prüfen kann ist, ob die Pinbelegung (ECS) sowie die verwendeten Konstanten (READ, WREN,...) korrekt sind. Da solltest Du noch einmal genau nachschauen. Gleiches gilt natürlich auch für die Schaltung. Alle Verbindungen korrekt? Versorgungsspannung sauber? Abblockkondensator am EEPROM?

Außerdem wäre es gut zu wissen, welche Symptome denn überhaupt auftreten? Was bedeutet "Leider wird mir nichts angezeigt." denn nun tatsächlich? Liest Du immer eine 0, oder was?

Gruß
Daniel
Gespeichert
dewey
Jr. Member
**
Offline Offline

Beiträge: 62


Profil anzeigen
« Antworten #4 am: Januar 26, 2010, 20:11:48 »

Hallo

Im Datenblatt steht das man das Write enable latch setzen muss bevor man Daten in den EEPROM schreiben kann. Und es steht auch drinnen dass man den Chipselect (ECS) low setzen soll, dann das WREN Byte an das EEPROM senden und dann unbedingt ECS wieder auf high setzen muss damit das write enable latch auch wirklich gesetzt ist.
Naja und da habe ich mir gedacht das ich ganz einfach mal 20ms Zeitverzögerung einbaue damit wirklich genug Zeit bleibt. Ich werde nochmal im Datenblatt nachlesen ob es da eine maximale Delay Zeit gibt.

zum Aufbau der Schaltung: sollte eigentlich alles passen. Ich habe eine 3,3Volt Versorgung (hoffe ich habe mich im Datenblatt nicht verschaut aber es sollte mit den 3,3V funktionieren). EInen Abblockkondensator habe ich auch drinnen, gleich beim eeprom
habe 23nF verwendet, ist der Wert ok? oder sollte ich einen anderen verwenden??

Verbindungen, Kontakte sollten alle passen werde das aber nochmal kontrollieren.

zu den Symptomen: Nach einschalten der Spannungsversorgung wird das Display initialisiert (alle Pixel gesetzt und nach einer Sekunde rückgesetzt bzw der Display RAM wird gelöscht) also soweit alles so wie es sein sollte.
nun sollten die Daten (also das eine Daten byte 0xFF) in den eeprom geschrieben werden (kann nicht sagen ob das korrekt durchgeführt wird) und dann nach 2 Sekunden Verzögerung sollten die Daten aus dem EEprom gelesen werden und anschließend auf dem Display angezeigt werden. Es wird aber nur 0x00 angezeigt (also am Display wird kein Pixel gesetzt)

Werde mir jetzt auf jedenfall noch mal den Aufbau ansehen und im Datenblatt wegen dieser Delay-Zeit schauen und eventuell runtersetzen und nochmal probieren.

mfg Dewey
Gespeichert
Bernd
Globaler Moderator
Hero Member
*****
Offline Offline

Beiträge: 3815



Profil anzeigen
« Antworten #5 am: Januar 26, 2010, 23:58:16 »

Zitat
Es wird aber nur 0x00 angezeigt

Das deutet sehr auf einen Fehler beim Auslesen hin. Der Schreibvorgang mit 0xFF ist praktisch bedeutungslos, da es dem gelöschten Zustand des EEPROMs und damit fast immer dessen Lieferzustand entspricht. Im Endeffekt ergibt sich daraus in Deinbem Fall, daß man nie sicher sein kann, ob ein Schreibvorgang mit dem Wert 0xFF erfolgreich war oder nicht.

Wie ist die SPI-Schnittstelle für den Zugriff auf das EEPROM konfiguriert? Von besonderem Interesse sind dabei die Bits CKE, CKP und SMP.


Viele Grüße

Bernd
Gespeichert

dewey
Jr. Member
**
Offline Offline

Beiträge: 62


Profil anzeigen
« Antworten #6 am: Januar 27, 2010, 14:17:05 »

Hallo

Ich habe die SPI folgendermaßen initialisiert:

Code:
void init_spi() {
   // PIN RC3 und RC5 als Ausgang definieren
   TRISC3=0;
   TRISC5=0;
   
   // setup SPI mode
   CKE = 0;  //Transmit occurs on transition from Idle to active clock state
   CKP = 1;  //Idle state for clock is a high level
   SSPM0 = 0; // SPI Mode: Master, fosc/4
   SSPM1 = 0;
   SSPM2 = 0;
   SSPM3 = 0;
   SSPEN = 1; // SPI Enable -> 1
}

Mit diesen Einstellungen sende ich Daten in das Display RAM und es funktioniert einwandfrei. Hoffe das passt so auch für den Eeprom??

mfg


Sooo habe jetzt mal im Datenblatt vom Display und vom EEprom nachgesehen wie des mit dem SCLK ausschaut. Es müsste eigentlich so stimmen wie ich es gemacht habe.
« Letzte Änderung: Januar 27, 2010, 14:54:09 von dewey » Gespeichert
Bernd
Globaler Moderator
Hero Member
*****
Offline Offline

Beiträge: 3815



Profil anzeigen
« Antworten #7 am: Januar 27, 2010, 18:27:43 »

Zitat
Sooo habe jetzt mal im Datenblatt vom Display und vom EEprom nachgesehen wie des mit dem SCLK ausschaut. Es müsste eigentlich so stimmen wie ich es gemacht habe.

Die Einstellungen sind auch meines Erachtens korrekt. Zwei Dinge noch:

1)
Zitat
Ich habe eine 3,3Volt Versorgung

Auch für den 16F877A?. Wenn ja, muß streng genommen ein 16LF877A eingesetzt werden (maximale Taktfrequenz 10MHz). Wenn nein, wird der High-Pegel des EEPROMs nicht ausreichend sein, um als solcher zu erkannt werden.

2)
Code der Funktion read_spi()?


Viele Grüße

Bernd
Gespeichert

dewey
Jr. Member
**
Offline Offline

Beiträge: 62


Profil anzeigen
« Antworten #8 am: Januar 27, 2010, 18:46:23 »

Sorry für die falsche Angabe ich verwende einen 16LF877a (8Mhz Takt) mit einer Versorgungsspannung von 3,3V.

Hier die read_spi() Funktion:
Code:
void write_spi(unsigned int data) {
   SSPBUF = data;
}

unsigned int read_spi() {
   unsigned int data = 0;
   data = SSPBUF;
   return data;
}



mfg
Gespeichert
Bernd
Globaler Moderator
Hero Member
*****
Offline Offline

Beiträge: 3815



Profil anzeigen
« Antworten #9 am: Januar 27, 2010, 23:04:31 »

Um Daten als Master über SPI lesen zu können, muß man zuerst ein Dummy-Byte senden und danach auf das Ende des Sendevorgangs warten. Erst dann können die Daten über SSPBUF ausgelesen werden.

Code:
unsigned char read_spi (void)
{
   SSPBUF = 0; // Dummy-Byte „0“ senden
   while (BF == 0)  // warten, bis Byte gesendet, d.h bis
      ;             // die zu empfangenden Daten zur Verfügung stehen
   
  return SSPBUF;    // empfangenen Wert zurückgeben
}

Beim Schreiben muß man des weiteren darauf achten, daß man nicht erneut in SSPBUF schreibt, bevor das zu übertragende Byte komplett gesendet worden ist (bei hohen SPI-Frequenzen ist das u.U. nicht nötig, da die Abarbeitung der Schreibroutine insgesamt länger dauert, als die Übertragung des Bytes).

Code:
void write_spi (unsigned char data)
{
    do
    {
       WCOL = 0;
       SSPBUF = data; 
    } while (WCOL == 1);
}

Noch zwei Sachen:

1)
Beim Hi-Tech (und allen anderen dem ANSI-C Standard folgenden Compilern) kann ein int mindestens 16 Bit aufnehmen. Für 8-Bit Datentypen sollte char verwendet werden.

2)
Zitat
Code:
write_spi(WREN);

WREN ist beim Hi-Tech als ein Bit-Name bereits definiert (EECON1-Register). Daher solltest Du den Namen des Defines besser ändern, z.B. in EEP_WREN.


Viele Grüße

Bernd
« Letzte Änderung: Januar 27, 2010, 23:14:01 von Bernd » Gespeichert

dewey
Jr. Member
**
Offline Offline

Beiträge: 62


Profil anzeigen
« Antworten #10 am: Januar 28, 2010, 12:22:06 »

Hallo

Hab die Funktionen jetzt mal geändert. Leider ändert sich an der Situation nichts.

Jetzt mal eine ganz Blöde Frage zum Aufbau:

EEPROM PIN      PIC
    1...CS   -> RD3
    2...SO   -> SDI RC4
    3.../WP -> +3,3V
    4...VSS 
    5...SI    -> SDO RC5
    6...SCLK  -> SCLK RC3
    7.../HOLD -> +3,3V
    8...VDD -> +3,3V

Ich habe den PIC mit dem EEPROM so verbunden. Bin mir jetzt nicht sicher ob die SO und SI Leitungen ausgekreuzt werden müssen oder nicht??

mfg
Gespeichert
dewey
Jr. Member
**
Offline Offline

Beiträge: 62


Profil anzeigen
« Antworten #11 am: Januar 28, 2010, 17:40:34 »

Hallo

Sooooo bin jetzt so weit das ich den ROM auslesen bzw beschreiben kann.

Habe mich mal mit dem Oszi hingesetzt und alle Signale durchgecheckt. Also ich habe zuerst nur den EEPROM beschrieben und mir die Signale angesehen und festgestellt es passt alles. Dann habe nur aus dem EEPROM gelesen und mir die Daten auf dem Display ausgeben lassen und natürlich alle SIgnale gemessen. Auch hier habe ich festgestellt es funktioniert alles und auf dem Display werden mir die richtigen Daten angezeigt.

Aber jetzt kommt das komische an der ganzen Geschichte. Nun habe ich nochmals folgendes versucht:
Datenbyte an eine bestimmte Speicheradresse gesendet, anschließend die Daten von der vorher beschriebenen Speicherzelle auslesen und auf dem Display anzeigen lassen. Und siehe da es wird mir nichts angezeigt. Die Daten die ich an die neue Speicheradresse gesandt habe werden aber erfolgreich abgespeichert.
Der Code sieht so aus:

Zuerst habe ich folgenden Code ablaufen lassen
So wird mir das Datenbyte nicht am Display angezeigt:
Code:
void write_start() {
   unsigned int data = 0;
   
   lcd_printf("Start", 0, 0); // wird erfolgreich auf dem Display ausgegeben
   
   write_eeprom(0x0A, 201); //Daten werden erfolgreich abgespeichert
   DelayUs(10);
   data = read_eeprom(200);
   DelayUs(10);
   write_data(data, 2, 0);
}

Nun spielte ich folgendes Programm ein
So wird mir das Datenbyte am Display angezeigt:
Code:
void write_start() {
   unsigned int data = 0;
   
   lcd_printf("Start", 0, 0); // wird erfolgreich auf dem Display ausgegeben
   
   //write_eeprom(0x0A, 201);
   DelayUs(10);
   data = read_eeprom(201);
   DelayUs(10);
   write_data(data, 2, 0); //am Display wird mir 0x0A angezeigt
}

Also sobald ich beide Funktionen (eeprom_write() und eeprom_read()) benutze, wird mir nichts mehr angezeigt. Werde jetzt nochmal mit Oszi den Fall in dem mir nichts angezeigt wird durchmessen und schauen ob ich so auf eine Lösung komme.

Hat von euch irgendjemand eine Idee woran das liegen kann??

mfg
Gespeichert
Bernd
Globaler Moderator
Hero Member
*****
Offline Offline

Beiträge: 3815



Profil anzeigen
« Antworten #12 am: Januar 28, 2010, 17:40:59 »

Zitat
Ich habe den PIC mit dem EEPROM so verbunden. Bin mir jetzt nicht sicher ob die SO und SI Leitungen ausgekreuzt werden müssen oder nicht??

Verdrahtung stimmt so.

Die von mir geposteten Lese- und Schreibfunktionen paßten nicht zusammen. Problem dabei war, daß das BF-Flag beim Eintritt in read_spi() schon gesetzt war (durch den Aufruf von write_spi() zuvor).

Nächster Versuch:
Code:
unsigned char read_spi (void)
{
   SSPBUF = 0; // Dummy-Byte „0“ senden
   while (BF == 0)  // warten, bis Byte gesendet
      ;                
   return SSPBUF;   // empfangenen Wert zurückgeben
}

void write_spi (unsigned char data)
{
    SSPBUF = data;  
    while (BF == 0) // warten, bis Byte gesendet
        ;
    SSPBUF;         // Dummy-Read, löscht BF-Flag
}

Oder auch einfacher über nur eine Funktion:

Code:
unsigned char spi_com (unsigned char data)
{
    SSPBUF = data;
    while (BF == 0)
       ;

    return SSPBUF;
}

...

   spi_com (READ);     // READ ist eine Konstante mit dem Wert 0x03 ->laut Datenblatt
   spi_com (h_addr);   // High Byte der 16bit Adresse
   spi_com (l_addr);   // Low Byte der 16Bit Adresse
   data = spi_com (0); // gelesenen Daten in der variable data abspeichern


Viele Grüße

Bernd
Gespeichert

dewey
Jr. Member
**
Offline Offline

Beiträge: 62


Profil anzeigen
« Antworten #13 am: Januar 29, 2010, 09:07:24 »

Hallo

Sooo habe die read_spi() und write_spi() jetzt mal umgeändert. aber leider hat sich nichts geändert. Bin mir nicht sicher ob du den letzten Beitrag von mir gesehen hast, da ich ihn ca 30 sekunden vor dir gepostet habe*gg*

Vielleicht eine Idee warum das nicht so hinhaut wie ich will??

mfg
Gespeichert
Bernd als Gast
Gast
« Antworten #14 am: Januar 29, 2010, 17:12:57 »

Zitat
Vielleicht eine Idee warum das nicht so hinhaut wie ich will??

Zitat
Code:
   write_eeprom(0x0A, 201); //Daten werden erfolgreich abgespeichert
   DelayUs(10);
   data = read_eeprom(200);

Der interne Schreibvorgang (nach steigender Flanke an CS) im EEPROM benötigt bis zu 5ms. Während des internen Schreibvorgangs kann man nicht auf die im EEPROM gespeicherten Daten zugreifen.


Viele Grüße

Bernd
Gespeichert
Seiten: [1] 2 Nach oben Drucken 
« vorheriges nächstes »
Gehe zu:  

Powered by MySQL Powered by PHP Made for Mozilla (Firefox) Made for Internet Explorer
Seite erstellt in 0.053 Sekunden mit 19 Zugriffen.
 
Top! Top!