Forum: Compiler & IDEs DS1820


von Sascha (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

Ich will einen DS18S20 auslesen... Ich benutze ienen Controller von 
Atmel mit nem Takt von 7,37 MHz.

Die Prozeduren zum Reset, Schreiben und Lesen müssten eigentlich 
stimmen, hab mal ein Oszi dran gehangen... Doch irgendwie haut das noch 
nicht ganz hin...

Könnt ihr mir weiter helfen? Hab meinen C-Code angehängt...

Danke schön!

von Sascha (Gast)


Lesenswert?

Mir würde auch schon reichen, wenn mir jemand sagen kann, wie ich die 
read_bit(); Anweisung gestalten kann???

MfG

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Warum versuchst du, Fahrräder noch einmal zu erfinden?  Die Funktion
delay1() wird auf einem GCC 4.x zu gar nichts mehr evaluieren, weil
sie laut Meinung des Compilers nichts macht.  Die Funktion delay_ms()
verzögert zwar irgendwas, aber was lässt dich annehmen, dass sie
etwas Millisekundenartiges darstellen würde?

Tu dir einen Gefallen, und nimm den Krempel aus <util/delay.h>, dafür
ist er nämlich da.

Ich hatte aus Interesse auch mit mit einem DS18S20 (?) angefangen,
hier das Resultat:
1
/*
2
 * ----------------------------------------------------------------------------
3
 * "THE BEER-WARE LICENSE" (Revision 42):
4
 * <joerg@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
5
 * can do whatever you want with this stuff. If we meet some day, and you think
6
 * this stuff is worth it, you can buy me a beer in return.        Joerg Wunsch
7
 * ----------------------------------------------------------------------------
8
*/
9
#include <stdint.h>
10
#include <stdio.h>
11
#include <stdbool.h>
12
13
#include <avr/io.h>
14
#include <util/crc16.h>
15
16
#include "1wire.h"
17
18
# define F_CPU 8000000UL
19
# include <util/delay.h>
20
# include <avr/io.h>
21
# include <avr/interrupt.h>
22
23
#define concat(a, b) a##b
24
#define indir(a, b) concat(a, b)
25
#define ow_port indir(PORT, OW_PORT)
26
#define ow_pin  indir(PIN, OW_PORT)
27
#define ow_ddr  indir(DDR, OW_PORT)
28
29
static inline void
30
clear_dq(void)
31
{
32
  ow_port &= ~(1 << OW_PIN);
33
  ow_ddr  |= (1 << OW_PIN);
34
}
35
36
static inline void
37
set_dq(void)
38
{
39
  ow_port &= ~(1 << OW_PIN);
40
  ow_ddr  &= ~(1 << OW_PIN);
41
}
42
43
static inline uint8_t
44
get_dq(void)
45
{
46
  return (ow_pin & (1 << OW_PIN)) == 0;
47
}
48
49
bool
50
ow_reset(void)
51
{
52
  bool presence;
53
54
  cli();
55
  clear_dq();
56
  _delay_ms(0.48);
57
  set_dq();
58
  _delay_ms(0.07);
59
  presence = get_dq();
60
  sei();
61
  _delay_ms(0.24);
62
63
  return presence;
64
}
65
66
static uint8_t
67
ow_read_bit(void)
68
{
69
  bool res;
70
71
  cli();
72
  clear_dq();
73
  set_dq();
74
  _delay_us(15);
75
76
  res = get_dq();
77
  sei();
78
  _delay_us(60);
79
80
  return res? 0: 1;
81
}
82
83
static void
84
ow_write_bit(bool bit)
85
{
86
  cli();
87
  clear_dq();
88
  if (bit)
89
    set_dq();
90
  _delay_ms(0.1);
91
  set_dq();
92
  sei();
93
}
94
95
uint8_t
96
ow_read_byte(void)
97
{
98
  uint8_t i;
99
  uint8_t val = 0, mask;
100
101
  for (i = 0, mask = 1; i < 8; i++, mask <<= 1)
102
    {
103
      if (ow_read_bit())
104
        val |= mask;
105
      _delay_ms(0.1);
106
    }
107
108
  return val;
109
}
110
111
void
112
ow_write_byte(uint8_t val)
113
{
114
  uint8_t i;
115
  uint8_t mask;
116
117
  for (i = 0, mask = 1; i < 8; i++, mask <<= 1)
118
    {
119
      ow_write_bit(val & mask);
120
    }
121
  _delay_ms(0.1);
122
}
123
124
uint8_t
125
ow_checkcrc(uint8_t *data, uint8_t nbytes)
126
{
127
  uint8_t crc = 0, i;
128
129
  for (i = 0; i < nbytes; i++)
130
    crc = _crc_ibutton_update(crc, data[i]);
131
132
  return crc; // must be 0
133
}
134
135
void
136
Read_Temperature(void)
137
{
138
  uint8_t get[9];
139
  uint8_t temp_lsb,temp_msb;
140
  uint8_t k;
141
142
  ow_reset();
143
144
  ow_write_byte(0xCC); //Skip ROM
145
  ow_write_byte(0x44); // Start Conversion
146
147
  for (uint16_t i = 0; i < 750; i++)
148
    _delay_ms(1);
149
150
  ow_reset();
151
152
  ow_write_byte(0xCC); // Skip ROM
153
  ow_write_byte(0xBE); // Read Scratch Pad
154
155
  printf("ScratchPAD DATA = ");
156
  for (k = 0; k < 9; k++){
157
    get[k] = ow_read_byte();
158
    printf("%02X ", get[k]);
159
  }
160
  k = ow_checkcrc(get, 9);
161
  printf(" (CRC %s)\n", k == 0? "OK": "FAIL");
162
163
  temp_msb = get[1]; // Sign byte + lsbit
164
  temp_lsb = get[0]; // Temp data plus lsb
165
  if (temp_msb <= 0x80){
166
    temp_lsb = (temp_lsb / 2);
167
  } // shift to get whole degree
168
  temp_msb = temp_msb & 0x80; // mask all but the sign bit
169
  if (temp_msb >= 0x80) {
170
    temp_lsb = (~temp_lsb)+1;
171
  } // twos complement
172
  if (temp_msb >= 0x80) {
173
    temp_lsb = (temp_lsb / 2);
174
  }// shift to get whole degree
175
  if (temp_msb >= 0x80) {
176
    temp_lsb = ((-1) * temp_lsb);
177
  } // add sign bit
178
179
  printf("T = %d °C\n", (int)temp_lsb ); // print temp. C
180
}
181
182
void
183
Read_ROMCode(void)
184
{
185
  uint8_t n;
186
  uint8_t dat[8];
187
188
  printf("Reading ROM Code\n");
189
190
  ow_reset();
191
192
  ow_write_byte(0x33);
193
194
  printf("ROM Code = ");
195
  for (n = 0; n < 8; n++) {
196
    dat[n] = ow_read_byte();
197
    printf("%02X ", dat[n]);
198
  }
199
  n = ow_checkcrc(dat, 8);
200
  printf(" (CRC %s)\n", n == 0? "OK": "FAIL");
201
}
Hier ist noch die 1wire.h:
1
#include <stdbool.h>
2
3
#define OW_PORT B
4
#define OW_PIN  7
5
6
extern bool ow_reset(void);
7
extern void Read_ROMCode(void);
8
extern void Read_Temperature(void);
Bitte mit -Os und -std=gnu99 compilieren.

von Peter D. (peda)


Lesenswert?

Wie wärs mit nem Blick in die Codesammlung ?


Beitrag "DS1820, DS18B20 in C"


Peter

von Sascha (Gast)


Lesenswert?

Ich wollte eigentlich nur wissen warum mein code net geht! Die Beispiele 
ahbe ich ja bereits studiert und angewendet!

von Peter D. (peda)


Lesenswert?

Sascha wrote:
> Ich wollte eigentlich nur wissen warum mein code net geht!

Du nimmst den ganzen Port C, Du darfst aber nur einen Pin nehmen.


Peter

von Sascha (Gast)


Lesenswert?

Na das is doch egal ob nu ein Pin ausgang is oder net, den Status erfrag 
ich mit PINC0, also nur einem Pin...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Wie du aber mit den aus der Luft gegriffenen Warteschleifen ein
definiertes Timing erreichen willst, haste mir immer noch nicht
verraten.  Timing ist aber zwangsweise bei 1-wire das A und O.

von Sascha (Gast)


Lesenswert?

Dieses delay1(); ist eine von mir geschriebene Schleife, hab die so 
genannt... Sie zählt von 0 bis zum eingegebenen Wert... Muss im 
Quelltext wohl verloren gegangen sein...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Sascha wrote:

> Dieses delay1(); ist eine von mir geschriebene Schleife, hab die so
> genannt... Sie zählt von 0 bis zum eingegebenen Wert... Muss im
> Quelltext wohl verloren gegangen sein...

Nein, ist nicht verlorengegangen.  Wie ich dir aber schon einen
Kilometer weiter oben geschrieben habe (interessiert dich eigentlich,
welche Gedanken sich die Leute um dein Zeug machen?), macht sie nur
aus Sicht des Compilers rein gar nichts, folglich eliminiert er sie.
Das ist sein gutes Recht.  Du hast keinen Anspruch auf einen
bestimmten Assemblercode, sondern nur einen Anspruch darauf, dass der
generierte Assemblercode funktional genau das tut, was du in C
hingeschrieben hast.  Eine Zuweisung zu einer Variablen, die nie
wieder benutzt wird, hat funktional keinen Effekt.

Daher mein Hinweis, bitte doch statt deines selbstgerödelten und nicht
wirklich verstandenen (geschweige denn im Assemblercode getimeten)
Codes bitte die Funktionen aus <util/delay.h> zu benutzen.  Das Timing
ist das A und O bei 1-wire (das liegt in der Natur der Sache), da
solltest du besser auf Bewährtes zurückgreifen, statt sinnlose
Fahrräder noch einmal zu erfinden.  Als Beispiel dann mein Code, der
ungefähr dasselbe tun sollte wie deiner, außer dass ich eine minimale
Hardwareabstraktion bereits von vornherein eingeplant habe (die deinem
Code aber sicher auch gut zu Gesicht stünde).

von Peter D. (peda)


Lesenswert?

Sascha wrote:
> Na das is doch egal ob nu ein Pin ausgang is oder net, den Status erfrag
> ich mit PINC0, also nur einem Pin...

Tust Du eben genau nicht !!!
1
unsigned char read_bit(void)
2
...
3
  bitstat=PINC;
4
  return(bitstat);
5
...
6
    if(read_bit())
7
                        value|=0x01<<i;


Peter

von Sebastian (Gast)


Lesenswert?

Wie realisiere ich:

"Bitte mit -Os und -std=gnu99 compilieren."

mit AVR Studio4?

läuft das Programm?

MfG

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Sebastian wrote:

> Wie realisiere ich:
>
> "Bitte mit -Os und -std=gnu99 compilieren."
>
> mit AVR Studio4?

Indem du dich durch die entsprechenden Optionen durchklickerst.

Oder gleich ein externes Makefile nimmst. ;-)

