Forum: Compiler & IDEs DS18S20 gibt immer nur "2" aus


von Paul P. (cesupa)


Lesenswert?

Hallo,

bin grad dabei mit Hilfe des DS18S20 die Temperatur auszulesen. Erstmal 
nur testweise. Benutze dafür einen Atmega32 mit 16MHz auf dem 
Pollinboard + Addonboard. Das ganze geschieht in C und sieht so aus:
1
/*
2
 * main.c
3
 *
4
 *  Created on: 15.07.2010
5
 *      Author: cesupa
6
 */
7
8
#include <avr/io.h>
9
#include <util/delay.h>
10
#include <stdlib.h>
11
#include "lcd_addonboard.h"
12
13
/* Thermometer Connections (At your choice) */
14
#define PORT PORTD
15
#define DDR DDRD
16
#define PIN PIND
17
#define DQ PD6
18
/* Utils */
19
#define INPUT_MODE() DDR&=~(1<<DQ)
20
#define OUTPUT_MODE() DDR|=(1<<DQ)
21
#define LOW() PORT&=~(1<<DQ)
22
#define HIGH() PORT|=(1<<DQ)
23
24
25
26
uint8_t reset();
27
uint8_t write_bit(uint8_t bit);
28
uint8_t read_bit();
29
uint8_t read_byte();
30
unsigned char rom_c[8],scratch_pad[9];
31
32
void write_byte(uint8_t byte);
33
34
int main()
35
{
36
  uint8_t z=0;
37
  char string[20];
38
39
  lcd_init();
40
  if(!reset())
41
    lcd_str("DS18S20 found");
42
  else
43
    lcd_str("FAILURE");
44
45
  write_byte(0xcc);
46
  write_byte(0x44);
47
  _delay_ms(1000);
48
49
  if(!reset())
50
  {
51
    write_byte(0xcc);
52
    write_byte(0xbe);
53
    for(z=0;z<9;z++)
54
    {
55
      scratch_pad[z]=read_byte();
56
    }
57
58
59
    lcd_str(itoa(scratch_pad[8],string,10));
60
  }
61
  else
62
    lcd_str("FAILURE_2");
63
64
  while(1);
65
  return 0;
66
}
67
68
uint8_t reset()
69
{
70
  uint8_t i=0;
71
  //Pull line low and wait for 480uS
72
73
  OUTPUT_MODE();
74
  LOW();
75
  _delay_us(480);
76
  //Release line and wait for 60uS
77
  INPUT_MODE();
78
  LOW();
79
80
  _delay_us(70);
81
82
  //Store line value and wait until the completion of 480uS period
83
  i=(PIN & (1<<DQ));
84
  OUTPUT_MODE();
85
  LOW();
86
  _delay_us(410);
87
88
  //Return the value read from the presence pulse (0=OK, 1=WRONG)
89
  return i;
90
91
}
92
93
uint8_t write_bit(uint8_t bit)
94
{
95
  //Pull line low for 1uS
96
  OUTPUT_MODE();
97
  LOW();
98
99
  _delay_us(1);
100
  //If we want to write 1, release the line (if not will keep low)
101
  if(bit) INPUT_MODE();
102
  //Wait for 60uS and release the line
103
  _delay_us(119);
104
  INPUT_MODE();
105
return 0;
106
}
107
108
uint8_t read_bit()
109
{
110
  uint8_t bit;
111
  //Pull line low for 1uS
112
  OUTPUT_MODE();
113
  LOW();
114
115
  _delay_us(1);
116
  //Release line and wait for 14uS
117
  INPUT_MODE();
118
  _delay_us(14);
119
  //Read line value
120
  bit=PIN&(1<<DQ);
121
  //Wait for 45uS to end and return read value
122
  _delay_us(105);
123
  return bit;
124
125
}
126
127
unsigned char read_byte()
128
{
129
  uint8_t i=0;
130
  unsigned char n=0;
131
132
  for(i=0;i<8;i++)
133
  {
134
    if(read_bit()) n|=0x01 << 1;
135
  }
136
    return n;
137
}
138
139
void write_byte(uint8_t byte)
140
{
141
  uint8_t i=8;
142
  while(i--){
143
  //Write actual bit and shift one position right to make  the next bit ready
144
  write_bit(byte&1);
145
  byte>>=1;
146
  }
147
148
}

Wenn ich mir die Bytes des Scratchpads ausgeben lasse, steht auf dem LCD 
ständig eine "2" da....ich hab leider keine Ahnung woran das liegen 
könnte. Bitte um Hilfe.

Gruß
Paul

von (prx) A. K. (prx)


Lesenswert?

Fällt dir da was auf?
 if(read_bit()) n|=0x01 << 1;

