Forum: Mikrocontroller und Digitale Elektronik DS18B20 Nutzung von fertigem Code


von Fabian S. (ih453)


Lesenswert?

Hallo zusammen,
ich beschäftige mich aktuell zum ersten Mal mit der Verwendung von 
„fertigem und fremden“ C-Code.
Bei meinem LCD hat meine Vorgehensweise (mit der Hilfe von alten Threads 
aus diesem Forum) sehr gut geklappt.
Da dies so gut geklappt hat, wollte ich nun eine Temperaturmessung mit 
Hilfe des DS18B20 von Maxim (Dallas) durchführen.
Auf der Suche nach einem fertigen Code, habe ich den von Goce Boshkovski 
gefunden.
(https://github.com/positronic57/DS18S20Library).
Mit diesem Code habe ich jedoch 2 Probleme und hoffe, dass ihr mir dabei 
helfen könnt.

Zum einen verstehe ich folgende Code-Zeile (zu finden in der ds18s20.c) 
nicht
1
*(pDS18x20->DS18x20_PORT-1) |= _BV(pDS18x20->DS18x20_PIN);
Warum -1?  Warum wird der Klammerausdruck als Pointer dargestellt?

Zum anderen funktioniert dieses Programm leider nicht bei mir, falscher 
Temperaturwert.
Folgendes habe ich bisher getestet:
-  Ich habe die Adressen (READ_ROM, …) überprüft
-       Ich habe die eingstellten Timings überprüft
-  ID und CRC sind laut Programm OK
-  Die ersten beiden Einträge im scratchpad verändern sich leider nicht

woran kann dies liegen?
Laut den Fehlererkennungsmechanismen müssten diverse Fehler doch erkannt 
werden.

Pin/Port wurden natürlich angepasst.

Ausschnitt aus der main:

1
int main(void)
2
{
3
  lcd_init();
4
  TSDS18x20 DS18x20;
5
  TSDS18x20 *pDS18x20 = &DS18x20;
6
  
7
  if (DS18x20_Init(pDS18x20,&PORTC,PC6))
8
  {
9
    lcd_setcursor(1,1);
10
    lcd_string("1Wire NOK");
11
        
12
    return -1;
13
  }
14
  else
15
  {
16
    lcd_setcursor(0,1);
17
    lcd_string("1Wire OK");
18
    
19
    if (pDS18x20->SensorModel==1)
20
    {
21
      lcd_setcursor(0,2);
22
      lcd_string("DS18B20");
23
    }
24
    if (pDS18x20->SensorModel==0)
25
    {
26
      lcd_setcursor(0,2);
27
      lcd_string("DS18S20");
28
    }
29
  }  
30
    
31
  
32
  lcd_clear();
33
  if (DS18x20_MeasureTemperature(pDS18x20))
34
  {
35
    lcd_setcursor(0,2);
36
    lcd_string("TEMP is");
37
    dtostrf(DS18x20_TemperatureValue(pDS18x20),9,4,chr_buffer);
38
    lcd_string(chr_buffer);
39
  }
40
  else
41
    {
42
    lcd_string("ERROR");;
43
    }
44
  // _us_delay(10000);
45
  lcd_clear();
46
  
47
char str_1[20];
48
49
itoa(pDS18x20->scratchpad[0], str_1, 10);
50
  lcd_setcursor(0,1);
51
  lcd_string(str_1);  
52
53
itoa(pDS18x20->scratchpad[1], str_1, 10);
54
  lcd_setcursor(0,2);
55
  lcd_string(str_1); 
56
 
57
 itoa(pDS18x20->scratchpad[4], str_1, 10); 
58
  lcd_setcursor(0,3);
59
  lcd_string(str_1); 
60
  
61
 itoa( pDS18x20->serialNumber[0], str_1, 10); 
62
  lcd_setcursor(0,4);
63
  lcd_string(str_1); 
64
 
65
  while(1)
66
  {
67
  }
68
69
  return 0; 
70
}

Umgebung:
Programmiersoftware ist AVRStudio 5.1
Controller Atmega1284P
Flasher besitzt keine Debugmöglichkeit

Ich hoffe ihr könnt mir hier weiterhelfen.

Danke und Gruß
Fabian

von Stefan F. (Gast)


Lesenswert?

> Warum -1?  Warum wird der Klammerausdruck als Pointer dargestellt?

Solche Fragen solltest du eigentlich an den Autor des Werkes schicken.

Hier wird wohl von der Adresse des PORT Registers 1 subtrahiert, um auf 
das DDR register zu kommen. Eine ganz blöde Methode, denn die 
Reihenfolge der Register ist nicht bei allen AVR Controllern gleich. 
Teilweise passt es auf einem Controller auch nur für bestimmte Register.

von Karl M. (Gast)


Lesenswert?

Hallo,

Fabian S. schrieb:
> Zum einen verstehe ich folgende Code-Zeile (zu finden in der ds18s20.c)
> nicht*(pDS18x20->DS18x20_PORT-1) |= _BV(pDS18x20->DS18x20_PIN);Warum -1?
> Warum wird der Klammerausdruck als Pointer dargestellt?

(pDS18x20->DS18x20_PORT) ist eine Adresse im SRAM, für den Zugriff auf 
ein PORT-Register.
Bei einige Atmel liegt eine Adresse tiefer das zugehörige DDR-Register.

Um dann auf das Byte Register zugreifen zu können, muss man 
*(pDS18x20->DS18x20_PORT) schreiben.

In meinen Programmen definiere ich über eine #define mir ein Alias für 
das PortPin, DdrPin und greife darauf direkt zu.

von Falk B. (falk)


Lesenswert?

Fabian S. schrieb:

> Zum einen verstehe ich folgende Code-Zeile (zu finden in der ds18s20.c)
> nicht*(pDS18x20->DS18x20_PORT-1) |= _BV(pDS18x20->DS18x20_PIN);

über den Pointer pDS18x20, welcher auf ein Struct TSDS18x20 zeig, wird 
der Member DS18x20_PORT dereferenziert (ausgewählt). Dieser Member 
wiederum ist ein Pointer auf ein 8 Bit IO-Register. Dort steht die 
Adresse von PORTA etc. drin, wo der OneWire Bus angeschlossen ist.

>Warum -1?

Ganz einfach. Schau dir mal das Register Summary von deinem AVR an. 
Dorst sieht man, das immer genau vor der Adresse von PORTx DDRx steht.
Ergo. Die Zeile setzte ein Bit in DDRx, siehe Bitmanipulation.

> Warum wird der Klammerausdruck als Pointer dargestellt?

Der Poionter wird dereferenziert. Damit das klappt, muss man die 
Reihenfolge der einzelnen Schritte beachten und ggf. Klammern setzen. Ob 
die hier WIRKLICH nötog sind, weiß ich auf die Schnelle nicht.

https://en.cppreference.com/w/c/language/operator_precedence

Also -> hat mit die allerhöchste Priorität, da sind die Klammern 
entbehrlich.

> Zum anderen funktioniert dieses Programm leider nicht bei mir, falscher
> Temperaturwert.

Welcher denn? Kommt überhautp eine Antwort vom Sensor? Was sagen die 
Rückgabewerte der Funktionen?

Fang mal ganz klein mit OWReset() an, dort muss im Ergfolgsfall ein 
FALSE zurück kommen. Wenn der IC nicht reagiert (oder am falschen Pin 
hängt) ein TRUE. Siehe Fehlersuche.

von Fabian S. (ih453)


Lesenswert?

Hallo,
vielen Dank für eure schnellen und sehr hilfreichen Antworten.

Falk B. schrieb:
> Ganz einfach. Schau dir mal das Register Summary von deinem AVR an.
> Dorst sieht man, das immer genau vor der Adresse von PORTx DDRx steht.
> Ergo. Die Zeile setzte ein Bit in DDRx, siehe Bitmanipulation.

Darauf wäre ich so schnell nicht gekommen.

Nachdem ich mit dem Code von Goce Boshkovski keinen Erfolgt hatte, 
wollte ich ausprobieren, ob der Sensor überhaupt richtig arbeitet.
Um dies auszuprobieren habe ich den Code von Falk gefunden, eingebunden 
und getestet.
Auch hier habe ich (erst) keine sinnvolle Temperatur bekommen.
Alle anderen Überprüfungen (bezogen auf CRC-Check) waren erfolgreich. 
Heute Morgen kam mir die Idee, dass es vermutlich an der 
2-Drahtbeschaltung liegen könnte. Darauf habe ich ein weiteres Mal das 
Datenblatt durchgelesen und siehe da, es gibt bei dieser Beschaltung 
eine Besonderheit, welche Falk auch in seinem C-Code vorgesehen hat. 
Dies habe ich jedoch gestern nicht gesehen/gefunden.
Nun bekomme ich auch eine sinnvolle Temperaturangabe.

Vielen Dank für eure Hilfe und eure Mühe.


Gruß Fabian

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

Fabian S. schrieb:

> Heute Morgen kam mir die Idee, dass es vermutlich an der
> 2-Drahtbeschaltung liegen könnte. Darauf habe ich ein weiteres Mal das
> Datenblatt durchgelesen und siehe da, es gibt bei dieser Beschaltung
> eine Besonderheit, welche Falk auch in seinem C-Code vorgesehen hat.
> Dies habe ich jedoch gestern nicht gesehen/gefunden.
> Nun bekomme ich auch eine sinnvolle Temperaturangabe.

Aha, du meinst parasitäre Stromversorgung. Ja, da muss die Software sehr 
schnell den Bus niederohmig auf HIGH schalten.

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.