Forum: Mikrocontroller und Digitale Elektronik PIC18F2620 mit I2C EEPROM 24LC04B unter CCS Compiler


von T. D. (thoms)


Lesenswert?

Hallo,

ich bräuchte etwas Anfahrhilfe beim Umgang mit dem obengenannten eeprom.

Auf dem EEprom möchte ich Messergebnisse in erster Linie nur 
abspeichern. Später sollen diese dann über eine serielle Schnittstelle 
direkt vom EEprom ausgelesen werden können (wahrscheinlich mit 
ponyprog).

Die Hardware ist bereits aufgebaut, nur habe ich doch erhebliche 
Probleme einen Ansatz zu finden, da ich mit externen Bausteinen nur 
wenig bis gar keine Erfahrung habe.

Im Compiler habe ich die nötigen Einstellungen gewählt, wie:

Aktivierung der I2C Schnitstelle im Slow Modus -->

 #use i2c(Master,Slow,sda=PIN_C4,scl=PIN_C3)

Treiber Auswahl für das EEprom -->

 #include <2404.C>
  init_ext_eeprom();

Hat vielleicht jemand ein demonstratives Programm, welches vielleicht 
sogar im CCS Compiler erstellt wude und Werte ins EEPROM schreibt und 
wieder ausliest. Wäre euch sehr dankbar.

Das zugehörige Handbuch zum CCS PICmicro gibt nicht allzuviel Auskunft 
zur I2C Schnittstelle.

Grüße Thomas

von Thorsten (Gast)


Lesenswert?

Hi,

hast du die I²C Leitung mit einem Pull Up (10K) gegen Vcc gelegt?

Gruß

Thorsten

von T. D. (thoms)


Lesenswert?

Hallo Thorsten,

beide Leitungen für die I2C Schnittstelle sind mit einem 10k Pull Up 
gegen +5V gelegt.

Laut Datenblatt zum EEPROM braucht nur die SDA Leitung einen PULL UP 
(10K für 100kHz). Im Handbuch zum Compiler stand ausdrücklich, dass 
beide (SDA und SCL) einen PULL UP von 1-10K an +5V benötigen.

Gruß Thomas

von Thorsten (Gast)


Lesenswert?

Hi,

schau dir mal die EX_EXTEE.C an. Das ist eine Beispiel für ein externes 
EEPROM.

Gruß

Thorsten

von T. D. (thoms)


Lesenswert?

Hi, habe die Beispieldatei schon mal nachgeschlagen gehabt und wieder 
verzweifelt beiseite gelegt. Im Programm sind soviele Kleinigkeiten die 
mir nicht verständlich sind.
Hatte das folgende Programm schon einmal ausprobiert aber leider nicht 
zum laufen gebracht. Wer weiß was ich alles falsch gemacht und 
interpretiert habe. Ich werd´s einfach weiter versuchen.

Gibt es irgendwelche groben Schlanker die ich beachten sollte und nicht 
einfach 1:1 übernehmen kann. Ich denke man erkennt meine nicht ganz so 
ausgeprägten Kenntnisse in dieser Materie (Schnitstellen I2C, SPI usw). 
Bei Tastern, Led´s, Potis und einlesen von Analogwerten, ausführen von 
Rechenoperationen (DFT bzw. FFT) sind meine Fähigkeiten dann erschöpft.



void main() {

   BYTE value, cmd;
   EEPROM_ADDRESS address;

   init_ext_eeprom();

   do {
      do {
         printf("\r\nRead or Write: ");
         cmd=getc();
         cmd=toupper(cmd);
         putc(cmd);
      } while ( (cmd!='R') && (cmd!='W') );

      printf("\n\rLocation: ");

#if sizeof(EEPROM_ADDRESS)==1
      address = gethex();
#else
#if EEPROM_SIZE>0xfff
      address = gethex();
#else
      address = gethex1();
#endif
      address = (address<<8)+gethex();
#endif

      if(cmd=='R')
         printf("\r\nValue: %X\r\n",READ_EXT_EEPROM( address ) );

      if(cmd=='W') {
         printf("\r\nNew value: ");
         value = gethex();
         printf("\n\r");
         WRITE_EXT_EEPROM( address, value );
      }
   } while (TRUE);
}

