Forum: Mikrocontroller und Digitale Elektronik DS18S20 Temperatur lesen / Timing


von W. P. (wopi)


Lesenswert?

Hallo

Ich habe einen DS18S20 am ATMEGA8 geschaltet.

DQ uber pullup zu PB1.

Mein reset Routine funtioniert, ich bekomme den Presence Pulse zuruck 
(Bus low), danach mochte ich ein SKIP ROM (0xCC) Befehl senden und eine 
Temperaturmessung durch Convert T (0x44) starten. Ich warte bis die 
Temperaturmessung beended ist. Danach versuche ich uber den READ 
SCRATCHPAD Befehl die ersten zwei Bytes des Scratchpad auszulesen.

Leider bekomme ich beide Bytes als 0x00 zuruck.

Irgendwo ist der Wurm drin:
1
#define F_CPU 1000000
2
#include <avr/io.h>
3
#include "lcd-routines.h"
4
#include <util/delay.h>
5
6
void delay_us ( uint8_t us )
7
{
8
  for(; us > 0; us--) _delay_us(1);
9
}
10
11
int ow_reset(void){
12
  DDRB |= (1<<PB1);
13
  PORTB &= ~(1<<PB1);
14
  _delay_us(480);
15
  DDRB &= ~(1<<PB1);
16
  _delay_us(80);
17
  while((PINB & (1<<PINB1))){
18
19
  }
20
  return 1;
21
}
22
23
uint8_t ow_write_byte(uint8_t value){
24
  uint8_t i      = 0;
25
  uint8_t pulse  = 0;
26
27
  for(i=0; i<8; i++){                   // 8 bits
28
    if(value & (1<<i)){
29
      pulse = 1;                        // 5us for logic 1
30
    } else {
31
      pulse = 100;                      // 100us for logic 0
32
    }
33
    DDRB |= (1<<PB1);                   // DQ Low
34
    PORTB &= ~(1<<PB1);
35
    delay_us(pulse);                    // send bit
36
    DDRB &= ~(1<<PB1);
37
    delay_us(120-pulse);                // fill up frame
38
    delay_us(10);                       // recovery period
39
  };
40
  return 1;
41
}
42
43
void main(void)
44
{
45
  lcd_init();
46
  ow_reset();
47
  ow_write_byte(0xCC);
48
  ow_write_byte(0x44);
49
  _delay_ms(1000);
50
  ow_reset();
51
  ow_write_byte(0xCC);
52
  ow_write_byte(0xBE);
53
54
  lcd_string("TEMP");
55
  ow_read_byte();
56
  ow_read_byte();
57
}
58
59
60
int ow_read_byte(void){
61
  uint8_t i = 0;
62
63
  for(i=0;i<8;i++){
64
    DDRB |= (1<<PB1);
65
    PORTB &= ~(1<<PB1);
66
    _delay_us(1);
67
    PORTB &= ~(1<<PB1);
68
    DDRB &= ~(1<<PB1);
69
    _delay_us(5);
70
    if((PINB & (1<<PINB))){
71
      lcd_string("1");
72
    }else{
73
      lcd_string("0");
74
    }
75
  }
76
  _delay_us(5);
77
  return 0;
78
}

Weiss Jemand Rat ?

Grus

von holger (Gast)


Lesenswert?

Da isser der Wurm;)

    PORTB &= ~(1<<PB1);
    _delay_us(1);
    PORTB &= ~(1<<PB1);

von W. P. (wopi)


Lesenswert?

holger schrieb:
> Da isser der Wurm;)
>
>     PORTB &= ~(1<<PB1);
>     _delay_us(1);
>     PORTB &= ~(1<<PB1);

Ich kann leider nicht folgen:
1
int ow_read_byte(void){
2
  uint8_t i = 0;
3
4
  for(i=0;i<8;i++){
5
    DDRB |= (1<<PB1);
6
    PORTB &= ~(1<<PB1);
7
    _delay_us(1);
8
    DDRB &= ~(1<<PB1);
9
    _delay_us(5);
10
    if((PINB & (1<<PINB))){
11
      lcd_string("1");
12
    }else{
13
      lcd_string("0");
14
    }
15
  }
16
  _delay_us(5);
17
  return 0;
18
}

von holger (Gast)


Lesenswert?

>Ich kann leider nicht folgen:

Ich auch nicht, aber das zweite PORTB... ist überflüssig.

Aber da solltest du noch mal GENAU hinsehen:

    if((PINB & (1<<PINB))){
      lcd_string("1");
     }else{
      lcd_string("0");
    }

von W. P. (wopi)


Lesenswert?

danke @holger
1
int ow_read_byte(void){
2
  uint8_t i = 0;
3
4
  for(i=0;i<8;i++){
5
    DDRB |= (1<<PB1);
6
    PORTB &= ~(1<<PB1);
7
    _delay_us(1);
8
    DDRB &= ~(1<<PB1);
9
    _delay_us(5);
10
    if(PINB & (1<<PINB1)){
11
      lcd_string("1");
12
    }else{
13
      lcd_string("0");
14
    }
15
  }
16
  _delay_us(5);
17
  return 0;
18
}