von Paul P. (cesupa)


Lesenswert?

Hallo,

ok, statt 1 hätte ich i schreiben sollen. Jetzt hab ich aber das 
Problem, dass ständig 255 rauskommt also jedes Bit eine 1 ist. Stimmt da 
etwas in meiner Leseroutine nicht?

Gruß
Paul

von (prx) A. K. (prx)


Lesenswert?

Im reset beim present bit nicht auf Ausgang setzen. Was du an dieser 
Stelle in der Doku siehst ist die Aktion vom device.

von Paul P. (cesupa)


Lesenswert?

ok, es funktioniert, nachdem ich die Variable bit in der Funktion 
read_bit() mit 0 initialisiert habe funktioniert alles.

Danke für eure Hilfe :)

Gruß
Paul

von 1ch (Gast)


Lesenswert?

> ok, statt 1 hätte ich i schreiben sollen.

1ch schre1be 1mmer 1 statt 1. Funkt1on1ert 
pr1ma!!!!!!11111111!!11!1!!!!1!!!!!1!!!!!

von Karl H. (kbuchegg)


Lesenswert?

Paul P. schrieb:
> ok, es funktioniert, nachdem ich die Variable bit in der Funktion
> read_bit() mit 0 initialisiert habe funktioniert alles.

Das ist zwar grundsätzlich eine gute Idee, erklärt aber das Problem 
nicht.

von Armin (Gast)


Lesenswert?

Hm, nicht wirklich.
In der Zeile "bit=PIN&(1<<DQ);" wird der Variablen "bit" ein Wert 
zugewiesen, ohne davor den Wert ausgelesen zu haben. Wenn man "bit" 
nicht mit 0 initialisiert, steht halt noch irgendetwas drin, wird dann 
aber eben einfach überschrieben.

Warum löst eine Initialisierung mit 0 das Problem?

von Lutz (Gast)


Lesenswert?

1
uint8_t write_bit(uint8_t bit)
2
{
3
  DDRD|=(1<<PD6);          // PD6 als Ausgang
4
  PORTD&=~(1<<PD6);        // PD6 auf low
5
  _delay_us(1);            // 1 µs warten
6
  if(bit) DDRD&=~(1<<PD6); // wenn bit != 0 dann PD6 auf low
7
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8
  _delay_us(119);          // 119 µs warten
9
  DDRD&=~(1<<PD6);         // PD6 als Eingang
10
return 0;
11
}

Bei read_bit ebenso. Was bringt denn das? Fehlt da jeweils ein 
else-Zweig? Ansonsten macht das if (bit) ja gar keinen Sinn und man kann 
gleich _delay_us(120) schreiben.

von Lutz (Gast)


Lesenswert?

Ja, ja , zu schnell geschossen: DDRD& ist natürlich was anderes als 
PORT& ..., also den Post einfach irgnorieren!

von Karl H. (kbuchegg)


Lesenswert?

Lutz schrieb:

>   if(bit) DDRD&=~(1<<PD6); // wenn bit != 0 dann PD6 auf low
>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


> Bei read_bit ebenso. Was bringt denn das? Fehlt da jeweils ein
> else-Zweig? Ansonsten macht das if (bit) ja gar keinen Sinn und man kann
> gleich _delay_us(120) schreiben.

Der Kommentar mag ein bischen verwirrend sein. Falsch ist er auf jeden 
Fall. Du magst auch übersehen haben, dass hier das DDRD Register 
geschaltet wird und nicht das PORTD.

> Ja, ja , zu schnell geschossen: DDRD& ist natürlich was anderes
> als PORT& ..., also den Post einfach irgnorieren!

Nicht wirklich.
Er enthält nämlich ein Element, dessen Verständnis wichtig ist: Die 
Leitung wird über das DDR Register umgeschaltet. Dies deshalb weil es ja 
einen externen Pullup Wderstand gibt, der die Leitung auf 1 zieht.

Durch

   DDRD&=~(1<<PD6);

wird daher, anders als es der Kommentar suggeriert, die Leitung durch 
den externen Pullup auf 1 gezogen, indem der Pin auf Eingang geschaltet 
wird.

: Wiederhergestellt durch User
von Seb a. (seppelg85)


Lesenswert?

Hallo zusammen

Auch wenn der Thread schon was älter ist, bräuchte ich hier mal Hilfe. 
Der Code ist übersichtlich und kompakt, daher habe ich den mal getestet.

Du hast geschrieben das der Code so funktioniert. Leider ist dem bei mir 
nicht so. Ich bekomme permanent eine 255 am LCD Display ausgegeben.

Hat hier noch jemand eine Idee was das Problem sein könnte?


Gruß

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.