INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.

Antwort schreiben 
 
Themabewertung:
  • 0 Bewertungen - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
FRAM am Arduino
10.09.2016, 18:14
Beitrag #9
RE: FRAM am Arduino
Da würde ich Bitklopfer mal recht geben.
Wenn du glaubst auf 0x200 zu schreiben wird vermutlich auf 0x000 geschrieben.
Der gleiche Fehler passiert dann beim Lesen und deshalb sieht das Ergebnis augenscheinlich gut aus.

Test:
1. schreib "ABCDEF" auf 0x1FE
2. schreib "123456" auf 0x000
3. lese 6 Byte ab Adresse 0x1FE (ergibt vermutlich "AB1234"
4. berichte über das Ergebnis.

Gruß
Arne

ExclamationMit zunehmender Anzahl qualifizierter Informationen bei einer Problemstellung, erhöht sich zwangsläufig die Gefahr auf eine zielführende Antwort.Exclamation
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
10.09.2016, 19:17 (Dieser Beitrag wurde zuletzt bearbeitet: 10.09.2016 19:22 von Tommy56.)
Beitrag #10
RE: FRAM am Arduino
(10.09.2016 18:14)ardu_arne schrieb:  Test:
1. schreib "ABCDEF" auf 0x1FE
2. schreib "123456" auf 0x000
3. lese 6 Byte ab Adresse 0x1FE (ergibt vermutlich "AB1234"
4. berichte über das Ergebnis.

Bei dem Kleinen liegen die Pagegrenzen bei 0xFF, 0x1FF usw. Der hat nur ein Byte als Adresse pro Page.

Code:
char text1[] = "1234567890";
char text2[] = "abcdefghij";

  fRamWrite(0xFB,text1);
  fRamWrite(0x1FB,text1);
  fRamWrite(0x0, text2);

  fRamRead(0xFB,buffer);
  Serial.println(buffer);  // Ergibt: 0123456789
  fRamRead(0x1FB,buffer);
  Serial.println(buffer);  // Ergibt: 0123456789

Dump:
FRAM Dump von  0000 bis  022F
0000 61 62 63 64 65 66 67 68 69 6A 00 00 00 00 00 00   abcdefghij......
0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
00A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
00B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
00C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
00D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
00E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
00F0 00 00 00 00 00 00 00 00 00 00 00 31 32 33 34 35   ...........12345
0100 36 37 38 39 30 00 00 00 00 00 00 00 00 00 00 00   67890...........
0110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
01A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
01B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
01C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
01D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
01E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
01F0 00 00 00 00 00 00 00 00 00 00 00 31 32 33 34 35   ...........12345
0200 36 37 38 39 30 00 00 00 00 00 00 00 00 00 00 00   67890...........
0210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................

Es sieht also danach aus, als würde es funktionieren.
Der Code kommt im nächsten Posting.

Gruß Tommy

Hallo zusammen,

hier der Code. Die Funktionen musste ich eine Headerdatei auslagern, da er mir in der ino die Templates angemeckert hat.

Den Dump kann man mit PStrings evtl. schöner schreiben, die muss ich mir aber erst anschauen.

fRam.h
Code:
// Mit Anleihen bei rkuehle (Template), Rob Tillaart (I2C_EEPROM library), Ardu_Arne (FRAM) und Arduino core (HEX)
// Handling für FRAM Bausteine 16 KBit (1 Adressbyte) und 64KBit (2 Adressbytes)
#include <Arduino.h>
#include <Wire.h>

// 1 für 16 k, 2 für 64 k
#define ADRESS_BYTES 1
#define TWI_LENGTH BUFFER_LENGTH - ADRESS_BYTES

// I2C-(Basis)Adresse (Das wird dann die 0xC, die im Datenblatt steht)
#define F_RAM 0x50

// FRAM schreiben - Variable, anzahl Bytes, Adresse im FRAM
void F_RAM_write (byte* wert, int numbytes, uint16_t framAddr) {
  int devAdr,rc;
  
  TWBR = 12;  // 400 kHz (maximum)
  // Adressierungsart 1 -> 3 Bit in Adresse
  if (ADRESS_BYTES == 1) {
    // 16 K
    devAdr = F_RAM | framAddr >> 8;
    Wire.beginTransmission(devAdr);
  }
  else {  
    // bei 64 K alles als Adresse
    Wire.beginTransmission(F_RAM);    
    Wire.write(framAddr >> 8);  
  }  
  Wire.write(framAddr & 0xFF);
  for (byte i = 0; i < numbytes; i++) Wire.write(wert[i]);
  rc = Wire.endTransmission();
  //Serial.print("rc: ");Serial.println(rc);
  TWBR = 72;  // 100 kHz (default)
}

// FRAM lesen - Variable, anzahl Bytes, Adresse im FRAM
void F_RAM_read (byte* wert, int numbytes, uint16_t framAddr) {
  int devAdr,rc;
  TWBR = 12;  // 400 kHz (maximum)
  // Adressierungsart 1 -> 3 Bit in Adresse
  if (ADRESS_BYTES == 1) {
    // 16 K
    devAdr = F_RAM | framAddr >> 8;
    Wire.beginTransmission(devAdr);
  }
  else {  
    // bei 64 K alles als Adresse
    Wire.beginTransmission(F_RAM);    
    Wire.write(framAddr >> 8);  
  }  
  Wire.write(framAddr & 0xFF);
  Wire.endTransmission();
  Wire.requestFrom(devAdr, numbytes);
  for (byte i = 0; i < numbytes; i++) {
    wert[i] = Wire.read();
    //Serial.println(wert[i],HEX);
  }
  TWBR = 72;  // 100 kHz (default)
}

// Schreibt beliebige Werte (auch Arrays beliebiger Typen) in den FRAM
template <class T> int fRamWrite(uint16_t framAddr, const T& wert) {
    byte* p = (byte*)(void*)&wert;
    int16_t len, cnt, orig;
    len = sizeof(wert);
    orig = len;
    // Solange Bytes zu senden sind
    while (len > 0) {
      cnt = len;
      // Wenn  länger als TWI-Buffer - Adresslänge, dann begrenzen
      if (cnt > TWI_LENGTH) cnt = TWI_LENGTH;
      // Schreiben
      F_RAM_write (p, cnt, framAddr);
      // Restbytes berechnen
      len -= cnt;
      // neue FRAM-Adresse
      framAddr += cnt;
      // neue Quelladresse
      p += cnt;
    }
    return orig;
}

// liest beliebige Werte aus dem FRAM . Die Länge wird von der Zielvariablen bestimmt
// optionaler Parameter laenge wird nur berücksichtigt, wenn er kleiner, als die Länge der Variablen ist

template <class T> int fRamRead(uint16_t framAddr, const T& wert, int laenge = 0) {
    byte* p = (byte*)(void*)&wert;
    int16_t len, cnt, orig;
    len = sizeof(wert);
    // Wunschlänge gesetzt und passt in Variable rein
    if ((laenge > 0) && (laenge < len)) len = laenge;
    orig = len;
    // Solange Bytes zu holen sind
    while (len > 0) {
      cnt = len;
      // Wenn  länger als TWI-Buffer - Adresslänge, dann begrenzen
      if (cnt > TWI_LENGTH) cnt = TWI_LENGTH;
      // Schreiben
      F_RAM_read (p, cnt, framAddr);
      // Restbytes berechnen
      len -= cnt;
      // neue FRAM-Adresse
      framAddr += cnt;
      // neue Quelladresse
      p += cnt;
    }
    return orig;
}

// Hilfsfunktion für Hexdarstellung
// Puffer, Wert, Stellenzahl (2 oder 4), Ein Blank wird voran gestellt
char *fillHex(char *buf, uint16_t val, uint8_t len) {
  uint16_t m;
  byte str,t;
  
  if (len == 4) {
    //Adresse
    str = 5;
    buf[0] = ' ';
    for(byte i= 1; i < 5;i++) buf[i] = '0';
  }
  else {
    // Byte
    str = 3;
    buf[0] = ' ';
    buf[1] = '0';
  }
  buf[str] = '\0';
  do {
    m = val;
    val /= 16;
    char c = m - 16 * val;
    buf[--str] = c < 10 ? c + '0' : c + 'A' - 10;
  } while(val);
  return buf;
}  

// Anzeige des Fram im angegebenen Bereich Hex und als (druckbares) Zeichen
void dumpFram(uint16_t von, uint16_t bis) {
  // Hexformatierer
  char buf[6];
  //Lesepuffer  
  byte readBuffer[16];
  // Zeichenpuffer
  char zbuffer[17];
  uint16_t start;
  uint8_t len = 16;
  start = von;
  
  Serial.print("FRAM Dump von "); Serial.print(fillHex(buf, von,4));
  Serial.print(" bis "); Serial.println(fillHex(buf, bis,4));
  while (start < bis) {
    memset(zbuffer,0,17); // leeren
    if ((bis - start) < 16) len = bis - start + 1;
    fRamRead(start, readBuffer, len);
    Serial.print(fillHex(buf,start,4)); // Adresse
    for (byte i=0; i < len; i++) {
      Serial.print(fillHex(buf,readBuffer[i],2));
      if ((readBuffer[i] < 32) || (readBuffer[i] > 126)) zbuffer[i] = '.';
      else zbuffer[i] = readBuffer[i];  // druckbare Zeichen
    }
    // Wenn letzte Zeile < 16, dann auffüllen
    if (len < 16) {
      for (byte i=0; i < (16-len); i++) Serial.print("   ");
    }
    Serial.print("   "); Serial.println(zbuffer);
    start += 16;
  }
}

//Füllen des Fram mit einem bestimmten Zeichen in einem Bereich
void fillFram(uint16_t von, uint16_t bis, uint8_t val) {
  // Hexformatierer
  char buf[6];
  byte writeBuffer[16];
  uint16_t start;
  uint8_t len = 16;
  start = von;
  memset(writeBuffer,val,16);
  Serial.print("FRAM schreiben von "); Serial.print(fillHex(buf, von,4));
  Serial.print(" bis "); Serial.print(fillHex(buf, bis,4));
  Serial.print(" mit "); Serial.println(fillHex(buf, val,2));
  len = 0;
  while (start < bis) {
    if ((bis - start) < 16) {
      len = bis - start + 1;
      F_RAM_write (writeBuffer, len, start);
    }
    else fRamWrite(start, writeBuffer);
    start += 16;
  }
}

Das Testprogramm fram2.ino
Code:
// fram2
#include <Wire.h>
#include "fRam.h"

char text[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-*/,;.:";
char buffer[45]; // Länge wie text

char text1[] = "1234567890";
char text2[] = "abcdefghij";

float f= 33.44;

typedef struct {
  int i1;
  uint32_t aktMillis;
} teststruct;

teststruct tarr[10];


void setup() {
byte pos;
  Serial.begin(115200);
  Serial.println("Start");
  Wire.begin();
  // Schreib- und Leseteil können auch wechselseitig auskommentiert werden
// evtl. aufräumen  
// fillFram(0, 0x2FF,0);
  
  // Schreibteil
  fRamWrite(0xFB,text1);
  fRamWrite(0x1FB,text2);
  fRamWrite(0x120, text);
  fRamWrite(0x220, f);
  for(int i=0; i < 10; i++) {
    tarr[i].i1 = i;
    tarr[i].aktMillis = millis();
    delay(3); // sonst ist das alles in der gleichen Millisekunde
  }
  fRamWrite(0x230, tarr);

  // Leseteil
  // nur die ersten 10 Zeichen
  pos = fRamRead(0x120,buffer,10);
  Serial.println(pos);
  // das muss man dann selbst machen
  buffer[pos] = '\0';
  Serial.println(buffer);
  
  // alles
  fRamRead(0x120,buffer);
  Serial.println(buffer);
  // float
  f = 0.0;
  fRamRead(0x220,f);
  Serial.println(f);
  
  // Array von Struct
  fRamRead(0x230,tarr);
  for(int i=0;i<10;i++) {
    Serial.print(tarr[i].i1);Serial.print("  ");Serial.println(tarr[i].aktMillis);
  }
  
  // Hilfsfunktionen
  dumpFram(0, 0x2FF);
}

void loop() {
  
}

Wenn ihr die Stelle findet, wo ich an den Pagegrenzen falsch lese/schreibe, freue ich mich.

Gruß Tommy
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
11.09.2016, 12:38
Beitrag #11
RE: FRAM am Arduino
Hallo Tommy,

du hast dich jetzt sehr tief in die Sache eingearbeitet.
Ich will deinen Code bei Gelegenheit mal testen und dann berichten.
Derzeit habe ich aber noch viele andere Dinge hier liegen die dringend erledigt werden sollten. Hab also bitte ein paar Tage Geduld.

Gruß
Arne

ExclamationMit zunehmender Anzahl qualifizierter Informationen bei einer Problemstellung, erhöht sich zwangsläufig die Gefahr auf eine zielführende Antwort.Exclamation
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
11.09.2016, 13:56
Beitrag #12
RE: FRAM am Arduino
(11.09.2016 12:38)ardu_arne schrieb:  Ich will deinen Code bei Gelegenheit mal testen und dann berichten.
Derzeit habe ich aber noch viele andere Dinge hier liegen die dringend erledigt werden sollten. Hab also bitte ein paar Tage Geduld.

Hallo Arne,

keine Hektik, die FRAMS laufen nicht weg und ich habe akut auch kein Projekt damit vor.
Es hat mich nur interessiert, weil ich die mal testen wollte.
Aber wie das so ist, wenn man mal mit dem Programmieren anfängt, dann kommt eine Idee zur anderen und es wächst.
Auf alle Fälle scheinen die Dinger sauschnell zu sein. Das langsamste war wohl Serial.print.

Gruß Tommy
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
21.09.2016, 12:48
Beitrag #13
RE: FRAM am Arduino
Hallo Tommy,

was du da an Code zusammen gestrickt hast funktioniert nach auch nach meinen kurzen Tests fehlerfrei. Smile Das kann man so verwenden.

Es ist auch so, dass die Serial.print() Ausgaben die meiste Zeit beanspruchen. Die FRAMs selbst sind sauschnell. Ich glaube in der Beschreibung auch gelesen zu haben dass der I²C Bus die Speicher ausbremst weil die in Wirklichkeit noch schneller könnten. Bei den SPI Versionen sind Timing-Parameter angegeben die um den Faktor 2 bis 5 kürzer sind als bei I²C. Die Angaben beziehen sich aber immer nur auf das serielle Interface und nicht auf die RAM-Zelle selbst. Das Interface (I²C oder SPI) ist also das Nadelöhr. Jedenfalls sind die FRAMs um einiges schneller als vergleichbare EEPROMs.

Ich hatte noch nach Möglichkeiten gesucht um die Größe des angeschlossenen FRAMs vom Arduino auslesen zu lassen, aber nichts gefunden. Damit könnte man verhindern dass über das Speicherende hinaus geschrieben wird. Wenn das passiert wird mit den o.g. Routinen der Speicheranfang überschrieben.
Pagegrenzen sind kein Problem sofern es beim verwendeten FRAM-Typ welche gibt.
Es bleibt also dem Anwender überlassen dafür zu sorgen dass man den zulässigen Bereich nicht überschreitet. Vielleicht könnte man z.B. ein:
Code:
#define fRamMaxAdress 0x7FF
einfügen und abfragen. Die Gefahr besteht wenn man z.B. ein char text[] ="ABC........"; kurz vor das Speicherende schreiben will.

Gruß
Arne

ExclamationMit zunehmender Anzahl qualifizierter Informationen bei einer Problemstellung, erhöht sich zwangsläufig die Gefahr auf eine zielführende Antwort.Exclamation
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
21.09.2016, 13:00 (Dieser Beitrag wurde zuletzt bearbeitet: 21.09.2016 13:02 von AlphaRay.)
Beitrag #14
RE: FRAM am Arduino
Könntest doch eine Routinge für die Initialisierung machen:

- am Anfgang des Speichers ein unverkennbare Zeichen schreiben
- am theoretischen Ende (8, 16, 32... kb) + 1 Byte mehr was wegschreiben
- die Zeichen am Anfang auslesen -> Zeichen ist geblieben? -> dann in Schleife in größere Bereiche Schreiben, bis dieses überschrieben worden ist => letzter Zugriff = Speichergröße

Oder geht das ggf. ohne zu schreiben? Also erstes Zeichen lesen + das angenoemmene letzte + 1 Byte mehr und dann das letztere der beiden mit dem ersten Zeichen im Speicher vergleichen..?
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
21.09.2016, 13:09
Beitrag #15
RE: FRAM am Arduino
(21.09.2016 13:00)AlphaRay schrieb:  Könntest doch eine Routinge für die Initialisierung machen:

- am Anfgang des Speichers ein unverkennbare Zeichen schreiben
- am theoretischen Ende (8, 16, 32... kb) + 1 Byte mehr was wegschreiben
- die Zeichen am Anfang auslesen -> Zeichen ist geblieben? -> dann in Schleife in größere Bereiche Schreiben, bis dieses überschrieben worden ist => letzter Zugriff = Speichergröße

Oder geht das ggf. ohne zu schreiben? Also erstes Zeichen lesen + das angenoemmene letzte + 1 Byte mehr und dann das letztere der beiden mit dem ersten Zeichen im Speicher vergleichen..?

Danke, das Ergebnis haben wir in Posting #10 beschrieben.

Gruß Tommy
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
29.10.2016, 14:29 (Dieser Beitrag wurde zuletzt bearbeitet: 29.10.2016 14:33 von ardu_arne.)
Beitrag #16
RE: FRAM am Arduino
Hallo,
bei dem Test in #13 hatte ich nur ein FM24C16B verfügbar.
Jetzt habe ich mit einem FM24C64B probiert und dabei
Code:
#define ADRESS_BYTES 2
verwendet.
Aus welchen Gründen auch immer funktioniert es aber nicht. Confused
Die Fehlersuche blieb bisher erfolglos, ich bleibe aber am Ball.
Es wird nach "fillFram(0, 0x7FF, 0x0);" immer FF zurück gelesen, ob das auch schon so geschrieben wird?

Gruß
Arne

ExclamationMit zunehmender Anzahl qualifizierter Informationen bei einer Problemstellung, erhöht sich zwangsläufig die Gefahr auf eine zielführende Antwort.Exclamation
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Möglicherweise verwandte Themen...
Thema: Verfasser Antworten: Ansichten: Letzter Beitrag
  LCD Anzeige für Arduino Mega2560 an Arduino Due? DaniDD 1 803 03.06.2015 12:16
Letzter Beitrag: DaniDD
  Arduino Pin mit anderem Arduino auslesen - geht das? Gelegenheitsbastler 8 3.211 08.05.2015 20:49
Letzter Beitrag: Bitklopfer
Question Arduino Mega ADK oder Arduino Due? Baja-Junky 1 4.159 14.08.2013 21:16
Letzter Beitrag: Bitklopfer

Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste