DS18S20 gibt immer nur "2" aus

OP #1786703
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
Gast #1788029
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?
Gast #1795715
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.
#1795746
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.
#2268715
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ß

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren