Forum: Mikrocontroller und Digitale Elektronik DS18b20 Reset geht nicht


von Ratemall (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich brauch dringend eure Hilfe.
Ich versuche seit drei Tagen einen DS18B20 zum laufen zu bekommen und 
bleib schon beim Reset hängen. Na das kann ja noch witzig werden.

Mein Aufbau:

Atmega 32 Pin A0 an PIN 2 des DS... .
Pin A1 und A2 Oszi.
GND an Pin 1 des DS... .
5V an Pin 3 des DS... . Selbe Versorgung wie vom Atmega 32.
Zischen Pin 2 und 3 des DS... befindet sich ein 4,7 k parallel.
Atmega Takt: 4Mhz Qaurz.

Was pasiert:
Schalte ich die Spannungsversorgung ein liegt A0 auf GND und A2 auf 
High.
Trenne ich die Datenleitung des DS... und starte neu ist A2 auch high.
Auf der Datenleitung liegen dann 5V.
Ich hab es auch schon mit einem anderen Probiert. Das selbe Problem.
Was mach ich falsch?

Danke für eure Hilfe.

Gruß,
Jürgen

von holger (Gast)


Lesenswert?

#define Bus        PA0

if (Bus == 0)

PA0 ist immer Null. Bus damit auch.

von Ratemall (Gast)


Lesenswert?

holger schrieb:
> #define Bus        PA0
>
> if (Bus == 0)
>
> PA0 ist immer Null. Bus damit auch.

Versteh ich nicht. Was willst du mir damit sagen? Hängt das mit dem 
Fehler zusammen?

von (prx) A. K. (prx)


Lesenswert?

Ratemall schrieb:

> Versteh ich nicht. Was willst du mir damit sagen? Hängt das mit dem
> Fehler zusammen?

Könnte man so sagen. Das entspricht ungefähr
  main()
  {
     if (1)
       printf("Fehler!");
     else
       printf("OK!");
  }
mit der anschliessenden verblüfften Frage, weshalb das Programm immer 
nur Fehler! ausspuckt.

von holger (Gast)


Lesenswert?

>Versteh ich nicht. Was willst du mir damit sagen?

PA0 ist ein #define aus einer Header Datei.
Du kannst nicht PA0 (was immer 0 ist) abfragen sondern das
Bit 0 (=PA0) aus dem PINA Register. Das ist dein Fehler.

von Ratemall (Gast)


Lesenswert?

Da ist ein Denkfehler von mir.
Ich muß die Variable reset abfragen:
1
    reset = (Eingang & 1<<Bus);
2
3
    _delay_us(480);
4
    BUSDDR_AUS();
5
    if (reset == 0)
6
    {  
7
        
8
      PORTA |= (1<<ERRJA);
9
    //  lcd_string("Reset fehler");
10
    }
11
    else
12
    {
13
      PORTA |= (1<<ERRNEIN);
14
    //  lcd_string("Reset okay");
15
    }

Funktioniert drotzem nicht.

von Ratemall (Gast)


Lesenswert?

Oha, jetzt wirds interessant.

Hab den Optimieren auf 00 gesetzt, funktioniert. Mit Datenleitung A1 
High und ohne A2 high.
Wie man im Code sieht wollte ich das ganze auf ein Display ausgeben. Das 
Display läuft aber nur bei 0S richtig.

Was tun?

von Ratemall (Gast)


Angehängte Dateien:

Lesenswert?

Okay, raus gefunden wo der Fehler ist. Der Fehler liegt bei der 
Display-Routine. Diese Fragt anscheinend das Busyflak nicht richtig ab. 
Im 0S funktioniert die Anzeige aber das Reset nicht. Im 00 funktioniert 
der Reset aber das Display zeigt nur Schrott. Es sieht so aus als würde 
das Display nicht nachkommen. Deshalb habe ich die Routine von so:
1
void lcd_string(char *s)
2
{
3
  char c;
4
  c=*s;
5
  while (c != '\0')
6
  {  
7
    RS_S;
8
    DISPLAY_PORT = c;
9
    DISPLAY_EN();
10
    DISPLAY_BUSY();
11
    *s++;
12
    c=*s;
13
  }
14
}

auf so:
1
void lcd_string(char *s)
2
{
3
  char c;
4
  c=*s;
5
  while (c != '\0')
6
  {  
7
    RS_S;
8
    DISPLAY_PORT = c;
9
    DISPLAY_EN();
10
    DISPLAY_BUSY();
11
    _delay_ms(10);
12
    *s++;
13
    c=*s;
14
  }
15
}

geändert.
Das macht das Display aber langsam.
Aber das ist woll ein anderes Problem. Muss ich ein neues Thread 
aufmachen oder kannst Du mir da auch schnell helfen?

von Cyblord -. (cyblord)


Lesenswert?

Wieso machst du nicht eins nach dem anderen? Bekomm doch erstmal deine 
LCD Routine in den Griff und frag das Busy Flag korrekt ab. Dein Code 
sieht allgemein ziemlich komisch aus.

Wenn du einen String durchlaufen willst, dann musst du s++ schreiben und 
nicht *s++. Du willst ja die Adresse um 1 erhöhen und nicht den 
Buchstaben. Allerdings funktioniert es, wegen der Operatorreihenfolge. 
Trotzdem falsch und murks.

Grundsätzlich so:
1
void lcd_string(char *s) {
2
  
3
  while(*s) {
4
    tuwas(*s);
5
    s++;
6
  }
7
}

Und dann die unnötigen Zuweisungen zur Variable c.
Warum schreibst du manche Funktionen klein (richtig) und andere 
wiederrum komplett groß? Der Code ist allgemein grausam.

von Karl H. (kbuchegg)


Lesenswert?

Und fang als erstes damit an, die eine Funktion zu machen, die ein 
einzelnes Byte ausgibt. Das ist doch grausam, wenn du da jedesmal immer 
wieder den gleichen Ausgabecode in jeder einzelnen Funktion hast.

Eine Stringausgabe ist dann ganz simpel
1
void lcd_string(const char *s)
2
{
3
  while(*s)
4
    lcd_character(*s++);
5
}

von Ratemall (Gast)


Lesenswert?

cyblord ---- schrieb:
> Wieso machst du nicht eins nach dem anderen?

Weil die Routine eigentlich schon längst fertig war.

Das ist ja cool. Die Routine hab ich noch von der Ausbildung. Die hat 
ein Lehrer erstellt und ich habe sie nur an mein Board angepasst.

cyblord ---- schrieb:
> Warum schreibst du manche Funktionen klein (richtig) und andere
> wiederrum komplett groß?

Das hatte denn Hintergedanken das die kleingeschriebenen aus dem 
Hauptprogram aufgerufen werden und die großen nur intern in der Routine 
benötigt werden.

Das heist wenn ich das:
1
void lcd_string(char *s)
2
{
3
  char c;
4
  c=*s;
5
  while (c != '\0')
6
  {  
7
    RS_S;
8
    DISPLAY_PORT = c;
9
    DISPLAY_EN();
10
    DISPLAY_BUSY();
11
    *s++;
12
    c=*s;
13
  }
14
}

zu dem:

void lcd_string(char *s)
{
   while (*s != '\0')
  {
    RS_S;
    DISPLAY_PORT = *s;
    DISPLAY_EN();
    DISPLAY_BUSY();
    s++;
   }
}

änder, müßte es auch mit der Optimierung 00 funktionieren?

Werds heute abend mall ausprobieren.

Danke für eure Mühe.

von Ratemall (Gast)


Lesenswert?

Hallo,

wollte nur schnell bescheidgeben das es so funktioniert:
1
void lcd_string(char *s)
2
{
3
   while (*s != '\0')
4
  {
5
    RS_S;
6
    DISPLAY_PORT = *s;
7
    DISPLAY_EN();
8
    DISPLAY_BUSY();
9
    s++;
10
   }
11
}

Aber das mit dem Busy-Flag klappt noch nicht.
Könnt ihr mir da auch noch helfen?
Wie muss ich denn Code ändern:
1
void DISPLAY_BUSY(void)
2
{
3
    uint8_t j;
4
    j=0;
5
    DDRC=0x00;
6
    while (!(j==0))
7
    {
8
      RS_L;
9
      RW_S;
10
      asm("nop");  
11
      EN_S;
12
      asm("nop");        
13
14
      if (!(PINC &(1<<PIN7)))
15
      {
16
        j=0;
17
      }
18
      else
19
      {
20
        j=1;
21
      }      
22
      EN_L;
23
      RW_L;
24
    }  
25
    DDRC=0xFF;
26
}

von Ratemall (Gast)


Lesenswert?

Achso, ich benutze ein EA W204B-NLW. Ist denke noch wichtig zu wiesen.

von Ratemall (Gast)


Lesenswert?

Guten abend.

Muss den Thread doch noch mal zum Leben erwecken.

Display funktioniert jetzt einwandfrei. Bastel schon seit Freitag wieder 
an dem Fühler rum und komme nicht weiter.

Dachte eigentlich der Reset funktioniert und habe am auslesen weiter 
gemacht. Da es nicht funktioniert, habe ich denn Reset nochmals 
untersucht und festgestellt das es mich vera.....t hat.

So sieht momentan der Code aus:
1
void reset (void)
2
  {
3
    uint8_t reset;
4
    BUSDDR_AUSGANG();
5
    BUS_LOW();
6
    _delay_us(480);
7
    BUSDDR_EINGANG();
8
    _delay_us(66);
9
    
10
    reset = (Eingang & 1<<Bus);
11
12
    _delay_us(480);
13
    BUSDDR_AUSGANG();
14
    if (reset == 1)
15
    {  
16
       lcd_string("Reset fehler");
17
    }
18
    else
19
    {
20
      lcd_string("Reset okay");
21
    }
22
  }

Ist die Datenleitung eingesteckt und ich schalte das Bord an, zeigt das 
Display: "Fehler". Ist die Datenleitung getrennt und ich schalte ein, 
zeigt das Display "okay" an. Die Routine funktioniert demnach. Weil, 
würde der Reset funktionieren würde der Sensor die Datenleitung auf null 
ziehen das ja dem trennen der Leitung entspricht.? Jetzt hab ich an der 
Leitung gemessen was für ein Pegel anliegt wenn die Leitung nicht 
angeschlossen ist. Siehe da, 5V. Ist das Richtig?

von Ratemall (Gast)


Lesenswert?

Hallo,

keiner eine Idee?

von Klaus (Gast)


Lesenswert?

Die Initialisieung sieht bei mie so aus.
Vllt. hilft dir das weiter.


// Initalisierung
int DS18S20_Init(void)
{
  uint8_t err=100;
  DS18S20_DDR |= 1 << DS18S20_wire;  // 1-wire Leitung auf LOW schalten
  _delay_us(480);            // mind. 480µs Low halten

  DS18S20_DDR &= ~(1<<DS18S20_wire);  // 1-wire Leitung auf HIGH 
schalten
    _delay_us(60);            // nach mind. 60µs wird der 
Precense-Impuls abgefragt

  err = (DS18S20_PIN & (1<<DS18S20_wire))  >> DS18S20_wire;  // err = 0 
Sensor ermittelt
  // Eine am Port D Pin 1 angeschlossene LED zeigt einen Fehler an wenn 
kein Sensor angeschlossen ist
  if (err == 1)
  {
    DS18S20_DDR |= ( 1 << LED_error);  // Kein Sensor vorhanden oder 
Leitungs Unterbrechung
  }
  else
  {
    DS18S20_DDR &= ~( 1 << LED_error);  // Mindestens ein Sensor 
ermittelt
  }
  _delay_us(480);
  return err;
}

von Klaus (Gast)


Lesenswert?

Sorry deine Frage vergessen

>Die Routine funktioniert demnach. Weil,
>würde der Reset funktionieren würde der Sensor die Datenleitung auf null
>ziehen.

Die Aussage ist richtig wenn der Sensor angeschlossen ist.


> das ja dem trennen der Leitung entspricht.?

Diese Ausage ist falsch! Warum? Weil der Pull-UP den BUS im Ruhezustand 
auf High-Signal zieht.

Du hast doch hoffentlich einen Externen Pull-UP?


> Siehe da, 5V. Ist das Richtig?
  Ja wenn externer PULL-UP auf High gechaltet ist

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.