Forum: Mikrocontroller und Digitale Elektronik Kleines Timingproblem beim DS1820


von Gast (Gast)


Angehängte Dateien:

Lesenswert?

Servus!

Irgendwo habe ich aber noch ein kleines Problem beim empfangen der Bits
vom DS1820. Leider kann ich immer nur Mist auslesen -> 11100000 usw.

Convert wurde gesendet, genau auch der Befehl zum Temperatur messen.
Aber irgendwie stimmt da was mit den Timings noch nicht so ganz.
Wahrscheinlich zwischen letzten Befehl senden und auslesen. Oder auch
beim Empfang der einzelnen Bits!? Entweder zulange oder zu kurz
gewartet. Ich weiß es nicht.

Das Datenblatt ist mir dabei auch nicht sehr hilfreich, zumindest finde
ich es einfach nicht genau. Im Forum hier, finden sich auch immer wieder
unterschiedliche Zeiten.

Wenn ich zwischen den einzelnen Bits empfangen ein _delay_us(80); drin
habe, kommt auch ein ziemlich wirrer Code raus, egal bei welchem Byte. 
Wenn ich es weg lasse, kommt anderer sinnloser Code raus.
Das 1. Byte soll laut Datenblatt ja nur 0x00 oder 0xFF sein, und sonst
nichts dazwischen.

Das Resetsignal wird korrekt empfangen, er ist also richtig
eingebaut und antwortet auch. Genauso empfange ich ja auch 1er und 0er
nur falsch.

Ich hatte das ganze gestern schon mal gepostet, aber irgendwie finde 
ich, passt es so gar nicht mehr zum Ausgangsproblem. Siehe-> 
Beitrag "Code gibt immer den gleichen Binärcode aus"

von Timmo H. (masterfx)


Lesenswert?

Bei mir sah das so aus:
1
static const int   A = 6 ,
2
      B = 64,
3
      C = 60,
4
      D = 10,
5
      E = 9,
6
      F = 55,
7
      G = 0,
8
      H = 480,
9
      I = 70,
10
      J = 410;
11
12
13
14
void w1_wr_byte(char byte byte){
15
  unsigned char i;
16
  for(i = 0; i < 8; i++){
17
    w1_write_bit(byte & 0x01);
18
    byte >>= 1; 
19
  }
20
  
21
}
22
23
24
unsigned char w1_rd_byte(){
25
  unsigned char i, result=0;
26
  for (i = 0; i < 8; i++){
27
    result >>= 1;
28
    if (w1_read_bit())
29
      result |= 0x80;
30
  }
31
  return result;
32
}
33
34
void w1_write_bit(unsigned char bit){
35
  unsigned char  result;
36
  if(bit){
37
    PORTT &= ~0x01;
38
    DDRT |= 0x01;
39
    delay_us(A);
40
    DDRT &= ~0x01;
41
    delay_us(B);
42
  }
43
  else{
44
    DDRT |= 0x01;
45
    delay_us(C);
46
    DDRT &= ~0x01;
47
    delay_us(D);
48
  }
49
}
50
51
unsigned char w1_read_bit(unsigned char bus){
52
  BT_UBYTE result;
53
  
54
  PORTT &= ~0x01;
55
  DDRT |= 0x01;
56
  delay_us(A);
57
  DDRT &= ~0x01;
58
  delay_us(E);
59
  result = PORTT & 0x01;
60
  delay_us(F);
61
62
  return result;
63
64
}
So hatte das bei mir glaub ich geklappt (war auf einem HC12). 
Selektierst du jedes Device per ID?
Ansonsten hier nochmal in der Appnote gucken: 
http://www.maxim-ic.com/appnotes.cfm/appnote_number/126

von Gast (Gast)


Lesenswert?

> Selektierst du jedes Device per ID?
Nein, es ist nur einer angeschlossen.

Wie lange wartest du vom letzten Befehl(0xBE) senden, bis zum auslesen 
der jeweiligen Bytes, und zwischen jedem Byte?

von (prx) A. K. (prx)


Lesenswert?

@Gast: Ich habe mir mal exemplarisch das Senden angesehen.

Der ganze Bitzyklus sollte normalerweise gut 60µs dauern, plus Erholzeit 
der Leitung. Du ziehst aber bei 0 für 90µs runter. Auch die 7µs sind 
etwas hoch, zumal die inhärente Verzögerung des Steuercodes drum herum 
auch mitzählt. Zum "Ausgleich" ist der Slot dann bei "1" zu kurz, nur 
rund 30µs.

Nach der 0-Phase sollte zudem explizit etwas Luft gelassen werden, damit 
der Widerstand die Leitung hochziehen kann - was bei längerer Leitung 
ein paar µs dauert. Dieser Aspekt fehlt übrigens auch in Peter 
Danneggers Code.

Üblicherweise kombiniert man übrigens Senden und Empfangen in einer 
Routine, weil es fast der gleiche Vorgang ist. Für den Empfang "sendet" 
man dann 0xFF.

von (prx) A. K. (prx)


Lesenswert?

Weiter im Text: Hier wohl unkritisch aber trotzdem falsch: wire_low() 
zieht u.U. kurz hoch bevor es runter geht. Generell wenn bei AVRs Open 
Drain realisiert werden soll: erst Ausgangsregister auf 0 setzen, dann 
auf Ausgang stellen, keinesfalls andersrum.

von Gast (Gast)


Lesenswert?

Soweit mal Thx. Ich habe den Code mal so geändert wie beschrieben.

Aber die Frage habe ich von oben noch:
>Wie lange wartest man vom letzten Befehl(0xBE) senden, bis zum auslesen
>der jeweiligen Bytes, und zwischen jedem Byte?
1
senden (0xBE); //Temp messen
2
_delay_us(?); // Wartezeit nach dem senden (bisher 50)
3
int wert1 = empfang();
4
//_delay_us(?); // Zeit zum 2. Byte empfangen (bisher nicht vorhanden)
5
int wert2 = empfang();

Diese beiden Delays stimmen wahrscheinlich noch nicht, und besonders die 
sind mir nicht ganz klar.

von (prx) A. K. (prx)


Lesenswert?

Nach dem Start der Messung ist Geduld angesagt (750ms). Zwischen den 
Bytes ist jedoch kein zusätzliches Delay nötig.

von (prx) A. K. (prx)


Lesenswert?

Zu empfang():
- Es wird zu früh gesampelt. Empfohlen wird ja knapp unter 15µs
- Auch hier den 60µs Zyklus fahren, nicht warten bis inaktiv.
Und wenn du das hast, wirst du sehen, dass es einfacher ist, beim Senden 
auf Verdacht nach knapp 15µs zu sampeln und als Ergebnis zu 
akkumulieren. Also die selbe Routine für beides verwenden.

Hab nochmal reingesehen. Die 90µs sind durchaus ok, vor allem wenn der 
eigene Takt arg ungenau ist. Aber unter 60µs darf der Bitzyklus nicht 
liegen, egal ob 1 oder 0 oder Lesen oder Schreiben.

von Gast (Gast)


Lesenswert?

Der Takt ist ziemlich genau, von einem externen Quarz mit 12 MHz.

Soweit empfange ich jetzt die korrekte Temperatur. :-) Thx dafür an 
alle.

Aber das 2. Byte empfange ich noch nicht ganz korrekt. Meist sowas wie 
11100000 oder 00001111. Eigentlich sollte das doch 00000000 oder 
11111111 sein, oder?

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.