von Pete K. (pete77)


Lesenswert?

Hast Du im Datenblatt des EEPROMS mal nachgeschaut, wie die Read bzw. 
Write Sequenz lautet ?

Meistens muss man erst eine Adresse schreiben, um dann im zweiten 
Schritt einen Wert zu lesen. Bei Dir sehe ich glaube ich nur das Lesen 
an sich.

von Gerhard. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Thomas,

im Anhang findest Du ein paar I2C EEPROM Routinen die ich vom CCS 
Beispiel adaptiert habe. In meiner Schaltung verwende ich den AT24C1024 
(128Kx8) mit 18F8722. Der Code wurde von mir nur fuer Testzwecke 
verwendet.

Vielleicht hilft Dir dieses Beispiel.

Die Funktion "test_EEPROM()" schreibt 256 bytes (ASCII) mittels page 
mode und dann liest die selben 256 Bytes wieder zurueck und misst die 
Zeit fuer den Schreibvorgang. Beim AT24C1024 dauert das schreiben in 
PAGE mode ungefaehr 9ms. Bei Deinem EEPROM ist der "PAGE size" viel 
kleiner und das muss angepasst werden. Sonst funktioniert das bei Dir 
nicht. Beim ATC1024 is der page size 256 bytes. Beim LC04 ist er 16 
bytes. Aendere Zeile 123:

write_ext_eeprom_page(0, buf, 256); auf
write_ext_eeprom_page(0, buf, 16);

....

read_ext_eeprom_sequential(0, buf, 256); auf
read_ext_eeprom_sequential(0, buf, 16);

Die Beispiele von CCS sollten auf alle Faelle funktionieren und als 
Startpunkt verwendbar sein.

Gruss,
Gerhard

von T. D. (thoms)


Lesenswert?

Hallo,

werde mich dann mal dran setzen und die mir jetzt zur Verfügung 
stehenden Beispiele durcharbeiten.

@Gerhard
Schon einmal einen herzlichen Dank an dieser Stelle!!!

Grüße Thomas

von Gerhard. (Gast)


Lesenswert?

Hallo Thomas,

@von Dir:

"beide Leitungen für die I2C Schnittstelle sind mit einem 10k Pull Up
gegen +5V gelegt.

Laut Datenblatt zum EEPROM braucht nur die SDA Leitung einen PULL UP
(10K für 100kHz). Im Handbuch zum Compiler stand ausdrücklich, dass
beide (SDA und SCL) einen PULL UP von 1-10K an +5V benötigen."

Ich moechte Dir noch raten die Pullup Widerstaende zwischen 3.9-4.7K zu 
dimensionieren. Es soll angeblich ausserhalb dieses Bereichs bei manchen 
Bausteinen damit Schwierigkeiten geben. Bei mir hat mit 3.9K immer alles 
bestens funktioniert.

Nicht vergessen die SDA und SCL als Eingaenge mit (set_tris_?) zu 
setzen.
Uebriegens, bei meiner Scahltung habe ich das so initialisiert:

Auuserhalb von main():

#use i2c(Master, SDA=PIN_H4, SCL=PIN_H5)
#define PORT_H_MASK 0b00111111

(in main()):

set_tris_h(PORT_H_MASK);
init_ext_eeprom();



Gerhard

von T. D. (thoms)


Lesenswert?

Hallo zusammen, trozt der Beispiele, welche ich auch einigermaßen
verstanden habe, da sie sich nah an das CCS Beispiel für EEPROM Treiber
halten, bin ich leider noch nicht zum Erfolg gelangt.

Für den Anfang wollte ich es nicht zu schwer machen und mich auf die
Grundbefehle aus der Treiberdati 2404.C beschränken, die wie folgt
lauten:

Library for a MicroChip 24LC04B                                 ////
////
////
////   init_ext_eeprom();    Call before the other functions are used
////
////
////
////   write_ext_eeprom(a, d);  Write the byte d to the address a
////
////
////
////   d = read_ext_eeprom(a);  Read the byte d from the address a
////
////
////
////   b = ext_eeprom_ready();  Returns TRUE if the eeprom is ready
////
////                            to receive opcodes

Problem:
Beschreibe ich das EEPROM mit Zahlen von 0..n und möchte es wieder
auslesen, erhalte ich auschließlich n mal den Wert -3.
Die Kommunikation zwischen µC und EEPROM scheint zu funktionieren, da
der Befehl ext_eeprom_ready() auch "TRUE" zurück gibt. Ich denke mal, es
ist wahrscheinlich eher schwierig, mit diesen Infos euch eine
Problemlösung zu entlocken und den Fehler zu erkennen, aber vielleicht
gibt es ja jemanden, der mich mit der Nase drauf schupsen kann ;0)

Am Rande hätte ich noch ein paar weitere Fragen:

1. Gehe ich richtig in der Annahme, dass man das EEPROM 24LC04 komplett
beschreiben kann, ohne dass man acht gibt welchen der zwei 256 byte
Blöcke man anscprechen möchte? Die Aufteilung für's 24LC04 ist 2x256x8 /
24LC08 ist 4x256x8. Das Datenblatt macht an dieser Stelle doch etwas
paradoxe Aussagen.

2. Für die I2C Schnitstelle gibt es die Wahl für "SLOW" oder "FAST"
Modus.
Sollte ich eine dieser Einstellung bevorzugen? Der Compiler generiert
mir etweder #use i2c(Master,Fast (oder Slow),sda=PIN_C4,scl=PIN_C3).

3. Frage an Dich Gerhard:
Was bewirke ich genau mit der Set_Tris_C(PORT_C_MASK) Funktion
in Verbindung mit #define PORT_C_MASK 0b00011000?
In der Hilfe funktion wird noch darauf hingewiesen, dass mit diesem
Befehl ein #use_fast_IO() benötigt wird - stimmt das, und wo liegt genau 
der Unterschied zu #use_standard_IO()?

zur Info: deinen Ratschlag mit den PullUp's habe ich schon mal
berücksichtigt und sie mit 3.9k ersetzt.

Viele Grüße Thomas

von Gerhard. (Gast)


Lesenswert?

Hallo Thomas,

komme erst jetzt dazu Dir zu antworten da zwischen uns 8 Stunden 
Zeitunterschied sind.

Das Set_tris_x erlaubt Dir die IO Port des PICs in Fast Mode zu 
verwenden.
Das bedeutet dass der Compiler nicht bei jeden Zugriff mittels der CCS 
gaengigen IO Funktionen (output_high( ))das Port direction register 
setzen muss.

CCS sagt dazu "Fast Mode". Wenn also die  Mask fuer Port C wie in meinem 
Beispiel 0b00011000 ist, dann setzt eine "1" das korrespondierende Port 
Bit auf Eingang und ein"0" als Ausgang. Wenn man diese Methode 
verwendet, muss vorher #use fast_io(c)" stehen.

Vom Handbuch:

#USE STANDARD_IO (port):

"This directive affects how the compiler will generate code for input 
and output instructions that follow. This directive takes effect until 
another #use xxx_io directive is encountered. The standard method of 
doing I/O will cause the compiler to generate code to make an I/O pin 
either input or output every time it is used. On the 5X processors this 
requires one byte of RAM for every port set to standard I/O.
Standard_io is the default I/O method for all ports."

#use fast_io (port):

"Affects how the compiler will generate code for input and output 
instructions that follow. This directive takes effect until another #use 
xxxx_IO directive is encountered. The fast method of doing I/O will 
cause the compiler to perform I/O without programming of the direction 
register. The user must ensure the direction register is set correctly 
via set_tris_X()."