Jetzt kriege ich aber lauter "1", 0xFF ausgelesen.

Das Default Value ist ja 0x00AA (Datenblatt)

Ich poste mal das komplette program im jetzigem Zustand:
1
#define F_CPU 1000000
2
#include <avr/io.h>
3
#include "lcd-routines.h"
4
#include <util/delay.h>
5
6
void delay_us ( uint8_t us )
7
{
8
  for(; us > 0; us--) _delay_us(1);
9
}
10
11
int ow_reset(void){
12
  DDRB |= (1<<PB1);
13
  PORTB &= ~(1<<PB1);
14
  _delay_us(480);
15
  DDRB &= ~(1<<PB1);
16
  _delay_us(80);
17
  while((PINB & (1<<PINB1))){
18
19
  }
20
  return 1;
21
}
22
23
uint8_t ow_write_byte(uint8_t value){
24
  uint8_t i      = 0;
25
  uint8_t pulse  = 0;
26
27
  for(i=0; i<8; i++){                   // 8 bits
28
    if(value & (1<<i)){
29
      pulse = 1;                        // 5us for logic 1
30
    } else {
31
      pulse = 100;                      // 100us for logic 0
32
    }
33
    DDRB |= (1<<PB1);                   // DQ Low
34
    PORTB &= ~(1<<PB1);
35
    delay_us(pulse);                    // send bit
36
    DDRB &= ~(1<<PB1);
37
    delay_us(120-pulse);                // fill up frame
38
    delay_us(10);                       // recovery period
39
  };
40
  return 1;
41
}
42
43
void main(void)
44
{
45
  lcd_init();
46
  ow_reset();
47
  ow_write_byte(0xCC);
48
  ow_write_byte(0x44);
49
  _delay_ms(1000);
50
  ow_reset();
51
  ow_write_byte(0xCC);
52
  ow_write_byte(0xBE);
53
54
  lcd_string("TEMP");
55
  ow_read_byte();
56
  ow_read_byte();
57
}
58
59
60
int ow_read_byte(void){
61
  uint8_t i = 0;
62
63
  for(i=0;i<8;i++){
64
    DDRB |= (1<<PB1);
65
    PORTB &= ~(1<<PB1);
66
    _delay_us(1);
67
    DDRB &= ~(1<<PB1);
68
    _delay_us(5);
69
    if(PINB & (1<<PINB1)){
70
      lcd_string("1");
71
    }else{
72
      lcd_string("0");
73
    }
74
  }
75
  _delay_us(5);
76
  return 0;
77
}

von W. P. (wopi)


Lesenswert?

Ich habe es noch etwas "aufpoliert", es ist mehr lesbar und einfacher zu 
andern. Leider bleibt der Fehler bestehen. Am DS18S20 kann es nicht 
liegen, weil ich ein Paar davon habe, und bei allen der Fehler 
auftaucht.

Also der Fehler: Ich kriege lauter "1" gelesen.
1
#define F_CPU 1000000
2
#include <avr/io.h>
3
#include "lcd-routines.h"
4
#include <util/delay.h>
5
6
void delay_us ( uint8_t us )
7
{
8
  for(; us > 0; us--) _delay_us(1);
9
}
10
11
void dq_low(uint8_t period){
12
  DDRB |= (1<<PB1);
13
  PORTB &= ~(1<<PB1);
14
  delay_us(period);
15
  DDRB &= ~(1<<PB1);
16
}
17
18
int ow_reset(void){
19
  dq_low(480);
20
  _delay_us(80);
21
  while((PINB & (1<<PINB1))){
22
23
  }
24
  _delay_us(300);
25
  return 1;
26
}
27
28
uint8_t ow_write_byte(uint8_t value){
29
  uint8_t i      = 0;
30
31
  for(i=0; i<8; i++){
32
    if(value & (1<<i)){
33
      dq_low(1);
34
      delay_us(115);
35
    } else {
36
      dq_low(100);
37
      delay_us(10);
38
    }
39
  };
40
  delay_us(50);
41
  return 1;
42
}
43
44
uint8_t ow_read_byte(void){
45
  uint8_t i = 0;
46
  uint8_t result = 0;
47
48
  for(i=0;i<8;i++){
49
    dq_low(2);
50
    _delay_us(14);
51
    if(PINB & (1<<PINB1)){
52
      result |= (1<<i);
53
    }
54
    _delay_us(1);
55
  }
56
  return result;
57
}
58
59
60
int main(void)
61
{
62
  uint8_t s0 = 0;
63
  uint8_t s1 = 0;
64
65
  lcd_init();
66
  ow_reset();
67
  ow_write_byte(0xCC);
68
  ow_write_byte(0xBE);
69
  s0 = ow_read_byte(); // = 0xFF - WHY ?!
70
  s1 = ow_read_byte(); // = 0xFF - WHY ?!
71
72
  ow_reset();
73
  
74
  lcd_setcursor(0,1);
75
  lcd_byte_binary(s0);
76
  lcd_setcursor(0,2);
77
  lcd_byte_binary(s1);
78
79
  return 1;
80
}

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.