Forum: Mikrocontroller und Digitale Elektronik Böses One-Wire device


von Joachim .. (joachim_01)


Lesenswert?

Freunde der sparsamen Portbreite,
ich hab hiern OneWire EEPROM DS2430A (32Byte x 8), der sich prima 
beschreiben lässt - aber stets nur an der falschen Stelle. Ich habe 
immer ein Adressoffset von 2.
1
if (!OneWire__reset()) return errorcode = 0;  // reset pulse (480µs to 960µs)
2
3
OneWire__write(0xCC, 0);      // Skip ROM
4
  
5
OneWire__write(0x0F, 0);      // Write Scratchpad
6
//OneWire__write((Byte)startaddr, 0);    // start addr  
7
OneWire__write(0, 0);         // start addr  
8
//write in EEPROM
9
OneWire__reset();             // reset pulse (480µs to 960µs)
10
  
11
OneWire__write(0xCC, 0);      // Skip ROM
12
OneWire__write(0x55, 0);      // Copy Scratchpad to EEPROM
13
OneWire__write(0xA5, 1);      // A5h Validation key
14
delay_ms(10);          // energize this OneWire parasite for 10ms. Yeah!



Lesen tu ich mit:
1
uint32_t readOneWireEEPROM (void) {
2
  uint32_t errorcode;
3
  
4
  if (!OneWire__reset()) return errorcode = 0;    // reset pulse (480µs to 960µs)
5
  OneWire__write(0xCC, 0);        // Skip ROM
6
  OneWire__write(0xF0, 0);        // Issue “Read Memory” command
7
8
  //move 32 bytes
9
  for (uint32_t i = 0; i < 32; i++ ) {
10
            eepromData[i] = OneWire__read();
11
            //eepromData[i] = i + 0x80;    //DEBUG                
12
  }
13
  return 1; //success
14
}





Das ist mein Tester:
1
//eepromData[] ist global definiert
2
3
// read EEPROM
4
checkForError = readOneWireEEPROM();
5
if (!checkForError) {
6
  printf("ERROR while read. Halt.");
7
  while(1);
8
}
9
int i;
10
//now lets read 32 bytes
11
for (i = 0; i < 32; i++ ) {
12
    if (i > 0 && !(i % 8)) printf("\r\n"); //only 8 Bytes in a line  
13
    printf("%02X: %02X\t\t", i, eepromData[i]);
14
}
OneWire EEPROM DS2430A test
00: FF    01: FF    02: 33    03: FF    04: FF    05: FF    06: FF 
07: 11
08: FF    09: FF    0A: FF    0B: FF    0C: FF    0D: FF    0E: FF 
0F: FF
10: FF    11: FF    12: FF    13: FF    14: FF    15: FF    16: FF 
17: FF
18: FF    19: FF    1A: FF    1B: FF    1C: FF    1D: 7F    1E: FF 
1F: FF


02: 33 <- erstes Byte



jetzt sollte eigentlich das erste Byte an Adresse 0 geschrieben werden, 
er steht aber an Adresse 2, d.h. alle getesteten Bytes die ich bisher 
schrieb waren um zwei nach oben versetzt. Was ist da los? Auch im 
Datenblatt hab ich nix darüber finden können.

von Ich (Gast)


Lesenswert?

Zeig doch bitte den kompletten Code (Dateianhang) her, insbesondere das 
tatsächliche Beschreiben des EEPROMs und die Funktion OneWire__Write().

von Joachim .. (joachim_01)


Angehängte Dateien:

Lesenswert?

Die beiden Dateien waren für den Arduino DUE in C++ geschrieben, ich 
habe sie auf C umgeschrieben.

Ich hab 32 Bytes mit dem Inhalt 0x40 + 0..1F ins EEPROM geschrieben, der 
Effekt ist immer der gleiche: Das Byte an Position 00 bleibt auf 0xFF 
stehen (nicht beschreibbar???), alle anderen lassen sich mit einem 
ungewollten Adressoffset von 2 beschreiben. Auch der Rollover bei 
Adresse 1F -> 00 passt. Ich dachte zuerst, es läge vielleicht an einem 
Fehler beim zurücklesen und auswerten, das habe ich jetzt geändert - der 
Effekt ist der gleiche.
1
// schnipp ----------------------------------------
2
3
  printf("\rOneWire EEPROM DS2430A test\r\n");
4
  uint32_t checkForError;
5
  int i;
6
  OneWire__init();
7
  if (!( pio_get(PIN_PUSHBUTTON_1_PIO, PIO_INPUT, PIN_PUSHBUTTON_1_MASK) )) {  //write if button pressed
8
          gpio_set_pin_high(LED0_GPIO);
9
          uint32_t eepromoffset = 0x00;          
10
          int eepromNumOfBytes = 32;
11
          for (i = 0; i < 32; i++) {eepromData[i] = 0x40 + i;}
12
          checkForError = writeInOneWireEEPROM(eepromoffset, eepromNumOfBytes);
13
          if (!checkForError) {
14
                printf("ERROR while write. Halt.");
15
                while(1);
16
          } 
17
  }