> läuft das Programm?

Es ist keins, sondern nur ein paar Funktionen.  Ein lauffähiges
Programm musst du dir schon selbst drumschreiben.

von Sebastian (Gast)


Lesenswert?

Ok, danke...

Würde es gehen, wenn ich in eine Mainfunktion Read_Temperature(); 
schreibe, rein theoretisch müsste doch dann ein Tempwert heraus kommen?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ich habe ungefähr sowas in meinem Testprogramm:
1
  bool ow_presence;
2
3
...
4
  ow_presence = ow_reset();
5
6
  printf("Hello, there, 1-wire device is%s present!\n",
7
         ow_presence? "": " not");
8
  if (ow_presence)
9
    {
10
      Read_ROMCode();
11
      Read_Temperature();
12
    }

von Michael R. (rubi)


Lesenswert?

Hallo Sascha

Ich würd ja den Code vom Jörg nehmen da er vorbildlich programmiert ist.
Wenn Du jedoch probieren möchtest ob dein Code funzt, dann definiere
die Variablen im delay Unterprogramm zusätzlich mit der volatile
Anweisung. Die sagt dem Compiler nämlich das er die Variable nicht 
wegoptimieren darf.

LG
Michael

von Sebastian (Gast)


Lesenswert?

Mmmh ich hab das Programm 1 zu 1 übernommen...
funzt aber net... ich seh aufm Oszi nicht, dass das scratchpad 
ausgegeben wird... Ich benutze nen Quarz mit 7,3728MHz... Des Weiteren 
benutze ich Port G0...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Ich benutze nen Quarz mit 7,3728MHz...

