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!
Mir würde auch schon reichen, wenn mir jemand sagen kann, wie ich die read_bit(); Anweisung gestalten kann??? MfG
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.
Ich wollte eigentlich nur wissen warum mein code net geht! Die Beispiele ahbe ich ja bereits studiert und angewendet!
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
Na das is doch egal ob nu ein Pin ausgang is oder net, den Status erfrag ich mit PINC0, also nur einem Pin...
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.
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...
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).
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
Wie realisiere ich: "Bitte mit -Os und -std=gnu99 compilieren." mit AVR Studio4? läuft das Programm? MfG
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.
Ok, danke... Würde es gehen, wenn ich in eine Mainfunktion Read_Temperature(); schreibe, rein theoretisch müsste doch dann ein Tempwert heraus kommen?
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 | }
|
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
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...
> 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.
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
> Wundert mich das das ohne die Datei "1wire.h" überhaupt compiliert.
Steht doch mit dabei...
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
> 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...
... Das weiß ich nicht... Wo kann man denn diese Optimierung einstellen... bzw. wie muss ich sie konfigurieren?
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.
Eine Frage hätte ich dann doch noch :-) die Temperatur wird in ganzen grad ausgegeben? Wie kann ich jetzt den Wert auf Kommastellen ausgeben?
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.