Bitte post mal Dein komplettes Programm als Anhang und ich werde Deinen 
Code am Wochenende bei mir mal ausprobieren. Muss nur mal sehen ob ich 
einen LC04 habe. Welchen PIC verwendest Du? Bei mir war es ein 18F8722.

Thomas:
"2. Für die I2C Schnitstelle gibt es die Wahl für "SLOW" oder "FAST"
Modus.
Sollte ich eine dieser Einstellung bevorzugen? Der Compiler generiert
mir etweder #use i2c(Master,Fast (oder Slow),sda=PIN_C4,scl=PIN_C3)."

Sollte beim 24LC04 nichts ausmachen. Bis 400 KHZ sollte der LC04 keine 
Mucken machen.

Uebriegens, solange nicht "FORCE_HW" gesetzt ist, arbeitet das I2C 
Interface in software mode. Also koennen alle anderen Port Pins 
verwendet werden. "FORCE_HW" funktioniert nur bei PICS mit Hardware 
SPI/I2C interface.

Im Allgemeinen funktioniert I2C mit CCS auf Anhieb solange man mit den 
Adressen Bits aufpasst. Wenn es Dir hilft, bei meinen Projekten habe ich 
bis jetzt die folgenden I2C ICs erfolgreich eingesetzt:

AT24AT1024
AT24LC02
TMP101
LM75
PCA9554/7
PCF8574
TPIC2810
LTC1669
DS1307
CMP03 Compass

Bitte auf keinem Fall aufgeben, da Dein Problem mit Sicherheit zu loesen 
ist. Da steckt irgendwo noch ein Hund drin; -)

Gruss,
Gerhard

von T. D. (thoms)


Lesenswert?

Hallo Gerhard,

danke für Deine Antwort... trotz der 8 Stunden Verschiebung kommen Deine 
Antworten für mich prompt genug ;o) Und wie Du schon sagtest, bloß nicht 
aufgeben.. da steckt irgendwo der Hund drin!

Freu mich gerad wie ein kleines Kind - denn es funktioniert! Wie schon 
gesagt - vielleicht muss mich nur jemand mit der Nase drauf schupsen.

Habe noch einmal alle gesetzten #defines, #use, #fuses überprüft und am 
Ende wars das fast_IO(port). Ich war schon so durch den Wind, dass ich 
es gar nicht ausprobiert hatte und einfach schlichtweg vergessen habe.

Nochmal recht herzlichen Dank an Dich und schon mal ein schönes 
Wochenende für Dich.

Beste Grüsse Thomas!

von Gerhard. (Gast)


Lesenswert?

Hallo Thomas,

danke fuer Deine gute Nachricht. Oft steht man eine Zeitlang vor einer 
hohen Wand und man kommt wegen einer unscheinbaren Kleinigkeit nicht 
weiter bis dann der "Breakthrough" kommt.

Uebrigens, es gibt noch eine gemeine Falle bei 18FXXXX PICS:

Es nicht genug nur das Tris Register zu konfigurieren. Du musst auch 
immer aufpassen dass das ADCON1 register welches die Analogeinganenge 
spezifiert nicht zur gleichen Zeit einen bestimmten pin der als 
digitaler Port eingesetzt werden sollte, auch als analog konfiguriert 
ist. Das ADCON(1) (A/D Control Register) register hat ueber den 
Digitalen Port-IO Vorrang.

Ich will Dir das nur sagen weil mir das schon mal passiert ist dass ein 
Digitaler Port Pin nicht funktionierte weil das ADCON Register falsch 
gesetzt war. Da kann man lange Fehler suchen wenn man nich daran denkt 
oder diesens Sachverhalt vergessen hat.

Dir auch ein schoenes Wochenende. Bei mir fing der Tag gerade an und das 
Wochenende ist noch etliche Stunden weit weg; -(

Gruss,
Gerhard

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.