Hast du dann auch F_CPU angepasst?

Außerdem solltest du wohl auch die printf()s rausnehmen, es sei denn,
du hast stdio irgendwie ohnehin bereits konfiguriert.

von Michael R. (rubi)


Lesenswert?

Wundert mich das das ohne die Datei "1wire.h" überhaupt compiliert.
Ein Codefragment soll in der Regel nur zeigen wie es gehen würde.

LG
Michael

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Wundert mich das das ohne die Datei "1wire.h" überhaupt compiliert.

Steht doch mit dabei...

von Michael R. (rubi)


Lesenswert?

Ups entschuldige, habe ich übersehen,...

LG
Michael

von Sebastian (Gast)


Lesenswert?

Hallo,

Ja ich habe das auf 7372800 geändert, die printf hab ich alle 
rausgenomen... Ich probier morgen nochma ein bissel... meld mich dann 
wieder... Was ich fragen wollte: die Anweisung _delay_ms(0.48); müsste 
doch 480µs verzögern... laut Oszi ist das aber weit mehr...? Hängt das 
eventuell von meiner Hardware ab?

MfG

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> die Anweisung _delay_ms(0.48); müsste
> doch 480µs verzögern...

Genau.

> laut Oszi ist das aber weit mehr...?

Zufällig 3.53 ms?