18
  else gpio_set_pin_low(LED0_GPIO);
19
  
20
21
  // read EEPROM
22
  checkForError = readOneWireEEPROM();
23
  if (!checkForError) {
24
    printf("ERROR while read. Halt.");
25
    while(1);
26
  }
27
  //now lets read 32 bytes
28
  for (i = 0; i < 32; i++ ) {
29
      if (i > 0 && !(i % 8)) printf("\r\n"); //8 Bytes in a line  
30
      printf("%02X: %02X\t\t", i, eepromData[i]);    
31
  }
32
    
33
// schnapp ----------------------------------------

Das Ergebnis:
00: FF    01: 5F    02: 40    03: 41    04: 42    05: 43    06: 44 
07: 45
08: 46    09: 47    0A: 48    0B: 49    0C: 4A    0D: 4B    0E: 4C 
0F: 4D
10: 4E    11: 4F    12: 50    13: 51    14: 52    15: 53    16: 54 
17: 55
18: 56    19: 57    1A: 58    1B: 59    1C: 5A    1D: 5B    1E: 5C 
1F: 5D

von nof (Gast)


Lesenswert?

Die Länge beim Schreiben muss uint32_t sein:
uint32_t writeInOneWireEEPROM ( uint32_t startaddr, uint32_t len)

Du hast es als int deklariert: int eepromNumOfBytes = 32;

von Joachim .. (joachim_01)


Lesenswert?

>uint32_t writeInOneWireEEPROM ( uint32_t startaddr, uint32_t len)
Yo... hab ich geändert und ausprobiert. Ändert nix am eigentlichen 
Problem.

Ich hatte anfangs mit der delay-Routine Schwierigkeiten, die 
mitgelieferte lib verursachte falsche Zeiten. Das hab ich jetzt soweit 
repariert daß ich das Device benutzen kann, wenn auch die Zeiten immer 
noch nicht sauber sind.
Interessant ist halt, daß alles bis auf die Teilfunktion "MASTER Tx DATA 
BYTE TO SCRATCHPAD ADDRESS" alles funktioniert. Und die ist Chip hart 
verdrahtet.

Ich hab noch nen Thermometer DS18B20, der funktioniert in allen 
Teilfunktionen ohne Fehler.

von Conny G. (conny_g)


Lesenswert?

Hallo Joachim,

habe mir interessehalber mal das Datasheet des EEPROM angesehen. Die 
Befehle stimmen wohl. Es werden auch nur 8 Bit übertragen, das passt 
auch.

Angenommen die Übermittlung der Startaddress funktioniert, dann müsste 
2x ein Inkrement des Address Pointers stattfinden, nur warum?
Alternativ funktioniert die Übertragung der Startaddress nicht richtig 
und es wird als 2 interpretiert.

Könnte das mit dem Timing etwas zu tun haben?
Du hast ja an ein paar Stellen das Timing angepasst, wie man an den 
Kommentaren sehen kann, das behebt aber das Problem nicht.
Vielleicht wäre es besser das Timing global zu fixen, entweder einen 
Oszillator verwenden oder nachsehen, ob das delay mit FCPU funktioniert 
und dann das FCPU um die paar Prozent anders setzen, dann verschiebt 
sich die Rechnung für das Delay minimal und es könnte passen.
Ansonsten kann man den internen Oszillator eines AVR auch trimmen, da 
gibt's ein Register für, das habe ich aber noch nicht gemacht.

Vg,
Conny

von Joachim .. (joachim_01)


Lesenswert?

Könnte das mit dem Timing etwas zu tun haben?
Yep, mittlerweile glaub ichs auch -  aber ich verwende keinen AVR 
sondern einen SAM3X8 Cortex M3 von Atmel. Die delay Routinen sind völlig 
anders als für die AVRs und scheint von Atmel von einem anderen M3 
angepasst worden zu sein. Vielleicht schreib' ich was neues und benutze 
den M3 Core Timer.

Merkwürdig ist halt auch, daß der Chip auf der EEPROM-Adresse 00 nicht 
beschreibbar ist. Selbst wenn der Adresszeiger "verrutscht" sollte das 
aber der Fall sein. Andererseits glaube ich nicht, daß ich mich irgendwo 
außerhalb der EEPROM-Funktionalität aufhalte (zB Seriennummer lesen, 
64bit Application Register), da kämen sicherlich viele Fehler.
Alles sehr seltsam.

von Conny G. (conny_g)


Lesenswert?

Ach, stimmt, das 5E wurde "verworfen", das hatte ich vorher gar nicht 
wahrgenommen.
Ja, das ist seltsam.
Aber auf jeden Fall erstmal das Timing perfektionieren, wer weiss, was 
es für Nebeneffekte hat.

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.