.

.

.

.

.

.

.

.

.

.
Schalt deinen Quarz bitte ein, dein AVR läuft noch mit dem 1-MHz-
RC-Oszillator...

von Sebastian (Gast)


Lesenswert?

Hi,

Zeit liegt bei 1ms... hab geschaut interner Oszillator müsste 
deaktiviert sein...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Optimierung ist aber eingeschaltet, oder?

von Sebastian (Gast)


Lesenswert?

... Das weiß ich nicht... Wo kann man denn diese Optimierung 
einstellen... bzw. wie muss ich sie konfigurieren?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Wer generiert denn dein Makefile?  (Ich vermute mal, du hast es sicher
nicht mit der Hand geschrieben.)

Bei Mfile:

Makefile -> Optimization level -> s  (ist aber dort die Voreinstellung)

Bei AVR Studio musste mal selbst gucken, hab' ich hier nicht.

von Sebastian (Gast)


Lesenswert?

Es geht... besten dank!

von Sebastian (Gast)


Lesenswert?

Eine Frage hätte ich dann doch noch :-)
die Temperatur wird in ganzen grad ausgegeben? Wie kann ich jetzt den 
Wert auf Kommastellen ausgeben?

von Fisch (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich versuche jetzt schon seit gestern den ds18s20 zum laufen zu 
bekommen, es gelingt mir aber nicht. Ich wollte ganz einfach anfangen 
und erstmal den Presence Puls abfragen und genau da liegt schon das 
Problem. Der Sensor antwortet einfach nicht. Am Sensor kann es 
eigentlich nicht liegen, da ich schon andere ausprobiert habe. Ein Oszi 
hab ich leider auch nicht zur Hand. Zum testen habe ich den Code von 
Jörg Wunsch benutzt und nur per main()die Funktion ow_reset() aufgerufen 
(siehe Anhang). Ich benutze eine AtMega32@16MHz und betreibe den Sensor 
mit eigener Spannungsversorgung und 4,7k Pullup an der Datenleitung. Wer 
schön wen jemand von euch eine Idee hat.

Gruß Fisch

von Fisch (Gast)


Lesenswert?

Hallo.
Nachdem ich den Sensor jetzt parasitär angschlossen funktioniert es 
schon besser. Ich kann selbst die Register auslesen. Aber es ist schon 
wieder ein neues Problem aufgetaucht. Wenn ich die Temperaturregister 
auslese bevor ich eine Wandlung durchgeführt habe, sendet der DS mir 85° 
was ja auch seine Richtigkeit hat. Nur wenn ich vorher eine Messung 
mache, zeigt er mir immer 127° (bzw. 00 FF) an. Ich warte zwischen 
Messung und dem Auslesen >1s. Hat jemand von euch solch ein Problem 
schonmal gehabt?

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.