Forum: Mikrocontroller und Digitale Elektronik Atmega 8 + dallas 18s20 + Neuling (never ending story)


von Chris (Gast)


Lesenswert?

Hallo zusammen,

ich bin ein Neuling was das programmieren von µC angeht.
Mir gelingt das Blinken einer LED mit einem Tiny13, Atmega 8, usw., 
einen "Attiny 13" als externen Oszillator ist mir auch schon gelungen 
(bzw. wurde zur Pflicht, da die Fuses eines Atmega 8 "verfused" waren). 
Ein Display anzusteuern gelingt mir ebenfalls schon mithilfe der Include 
Dateien aus den unten genannten Büchern.

Jetzt würde ich mich gerne so langsam an was "richtiges" heranwagen:
Und schon schreitere ich :?
Ich möchte gerne einen Dallas (Maxim) 18S20 ansprechen und die Werte an 
ein Display übertragen. Ich habe natürlich im Netz herumgesucht und jede 
Menge gefunden, aber wie es immer so ist, versteht man (meiner einer) 
nur "Bahnhof".

Vieles was ich gefunden habe ist in Bascom, was ich auch probiert habe - 
ich möchte gerne bei C bleiben:

// define DSS1820 Options
#define Ds1920 0x10
#define Searchrom 0xF0
#define Skiprom 0xCC
#define Read_rom 0x33
#define Convertt 0x44
#define Read_ram 0xBE
#define Write_ram 0x4E
#define Copy_ram 0x48
#define Recall_ee 0xB8
#define Read_power 0xB4

Jetzt zu meiner eigentlichen Frage:
wie übergebe ich am PIN PD5 dem 18S20 den Befehl: 0x44?
Oder wie starte ich bevor ich auslesen kann einen Reset? Wahrscheinlich 
durch setzen von Low auf High?

Sorry, wahrscheinlich für euch ein klacks, aber 2 Bücher helfen mir 
leider hier nicht weiter.

Franzis: AVR Mikrocontroller in C-Programmieren
Elektor: AVR Hardware und C-Programmierung in der Praxis

Viele Grüße... aus dem Münsterland

von perlbastel (Gast)


Lesenswert?

Vorab: Den IC kenne ich nicht, tippe mal auf Thermometer oder 
irgendeinen Sensor.

> wie übergebe ich am PIN PD5 dem 18S20 den Befehl: 0x44?
Hehe :-)
Was du da definiert hast sind Präprozessorkonstanten, nicht mehr und 
nicht weniger. Ist dir das klar? Den Befehl übergibst du in dem du im 
richtigem Rythmus an den passenden Pins wackelst wo der IC angeschlossen 
ist. Es kann auch sein das sich das Ding per SPI oder so ansteuern 
lässt, dann kannst du das Pinwackeln der internen Hardware vom µP 
überlassen.

So, jetzt zieh ich mir das Datenblatt von dem IC und meld mich dann 
wieder.

von Chris (Gast)


Lesenswert?

Hallo perlbastel,

>Den IC kenne ich nicht, tippe mal auf Thermometer oder
irgendeinen Sensor.
der Dallas 18S20 ist ein Temparatur Sensor.

>Was du da definiert hast sind Präprozessorkonstanten, nicht mehr und
nicht weniger. Ist dir das klar?
Ja, aber genau da haperts, denn wie übergebe ich am PD5 dem Dallas den 
Hexcode 0x44 als Beispiel.

Vielen Dank für die Mühen!

von perlbastel (Gast)


Lesenswert?

Soooo... Datenblatt hast du vermutlich vorliegen, deshalb spare ich mir 
den Link.

Disclaimer: Ich hab seit Monaten/Jahren keinen µP mehr angefasst und 
keine Hardware zum Testen da, alle Angaben ohne Gewähr. Ich kann mich 
irren.

Erstmal zur Hardware: Der IC wird mit Spannung versorgt und ist am Pin 
PD5 vom µP angeschlossen richtig? Desweiteren braucht es einen Pullup 
(4,7kOhm) für die Datenleitung (s. Datenblatt Seite 9 Figure 9) und ein 
Kondensator (100nF) an der Spannungsversorgung vom IC schadet sicherlich 
auch nicht.

Das ganze nennt sich 1-Wire-Bus: Die Leitung wird der Pullup im 
Ruhezustand auf Vcc gezogen und von den angeschlossenen ICs (also dein 
Thermometer und der µP) per MOSFET/Transistor auf GND gezogen. 
Vergleiche "Open Collector" (<--Google/wiki).

Der µP hat allerdings einen Totem-Pole-Ausgang (<--Google), kann also 
die Leitung mit Vcc oder GND treiben oder nichts von beiden (Tristate 
Z). Um einen OpenCollector-Ausgang zu erzeugen tricksen wir: PORTD.5 
bleibt immer auf 0 und wir ändern nur DDRD.5. Der Pin ist also entweder 
Ausgang der auf Low=GND geschaltet ist oder Eingang ohne internen 
Pullup.

Kommst du noch mit?

Also zum Reset: Datenblatt Seite 13 Figure 10
Den Pin für mindestens 480µS auf GND ziehen.

Also in C:
1
DDRD&=~(1<<PD5); //Pin als Eingang
2
PORTD&=(1<<PD5); //internen Pullup aus bzw. Pin auf Masse ziehen wenn DDRD.5=1
3
4
//...
5
6
//Reset:
7
DDRD|=(1<<PD5);
8
_wait_us(480+20); //minimum 480µs
9
DDRD&=(1<<PD5);
10
11
_wait_us(15); //es vergehen mindestens 15µs bevor der IC reagiert
12
13
//Presence Pulse auswerten:
14
int timeout=480-15; //nach 480µs-15µs sollte eine Reaktion erfolgt sein.
15
int error=0;
16
while(PIND&(1<<PD5)) //solange der Pin high ist 
17
{
18
   timeout--;
19
   if(timeout==0)  //480µs um?
20
   {
21
      error=1;
22
      break;
23
   }
24
   _delay_us(1);
25
}
26
if(error)
27
{
28
   kein presence pulse -->OK Houston, wir haben ein Problem hier oben...
29
}
Die Funktion _wait_us heisst eventuell anders, guck mal in avr/delay.h 
nach. Eigentlich sind diese Funktionen verpöhnt weil der µP sinnlos Zeit 
verplempert aber bei Wartezeiten im µs Bereich und für einen Anfänger 
will ich nicht mit Timern und Interrupts ankommen.

Wenn die Erkennung vom IC funktioniert sag Bescheid, dann geht es 
weiter.

von perlbastel (Gast)


Lesenswert?

Ich hab mal die Suche gefragt, 
Beitrag "Re: 1-Wire Reset Impuls?" sieht auf den ersten 
Blick ganz interessant aus.

Du merkst allerdings: Der 1-Wire-Bus ist etwas komplizierter als eine 
blinkende LED...

von Chris (Gast)


Lesenswert?

hallo perlbastel,

treffer versenkt, ich schreibe dir mal was ich jetzt "noch" nicht 
verstehe...

Erstmal danke für deine ausführliche Schreibweise!

>Disclaimer: Ich hab seit Monaten/Jahren keinen µP mehr angefasst und
>keine Hardware zum Testen da, alle Angaben ohne Gewähr. Ich kann mich
>irren.
Okay.

>Erstmal zur Hardware: Der IC wird mit Spannung versorgt und ist am Pin
>PD5 vom µP angeschlossen richtig?
Ja, der DS18S20 ist mit dem DQ am PD5 des Atmega 8 angeschlossen

>Desweiteren braucht es einen Pullup
>(4,7kOhm) für die Datenleitung (s. Datenblatt Seite 9 Figure 9) und ein
>Kondensator (100nF) an der Spannungsversorgung vom IC schadet sicherlich
>auch nicht.
Der 4,7 KOhm Widerstand ist dran, nein der 100nF Kondensator ist nicht 
dran.

>Das ganze nennt sich 1-Wire-Bus: Die Leitung wird der Pullup im
>Ruhezustand auf Vcc gezogen und von den angeschlossenen ICs (also dein
>Thermometer und der µP) per MOSFET/Transistor auf GND gezogen.
>Vergleiche "Open Collector" (<--Google/wiki).
Muss ich mir nochmals durchlesen, ungefähr verstanden

>Der µP hat allerdings einen Totem-Pole-Ausgang (<--Google), kann also
>die Leitung mit Vcc oder GND treiben oder nichts von beiden (Tristate
>Z). Um einen OpenCollector-Ausgang zu erzeugen tricksen wir: PORTD.5
>bleibt immer auf 0 und wir ändern nur DDRD.5. Der Pin ist also entweder
>Ausgang der auf Low=GND geschaltet ist oder Eingang ohne internen
>Pullup.
Stop! Jetzt setzt es aus, suche gerade in dem Elektor Buch nach einer 
Lösung.

>DDRD&=~(1<<PD5); //Pin als Eingang
>PORTD&=(1<<PD5); //internen Pullup aus bzw. Pin auf Masse ziehen wenn >DDRD.5=1
Glaub mir bitte, diese 2 Zeilen sind bei mir ebenfalls so geschrieben, 
außer der Beschreibung / Kommentar.

>//Reset:
>DDRD|=(1<<PD5);
>_wait_us(480+20); //minimum 480µs
>DDRD&=(1<<PD5);
Stichwort wäre hier PWM oder? Bitte um Erklärung.
Was passiert in den 480 µS

>_wait_us(15); //es vergehen mindestens 15µs bevor der IC reagiert
Verstanden!

>while(PIND&(1<<PD5)) //solange der Pin high ist
>{
>   timeout--;
>   if(timeout==0)  //480µs um?
>   {
>      error=1;
>      break;
>   }
>   _delay_us(1);
>}
>if(error)
>{
>   kein presence pulse -->OK Houston, wir haben ein Problem hier oben...
>}
Hier könnte ich informationen ans Display senden!

>Die Funktion _wait_us heisst eventuell anders, guck mal in avr/delay.h
>nach. Eigentlich sind diese Funktionen verpöhnt weil der µP sinnlos Zeit
>verplempert aber bei Wartezeiten im µs Bereich und für einen Anfänger
>will ich nicht mit Timern und Interrupts ankommen.
Ich kenne die Funktion _delay_ms(WERT), ich werde es mal ausprobieren.

Ich werde es ausprobieren, Danke!

von perlbastel (Gast)


Lesenswert?

Chris schrieb:
> Der 4,7 KOhm Widerstand ist dran, nein der 100nF Kondensator ist nicht
> dran.
Ok. Wenn du einen parat hast tu ihn dran, kann nur helfen. Hat der mega8 
einen Kondensator an VCC und einen Pullup am Resetpin?
>
> Stop! Jetzt setzt es aus, suche gerade in dem Elektor Buch nach einer
> Lösung.
Gut, wenn du nichts findest sag Bescheid dann erklär ich das nochmal. 
Ein Blick ins Datenblatt vom mega8 könnte auch helfen.

> Stichwort wäre hier PWM oder? Bitte um Erklärung.
Nein, mit PWM hat das nichts zu tun. Es wird einfach nur der Pin auf low 
gesetzt, gewartet und dann wird der Pin wieder als Eingang definiert, 
d.h. der 1-Wire-Bus geht dank Pullup wieder auf logisch 1 = VCC.

> Was passiert in den 480 µS
Der µP wartet einfach ab. Die Zeit kommt aus dem Datenblatt, da steht 
der Resetpuls muss mindestens so lang sein.

> Hier könnte ich informationen ans Display senden!
Genau! Aber bitte nicht in der while-Schleife, sonst kommt das Timing 
durcheinander (Displayansteuerung ist idR langsam und die Schleife soll 
nur ~1µs pro Durchlauf brauchen).

> Ich kenne die Funktion _delay_ms(WERT), ich werde es mal ausprobieren.
VORSICHT: Ich schrieb delay_us, also MIKROSekunden. _delay_ms wartet 
aber MILLISekunden, also 1000 mal länger...

von Chris (Gast)


Lesenswert?

>Ok. Wenn du einen parat hast tu ihn dran, kann nur helfen. Hat der mega8
>einen Kondensator an VCC und einen Pullup am Resetpin?
Ja, klar, der Atmega 8 wird sogar mit einem externe Oszillator 8 Mhz 
betrieben :).

>Genau! Aber bitte nicht in der while-Schleife, sonst kommt das Timing
>durcheinander (Displayansteuerung ist idR langsam und die Schleife soll
>nur ~1µs pro Durchlauf brauchen).
Ok, dann nach der while schleife.

>VORSICHT: Ich schrieb delay_us, also MIKROSekunden. _delay_ms wartet
>aber MILLISekunden, also 1000 mal länger...
Verstanden, dann suche ich danach, vielleicht ist wie du es beschrieben 
hast in der Lib delay_us vorhanden.

von Chris (Gast)


Lesenswert?

So....

//...
[c]
int main(void)
{
  lcd_init(); // Make LCD Init.
  lcd_send(COMMAND, LCD_CLEAR); // Make LCD Init. and clear
  lcd_set_cursor (1, 0); // Set Cursor to first line in first charakter
  lcd_write ("Wir beginnen.");

  DDRC&=~(1<<PC5); //Pin als Eingang
  PORTC&=(1<<PC5); //internen Pullup aus bzw. Pin auf Masse ziehen wenn 
DDRD.5=1

  //Reset:
  DDRC |= (1<<PC5);
  _delay_us(480+20); //minimum 480µs
  DDRC&=(1<<PC5);

  _delay_us(15); //es vergehen mindestens 15µs bevor der IC reagiert

  //Presence Pulse auswerten:
  int timeout=480-15; //nach 480µs-15µs sollte eine Reaktion erfolgt 
sein.
  int error=0;
  while(PINC&(1<<PC5)) //solange der Pin high ist
  {
    timeout--;
    if(timeout==0)  //480µs um?
    {
      error=1;
      break;
    }
    _delay_us(1);
  }
  if(error)
  {
    lcd_send(COMMAND, LCD_CLEAR);
    lcd_set_cursor (1, 0);
    //kein presence pulse -->OK Houston, wir haben ein Problem hier 
oben...
     // Set first of two lines and start with after 4 characters
    lcd_write ("Wir haben ein Prob."); // write 20:00:00 to lcd.
  }
  else
  {
    lcd_send(COMMAND, LCD_CLEAR);
    lcd_set_cursor (1, 0);
    lcd_write ("ALLES OK");
  }
    //while(1)
    //{
        //TODO:: Please write your application code
    /*
    This is a example to make addition
    for temparature

    Temp = Temp + Scratch(1)
    Temp1 = Temp
    Temp1 = Temp1 / 2
    Stemp = Scratch(8) - Scratch(7)
    Stemp = Stemp / Scratch(8)
    Stemp = Stemp + Temp1
    Stemp = Stemp - 0.25
    */

}
[c]

Ich habe bemerkt, wenn ich das LCD zwischendurch anspreche, dass der 
DS18S20 nicht erkannt wird, das ist mal ein Hinweis.

Jetzt zeigt mir das Display an: "alles OK".
Ich probiere mal eben ein neues delay dazwischen um einen Effekt zu 
erreichen.

Vielleicht verstehe ich ja noch wie die "Daten" 0x44 / 0xF0 vom DSS1820 
an den µC übertragen werden, das will mir nicht in den Kopf.

von mete (Gast)


Lesenswert?

Du solltest dir nochmals die Bitoperationen in deinem C Buch zu Gemüte 
führen:
1
PORTC&=(1<<PC5); //internen Pullup aus bzw. Pin auf Masse ziehen wenn DDRD.5=1

Das hier zum Beispiel setzt nicht etwa das bit PC5 auf 0, sondern setzt 
alle anderen Bits in PORTC auf 0, und bei PC5 kommt es darauf an ob es 
vorher in PORTC gesetzt war. Wenn es gesetzt war bleibt es danach noch 
immer auf 1, ansonsten bleibt es auf 0. Das ist auf jeden Fall nicht 
das, was der Code laut Kommentar tun soll.
1
  //Reset:
2
  DDRC |= (1<<PC5);
3
  _delay_us(480+20); //minimum 480µs
4
  DDRC&=(1<<PC5);

Hier setzt du in der ersten Zeile das bit PC5 in DDRC. Dann wartest du, 
und setzt in DDRC alle Bits auf 0, ausser PC5. Das lässt du auf 1.
Vermutlich wolltest du schreiben:
1
  DDRC &= ~(1<<PC5);

Wenn du ein Bit auf 0 setzen willst und die anderen unberührt bleiben 
sollen, musst du natürlich mit einer Bitmaske ein logisches Und bilden, 
die genau dieses Bit nicht gesetzt hat.

von perlbastel (Gast)


Lesenswert?

mete schrieb:
> Du solltest dir nochmals die Bitoperationen in deinem C Buch zu Gemüte
> führen:
f*ck, da hab ich tatsächlich was vergessen. Enschuldigung...

Es muss natürlich heissen
1
DDRC&=~(1<<PC5);

**ärger**

von Chris (Gast)


Lesenswert?

mete schrieb:
> Du solltest dir nochmals die Bitoperationen in deinem C Buch zu Gemüte
> führen:
> PORTC &=(1<<PC5); //internen Pullup aus bzw. Pin auf Masse ziehen wenn DDRD.5=1
Ja, der kommentar ist auf jedenfall falsch!
Der DDRD ist schon unterschiedlich zu DDRC.

> Das hier zum Beispiel setzt nicht etwa das bit PC5 auf 0, sondern setzt
> alle anderen Bits in PORTC auf 0, und bei PC5 kommt es darauf an ob es
> vorher in PORTC gesetzt war. Wenn es gesetzt war bleibt es danach noch
> immer auf 1, ansonsten bleibt es auf 0. Das ist auf jeden Fall nicht
> das, was der Code laut Kommentar tun soll.

>   //Reset:
>   DDRC |= (1<<PC5);
>   _delay_us(480+20); //minimum 480µs
>   DDRC &=(1<<PC5);
> Hier setzt du in der ersten Zeile das bit PC5 in DDRC. Dann wartest du,
> und setzt in DDRC alle Bits auf 0, ausser PC5. Das lässt du auf 1.
> Vermutlich wolltest du schreiben:
>   DDRC &= ~(1<<PC5);

> Wenn du ein Bit auf 0 setzen willst und die anderen unberührt bleiben
> sollen, musst du natürlich mit einer Bitmaske ein logisches Und bilden,
> die genau dieses Bit nicht gesetzt hat.

Danke für den Hinweis, jetzt bin ich total verwirrt, aber ich muss es 
mir unbedingt nochmals zu Gemüte führen!

Vielen Dank!

von Chris (Gast)


Lesenswert?

Mal ein Lob,

danke das Ihr mich nicht steinigt, trotz meiner groben Fehler.

Vielen Dank!

von perlbastel (Gast)


Lesenswert?

Chris schrieb:
> Mal ein Lob,
>
> danke das Ihr mich nicht steinigt, trotz meiner groben Fehler.
>
> Vielen Dank!

Ach was steinigen! Mich müsste man steinigen weil ich oben Mist 
geschrieben habe, ich hoffe du hast das "~" wo nötig im Code 
hinzugefügt.

Wie ist denn der aktuelle Stand, wird der IC korrekt erkannt? Dann geht 
es (eventuell erst morgen) weiter mit dem Senden von Befehlen. :-)

von Chris (Gast)


Lesenswert?

Hallo,

>Ach was steinigen! Mich müsste man steinigen weil ich oben Mist
>geschrieben habe, ich hoffe du hast das "~" wo nötig im Code
>hinzugefügt.
Ganz einfach weil ich es nicht weiß und "Blind" (entschuldige) abpinne.
Hast du mal ein Tutorial wo ich das mit den Bits sauber nachlesen kann, 
im Moment könnte ich in die Tischkannte beißen :-).

Ja den Code habe ich abgeändert, ich hoffe richtig.
Ich teste das ganze melde mich dann wieder.

Vielen Dank!

von perlbastel (Gast)


Lesenswert?

Chris schrieb:
> Hast du mal ein Tutorial wo ich das mit den Bits sauber nachlesen kann,
> im Moment könnte ich in die Tischkannte beißen :-).
Das wird schon. Guckst du Bitmanipulation

> Ich teste das ganze melde mich dann wieder.
Ok, prima.

von Chris (Gast)


Lesenswert?

Hallo perlbastel,

auch mit der oben genannten Änderung ist der Wert der auf dem LCD 
erreicht wird "ALLES OK".

Wie kann ich das ganze verstehen, reagiert der µC nun auf die Änderung 
am PC5 Pin?

Viele Grüße!

von Klaus (Gast)


Lesenswert?

Hier mal ein beispiel von mir vllt. bringt dir das was.
1
// Initalisierung
2
int DS18S20_Init(void)
3
{
4
  uint8_t err=100;
5
  DS18S20_DDR |= 1 << DS18S20_wire;  // 1-wire Leitung auf LOW schalten
6
  _delay_us(480);            // mind. 480µs Low halten 
7
  
8
  DS18S20_DDR &= ~(1<<DS18S20_wire);  // 1-wire Leitung auf HIGH schalten  
9
    _delay_us(60);            // nach mind. 60µs wird der Precense-Impuls abgefragt  
10
      
11
  err = (DS18S20_PIN & (1<<DS18S20_wire))  >> DS18S20_wire;  // err = 0  Sensor ermittelt
12
  // Eine am Port D Pin 1 angeschlossene LED zeigt einen Fehler an wenn kein Sensor angeschlossen ist 
13
  if (err == 1)
14
  {
15
    DS18S20_DDR |= ( 1 << LED_error);  // Kein Sensor vorhanden oder Leitungs Unterbrechung
16
  }
17
  else
18
  {
19
    DS18S20_DDR &= ~( 1 << LED_error);  // Mindestens ein Sensor ermittelt
20
  }
21
  _delay_us(480);
22
  return err;
23
}

von Chris (Gast)


Lesenswert?

Hallo Klaus,

danke, ja auf die LED bin ich mal wieder nicht gekommen, komme halt aus 
der Ecke Systemprogrammierung, da gibt es ein Print oder ähnliches fürs 
debugging bzw. Fehler.

Gute Idee mit der LED!

Danke!

woran sehe ich denn, außer der LED, dass einer der DS18S20 erkannt 
wurde.
1
int DS18S20_Init(void)
2
{
3
  uint8_t err=100;
4
  DS18S20_DDR |= 1 << DS18S20_wire;  // 1-wire Leitung auf LOW schalten
5
  _delay_us(480);            // mind. 480µs Low halten
6
7
  DS18S20_DDR &= ~(1<<DS18S20_wire);  // 1-wire Leitung auf HIGH
8
schalten
9
    _delay_us(60);            // nach mind. 60µs wird der
10
Precense-Impuls abgefragt
11
12
  err = (DS18S20_PIN & (1<<DS18S20_wire))  >> DS18S20_wire;  // err = 0
13
Sensor ermittelt

wir schalten ja wieder die 1-wire Leitung auf High und "hoffen" ein 
DS18S20 wird erkannt, richtig?

von perlbastel (Gast)


Lesenswert?

Chris schrieb:
> Hallo perlbastel,
>
> auch mit der oben genannten Änderung ist der Wert der auf dem LCD
> erreicht wird "ALLES OK".
Ok, also scheint der IC korrekt erkannt zu werden. Das ist ja schon mal 
gut. :-)

> Wie kann ich das ganze verstehen, reagiert der µC nun auf die Änderung
> am PC5 Pin?
(Ich gehe mal davon aus du wolltest PD5 schreiben.) Genau, der µP 
resettet den IC und erkennt dann den presence-pulse vom IC.

Jetzt geht es weiter mit dem Senden von Befehlen, s. dazu Datenblatt 
Seite 13f READ/WRITE TIME SLOTS. Ich lese das zum ersten Mal und bin mir 
nicht sicher es richtig verstanden zu haben, deswegen erstmal kein Code. 
Wenn du es nicht selber hinbekommst sag Bescheid dann guck ich mir das 
ganze nochmal genauer an.

von Lutz (Gast)


Lesenswert?

Chris schrieb:
> woran sehe ich denn, außer der LED, dass einer der DS18S20 erkannt
> wurde.

Ich hoffe, du hast erstmal nur einen einzigen Sensor angeschlossen. 
Ansonsten hast du spätestens in der nächsten Runde (=> Kommunikation mit 
dem Sensor) grooooße Probleme.

von Karl H. (kbuchegg)


Lesenswert?

Chris schrieb:

> wir schalten ja wieder die 1-wire Leitung auf High und "hoffen" ein
> DS18S20 wird erkannt, richtig?

Wenn dein Programm sagt, das es den Sensor erkannt hat, dann zieh den 
halt mal vom Bus ab, sodass er definitiv physikalisch nicht mehr 
vorhanden ist. Wenn dann dein Programm korekterweise angibt, dass es den 
Sensor nicht finden konnte, stehen die Chancen nicht schlecht, dass 
zumindest dieser Teil erst mal stimmt.

von perlbastel (Gast)


Lesenswert?

Gute Idee Karl Heinz! Warum kommt man da selber nicht drauf?

von Daniel C. (cecky)


Angehängte Dateien:

Lesenswert?

Hi Chris,

ich habe vor einiger Zeit auch mit dem ds18s20 rumgespielt. Ich habe 
damals ein schönes PDF gefunden, in dem das Handling doch ganz gut 
erklärt ist. Hier geht es zwar um den ds18b20, aber die Ansteuerung war 
glaube ich identisch. Nur in der Auswertung der Daten gab es ein paar 
Unterschiede. Vielleicht hilfts dir ja weiter.

von Klaus (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Chris!

hier mal ein Anhang zu meinem Post!
Da siehst du wie Precense impuls Aussehen muss wenn der Sensor 
angeschlossen ist.

Falls der Sensor nicht angeschlossen ist bleibt das Signal im 
Highzustand nach den 60µs und somit als Fehler ausgewertet.

Mit Init werden alle angeschlossenen Sensoren Antworten aber welcher wer 
ist bekommst so nicht heraus. Aber mindestens einer Antwortet oder 
keiner.

Sinnvollerweise arbeite nur mit einem. Wchtig ist auch das Timing 
einzuhalten.

Dann brauchst noch folgende oder ähnliche Routinen.
Hier nur Auszüge der Prototypen!

void DS18S20_writebit(uint8_t bitwert)
uint8_t DS18S20_readbit(void)
void DS18S20_writebyte(uint8_t data)
uint8_t DS18S20_readbyte(void)
void DS18S20_Conv_T(void)
void DS18S20_Match_Rom( uint8_t data)

Vor allem mit dem Datenblatt solltest du dich dann vertraut machen!

von Klaus (Gast)


Lesenswert?

Hier noch ein Link zu einem guten Dokument!

http://pic-projekte.de/Download/1-Wire-Projekt-V1_3.pdf

von Chris (Gast)


Lesenswert?

perlbastel schrieb:
>> Wie kann ich das ganze verstehen, reagiert der µC nun auf die Änderung
>> am PC5 Pin?
> (Ich gehe mal davon aus du wolltest PD5 schreiben.) Genau, der µP
> resettet den IC und erkennt dann den presence-pulse vom IC.
>
> Jetzt geht es weiter mit dem Senden von Befehlen, s. dazu Datenblatt
> Seite 13f READ/WRITE TIME SLOTS. Ich lese das zum ersten Mal und bin mir
> nicht sicher es richtig verstanden zu haben, deswegen erstmal kein Code.
> Wenn du es nicht selber hinbekommst sag Bescheid dann guck ich mir das
> ganze nochmal genauer an.
Ne, es ist der PIN 28, Bezeichnung seitens Atmel 8 Doku PC5.
Durch den Presence Impuls reagiert der PC5 vom Atmel und erkennt den IC?
Sorry für das erweiterte Nachfragen... I am learning the stuff.

Karl Heinz Buchegger schrieb:
> Wenn dein Programm sagt, das es den Sensor erkannt hat, dann zieh den
> halt mal vom Bus ab, sodass er definitiv physikalisch nicht mehr
> vorhanden ist. Wenn dann dein Programm korekterweise angibt, dass es den
> Sensor nicht finden konnte, stehen die Chancen nicht schlecht, dass
> zumindest dieser Teil erst mal stimmt.
Klar, hab nicht überlegt! Entschuldigt bitte.

Was ich beeindruckend finde unter Bascom (haut mich nicht) sind es ca.15 
Zeílen Code und in C werden es deutlich mehr.
Okay der C Code ist lesbarer.

Vielen Dank an alle die Unterstützen.

@perlbastel: oder @all
kannst du mir erläutern wie ich am PC5 dem DS18S20 ein 0xF0 sende?
Das ganze wird doch immer wieder benötigt, beispielsweise für einen 
Luftdrucksensor oder ähnlichem, wie funktioniert das ?

Mein Verständis was übetragen wird:
0xF0 = 0b11110000
0xCC = 0b11001100
Aber wie??

Viele Grüße
Danke!

von perlbastel (Gast)


Lesenswert?

Chris schrieb:
> Ne, es ist der PIN 28, Bezeichnung seitens Atmel 8 Doku PC5.
Oben stand PD5. Ist das im Code richtig (also PIN_C_, PORT_C_ und 
DDR_C_)?

> Durch den Presence Impuls reagiert der PC5 vom Atmel und erkennt den IC?
Der Pin reagiert nicht. Das ist doch ganz einfach: Der 18s20 wird 
resettet, der µP lässt die Leitung los, der Pullup zieht die Leitung auf 
VCC. Der 1820 zieht nach kurzer Wartezeit die Leitung auf GND. Der µP 
wartet eine gewisse Zeit und prüft dann ob der PC5 (durch den 1820) auf 
low=GND steht. Wenn dies der Fall ist wurde der Sensor erkannt.

Wie ist es denn jetzt? *Wird der Sensor erkannt und gibt es einen Fehler 
wenn du den Sensor abziehst?* Erst wenn das funktioniert lohnt es sich 
weiter zu machen.

> @perlbastel: oder @all
> kannst du mir erläutern wie ich am PC5 dem DS18S20 ein 0xF0 sende?
> Das ganze wird doch immer wieder benötigt, beispielsweise für einen
> Luftdrucksensor oder ähnlichem, wie funktioniert das ?
>
> Mein Verständis was übetragen wird:
> 0xF0 = 0b11110000
> 0xCC = 0b11001100
> Aber wie??
Erkläre ich dir wenn die Sensorerkkennung funktioniert, sonst wird das 
hier zu chaotisch.

von Karl H. (kbuchegg)


Lesenswert?

Chris schrieb:

> Was ich beeindruckend finde unter Bascom (haut mich nicht) sind es ca.15
> Zeílen Code und in C werden es deutlich mehr.

Das gilt aber nicht.
In BASCOM hat dir schon wer vorgearbeitet.

Wenn du ein Auto bauen willst und dann alles fertig kaufst und du nur 
noch den Autoradio montierst, indem du den Normstecker in die Normbuchse 
am Radio steckst, hast du nicht wirklich 'ein Auto gebaut'.

> Okay der C Code ist lesbarer.

Nicht unbedingt.
Aber wenn du da durch bist, verstehst du, wie dieser Bus funktioniert.

Ich will perlbastel nicht vorgreifen, der macht das sehr gut und wenn da 
jetzt zu viele Leute mitquatschn kommt nur Chaos raus. Aber nur soviel: 
Die Daten watscheln da im Gänsemarsch über die Leitung. Das scheint das 
zu sein, was dir am meisten Kopfzerbrechen macht - wie die Daten zum 
Sensor bzw. umgekehrt in die andere Richtung gehen. Ganz einfach: Ein 
Bit nach dem anderen.

von Chris (Gast)


Lesenswert?

Hallo zusammen,


perlbastel:
jepp, der Sensor wird erkannt und als Test ( man bin ich blöd ) habe ich 
den 18S20 abgezogen und ich bekam als information aufs Display 
übertragen "Wir haben ein Problem" - ergo et funktioniert.

>Das ist doch ganz einfach: Der 18s20 wird
>resettet, der µP lässt die Leitung los, der Pullup zieht die Leitung auf
>VCC. Der 1820 zieht nach kurzer Wartezeit die Leitung auf GND. Der µP
>wartet eine gewisse Zeit und prüft dann ob der PC5 (durch den 1820) auf
>low=GND steht. Wenn dies der Fall ist wurde der Sensor erkannt.
Darüber muss ich leider noch ein wenig grübeln. Sorry will mir nicht in 
den Kopf.

Karl Heinz Buchegger:
>Das gilt aber nicht.
>In BASCOM hat dir schon wer vorgearbeitet.
Dann weiß ich auch woher der Befehl im Basom "1wreset" und der "Rest" 
herkommt.

>Aber nur soviel:
>Die Daten watscheln da im Gänsemarsch über die Leitung. Das scheint das
>zu sein, was dir am meisten Kopfzerbrechen macht - wie die Daten zum
>Sensor bzw. umgekehrt in die andere Richtung gehen. Ganz einfach: Ein
>Bit nach dem anderen.
Ja, das ist es worüber ich nachdenke. Danke!

von perlbastel (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Ich will perlbastel nicht vorgreifen, der macht das sehr gut
Oh Danke, sowas aus deinem Munde freut mich!

> und wenn da
> jetzt zu viele Leute mitquatschn kommt nur Chaos raus.
Wohl war. Aber bitte trotzdem mitlesen und mich korrigieren wenn nötig.

Chris schrieb:
>  ergo es funktioniert.
Prima. :-)

> Darüber muss ich leider noch ein wenig grübeln. Sorry will mir nicht in
> den Kopf.
Vielleicht braucht es eine Analogie aus einem anderen Bereich? *Richtung 
Karl Heinz blick* (das ist eines seiner Spezialgebiete!)

So... Weiter gehts. Wir wollen dem 18s20 Daten übermitteln. Wie du schon 
selbst rausgefunden hast lässt sich jede Zahl binär darstellen:
0xF0 = 0b11110000
und (wie von Karl Heinz so schön formuliert) Bit für Bit im Gänsemarsch 
übertragen.

Grundsätzlich funktioniert das so (z.B.):
Wir wollen 0xF0 übertragen. 0xF0 entspricht 0b11110000. Ganz rechts 
steht das LSB (least significant bit, Bit mit der geringsten Wertigkeit 
= 2 hoch 0), damit wollen wir anfangen. Also los:
1
void senden(unsigned char byte)
2
{
3
  int counter; //mitzählen, insgesamt 8 Bits pro Byte
4
  for(counter=0;counter<8;counter++) //Jedes Bit einzelnd betrachten
5
  {
6
     if(byte&(1<<0)==1)
7
     {
8
        //eine 1 ausgeben
9
     }
10
     else
11
     {
12
        //eine 0 ausgeben
13
     }
14
     byte=byte>>1; //nächstes Bit an Position 0 schieben
15
  }
16
}
Interessant an der Sache ist jetzt WIE genau das Bit (nicht Byte!) 
ausgegeben wird. Beim sehr einfachen SPI-Bus beispielsweise wird das Bit 
einfach auf einen Pin (Datapin) gelegt (der Pin ist low oder high je 
nachdem ob das Bit 0 oder 1 ist) und anschließend der Clockpin 
getoogelt.
Wie genau es beim 1-Wire-Bus funktioniert lese ich jetzt nach und melde 
mich dann wieder.

Soweit alles klar?

von perlbastel (Gast)


Lesenswert?

Achso, kurze Zwischenfrage: Hast du ein Oszilloskop? (Ich erklär nachher 
warum ich frage.)

von Chris (Gast)


Lesenswert?

Hallo perlbastel,

>Achso, kurze Zwischenfrage: Hast du ein Oszilloskop? (Ich erklär nachher
>warum ich frage.)
genau das wollte ich eben einmal anschliessen....
Ich habe ein DSO 096 von waterott um vielleicht einen besseren Einblick 
zu bekommen.

vielleicht sehe ich ja etwas :).

von perlbastel (Gast)


Lesenswert?

Gut, wir waren beim Problem Bit-->Bus. Das Datenblatt vom 18s20 ist da 
ziemlich eindeutig (S.13f): Für eine 0 den Bus für mindestens 60µs (und 
max. 120µs, siehe Fig. 11) auf low ziehen. Für eine 1 den Bus auf low 
ziehen und nach frühstens 1µs und spätestens 15µs wieder "loslassen". 
Zwischen 2 Werten eine recovery-time von mindestens 1µs einhalten.

OK:
1
void senden(unsigned char byte)
2
{
3
  int counter; //mitzählen, insgesamt 8 Bits pro Byte
4
  for(counter=0;counter<8;counter++) //Jedes Bit einzelnd betrachten
5
  {
6
     if(byte&(1<<0)==1)
7
     {
8
        //eine 1 ausgeben
9
        DDRC|=(1<<PC5);
10
        _wait_us(5);
11
        DDRC&=~(1<<PC5);
12
13
     }
14
     else
15
     {
16
        //eine 0 ausgeben
17
        DDRC|=(1<<PC5);
18
        _wait_us(80);
19
        DDRC&=~(1<<PC5);
20
     }
21
     byte=byte>>1; //nächstes Bit an Position 0 schieben
22
     _wait_us(2); //mindestens 1 µs warten
23
  }
24
}

Da du ein Oszi hast kannst du sehr einfach überprüfen ob die Funktion 
das tut was sie soll. :-) Am besten du versuchst mal verschiedene Werte 
wie z.B. 0x55 zu senden, der 18s20 ist erstmal nicht nötig.

Wenn alles funktioniert sag Bescheid, dann geht es weiter mit dem 
letzten Teil: Die Antworten vom 18s20 lesen.

von Chris (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Perlbastel,

allmählich komm ich da hinter....

>Da du ein Oszi hast kannst du sehr einfach überprüfen ob die Funktion
>das tut was sie soll. :-) Am besten du versuchst mal verschiedene Werte
>wie z.B. 0x55 zu senden, der 18s20 ist erstmal nicht nötig.
>Wenn alles funktioniert sag Bescheid, dann geht es weiter mit dem
>letzten Teil: Die Antworten vom 18s20 lesen.

0x55 = 01010101 :)

Okay das DSO ist falsch eingestellt, aber ich erkenne langsam was 
passiert... und mein C Verständnis wird auch besser.

von perlbastel (Gast)


Lesenswert?

Chris schrieb:
> allmählich komm ich da hinter....
> Okay das DSO ist falsch eingestellt, aber ich erkenne langsam was
> passiert... und mein C Verständnis wird auch besser.
Das ist Sinn der Sache. :-)

Was noch fehlt ist das Lesen vom 18s20: Datenblatt S. 14f

Willst du es selber versuchen oder soll ich dir eine Funktion schreiben 
die du dann testen kannst?

von Chris (Gast)


Lesenswert?

Hallo Perlbastel,

ich versuche es einmal und sonst schreib ich wieder... wenn ich den 
18S20 ausgelesen bekomme poste ich natürlich auch.

= ich melde mich auf jedenfall :)

Danke.

von Chris (Gast)


Lesenswert?

Hallo zusammen,

was ich noch nicht ganz verstanden habe wofür read / write Time Slot 
ist.
Ich kann dem 18S20 ein High oder Low senden, aber wofür...

Was ich lesen kann aus dem Datenblatt ist, dass ich dem 18S20 eine 0 
oder eine 1 zwischen 60µs bis 120µs senden kann.

von perlbastel (Gast)


Lesenswert?

Chris schrieb:
> Ich kann dem 18S20 ein High oder Low senden, aber wofür...
Du willst doch dem 18s20 Befehle senden oder? Was sind Befehle? Zahlen. 
Und genau diese sendest du zum 18s20 in dem du den Bus für bestimmte 
Zeiten auf low ziehst.

Anders gesagt: Der Bus liegt im Ruhezustand auf high=VCC. Wie oben 
beschrieben können µP und 18s20 den Bus nur auf low ziehen, also ist die 
einzige Möglichkeit 1 und 0 zu codieren die Zeit für welche der Bus auf 
low=GND gezogen wird. Und genau so funktioniert das: Wenn du den Bus für 
5µs auf low ziehst wird eine 1 erkannt, wenn du es für 80µs tust eine 0. 
Das ist einfach eine Konvention die zum 1-Wire-Bus gehört. Die 
Bezeichnung "time slot" kann man einfach ignorieren, das klingt unnötig 
kompliziert. Ein Slot ist hier einfach eine Zeitspanne in der der Master 
(also der µP) auf den Bus zugreift / den Bus auf low zieht.

> Was ich lesen kann aus dem Datenblatt ist, dass ich dem 18S20 eine 0
> oder eine 1 zwischen 60µs bis 120µs senden kann.
Diesen Satz verstehe ich jetzt nicht... Nochmal: Die Länge des 
0-Impulses (also die Dauer für die der Bus auf low geht) bestimmt ob der 
18s20 eine 0 oder eine 1 erkennt. Hm, ich weiß wirklich nicht wie ich 
das anders erklären soll. Karl Heinz, bist du da und hast eine 
Analogie auf Lager?

Das lesen funktioniert (soweit ich das um diese Uhrzeit noch überblicke) 
wie folgt: Den Bus für mindestens 1µs auf low ziehen und anschließend 
den Status (high/low) des Busses einlesen. Ist der Bus high hat der 
18s20 eine 1 gesendet, ansonsten eine 0. Die Daten sind 15µs nach der 
vom µP initierten fallenden Flanke gültig, wenn du den Bus für 2µs auf 
low ziehst hast du also noch 13µs um das vom 18s20 gesendete Bit 
einzulesen.

Guck dir mal Fig. 11 auf Seite 14 an, das ist eigentlich schon 
ausreichend um den Bus anzusteuern.

WELCHE Befehle du dem 18s20 senden musst um dieses und jenes zu tun und 
WANN der 18s20 überhaupt etwas zurücksendet was du per µP lesen kannst 
ist dann noch eine andere Geschichte, dafür muss ich das Datenblatt 
nochmal genau lesen (aber nicht mehr heute abend).

Jetzt bist du dran. :-)

von Chris (Gast)


Lesenswert?

> Ich kann dem 18S20 ein High oder Low senden, aber wofür...
>Du willst doch dem 18s20 Befehle senden oder? Was sind Befehle? Zahlen.
>Und genau diese sendest du zum 18s20 in dem du den Bus für bestimmte
>Zeiten auf low ziehst.
Jetzt hast du mich mißverstanden. Ich dachte mit dem "Read / Write Slot" 
wird der 18S20 noch in einen anderen "Zustand" gesetzt, so hatte ich das 
Datenblatt verstanden, deshalb die Rückfrage mit der 0 und 1. Ich denke 
oft zu kompliziert.

Entschuldigt meine doofen Fragen, mir ist seit eben klar, wie ich Daten 
/ Zahlen mit den Low und High Impulsen in einer gewissen Zeit sende, 
doch hardere ich noch zusätzlich mit dem Verständnis von den 
Bitmanipulationen jetzt noch mit den µs für das empfangen von Daten 
etc.. Das kriege ich auch noch hin.

Was aufjedenfall geholfen hat, ich kann nun noch einfacher die Scripte 
lesen und verstehe schon viel mehr im Gegensatz als vor 3 Tagen.

Many Thanks!
Ersteinmal vielen Dank für deine Mühen!

von Karl H. (kbuchegg)


Lesenswert?

perlbastel schrieb:

> Diesen Satz verstehe ich jetzt nicht... Nochmal: Die Länge des
> 0-Impulses (also die Dauer für die der Bus auf low geht) bestimmt ob der
> 18s20 eine 0 oder eine 1 erkennt. Hm, ich weiß wirklich nicht wie ich
> das anders erklären soll. Karl Heinz, bist du da und hast eine
> Analogie auf Lager?

Ich denk ja eh schon die ganze Zeit nach. Aber mir fällt auch nix 
gscheits ein. Fahnen auf Fahnenmasten mit denen von einem Berg zum 
anderen übertragen werden soll. Rauchzeichen. Passt halt alles nicht, 
weil wir nur 1 Leitung haben auf der Hin und Rück von statten geht. So 
was benutzt im täglichen Leben keiner. Die reine Übertragung kann man ja 
noch erklären: große Rauchwolke ist 1, kleine ist 0. Türklingel lang 
betätigt ist 1, kurz betätigt ist 0 (wer jetzt an Morsen denkt, liegt 
vom Prinzip her gar nicht so weit daneben): Aber den Presence Puls auf 
nur einer Leitung krieg ich überhaupt nirgends unter.

von perlbastel (Gast)


Lesenswert?

@Karl Heinz
Mach dir wegen mir bloss keinen Stress!

Ich warte erstmal mit weiteren Posts bis wieder konkrete Fragen kommen. 
Für heute hab ich eh keine Lust mehr, bin gerade 30km Rad durch 
hügeliges Gelände gefahren... schwitz

von Chris (Gast)


Lesenswert?

Hallo zusammen,

ich habe nochmals von vorne angefangen, Bsp.: "wie lese ich einen 
Schalter aus".
Das Auslesen von vielen verschiedenen Schaltern klappt und das 
anschliessende triggern eines Ausgangsports der dann "was anderes macht" 
auch.
Wenn ich keinen 18S20 an der Schaltung angeschlossen habe wird eine LED 
angesprochen, die mir damit mitteilt das etwas nicht in Ordnung ist.
Ich tue mich noch ein wenig schwer den 18S20 zu lesen.
Liegt sicher auch daran, dass ich erst ein wenig besser in C werden 
muss.

Jetzt eine grundsätzliche Frage:
Kann ich eine Ausgabe, ähnlich wie beim LCD, auch auf einen USB-Augang 
ausgeben? Meine Idee liegt darin, dass ich eventuell Debug Informationen 
im Code implementieren kann um dem "Geheimnis, was keins ist" auf die 
Spur zu kommen?

Ja, der Eintrag jetzt passt nicht ganz zum Thema, aber vielleicht kann 
man mir auf die Sprünge helfen.

Einen Link habe ich auf Mikrocontroller.net gefunden
http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART
Klappt dieser auch mit einem Serial To USB Adapter? (habe kein Serial 
mehr)


Viele Grüße...

von perlbastel (Gast)


Lesenswert?

Chris schrieb:
> Klappt dieser auch mit einem Serial To USB Adapter? (habe kein Serial
> mehr)
Ja, dafür sind die Dinger gebaut. Was nicht (bzw. nur seeeehr langsam) 
funktioniert ist Bit-Banging, aber das willst du nicht.

von Chris (Gast)


Lesenswert?

Hallo,

@perlbastel:
wenn ich direkt von AVR auf USB gehen möchte brauche ich einen:
FTDI 232.
Dieser wiederrum benötigt einen Treiber seitens Windows, wenn ich 
Windows nutzen würden....
Mir fehlt zum Aufbau eh ein wenig "Fogelfutter", habe einen Kondensator 
zu wenig etc...

Zurück zum 18S20:
auch wenn es inwzischen nervt sich es durchzulesen:

Ich habe nun versucht so den 18S20 "zu lesen" bzw. auch zu schreiben, 
ganz sicher völliger quatsch, aber zumindest ist es ein Versuch. Ich 
habe auch direkt kommentiert, damit man vielleicht sieht woran es bei 
meinem Verständnis hapert.
1
int lesen(void)
2
{
3
  int counter; //mitzählen, insgesamt 8 Bits pro Byte
4
  uint8_t byte; // defition for byte will be present into lcd
5
6
  DDRC &= ~(1<<PC5); // als EIngang
7
  PORTC &= ~(1<<PC5); // Pullup auf Masse
8
  //_delay_us(1); // warte
9
10
  for(counter=0;counter<8;counter++) //Jedes Bit einzelnd betrachten
11
    {
12
      if (PINC&(1<<PC5)) // pruefe ob PC5 auf 1
13
      {
14
        byte = byte<<1; // schreibe 1 weg
15
        _delay_us(1);  // warte
16
      }
17
      else // wenn PC5 nicht auf 1
18
      {
19
        byte = byte<<0; // schreibe 0 weg
20
        _delay_us(1); // warte
21
      }
22
    }
23
          _delay_us(14); // warte gesamt
24
    return (byte); // gebe zurueck
25
}

Mit dem Read / write Slot wird es allmählich klarer nur die Umsetzung in 
C ist mir nicht ganz klar, aber es wird besser (persönliche Meinung)


Grüße! Und vielen Dank für die Unterstützung!

von Klaus (Gast)


Lesenswert?

Hallo Chris!

Ich verfolg den Tread ein bischen und stelle Fest, das du den o.g. Link 
keine beachtung schenkst. Dort ist sehr gut beschrieben wie der 1-wire 
Bus funktioniert vorallem das mit dem Time-Slot!

Aber um dir etwas unter die Arme zu greifen schau dir mal den Folgenden 
Code an und Vergleiche mit deinem.




Das hier steht in main:

Das Augenmerk bitte auf die beiden folgenden zeilen richten.

DS18S20_PORT = 0x00;  // Pull_UP aus
DS18S20_DDR &= ~ (1<<DS18S20_wire) | (1<<LED_error);  // 1-wire Leitung 
auf LOW (Eingang) schalten

Der Pull-Up Widerstand zieht den Porteingang auf High also nicht 
versuchen den Port per Befehl auf High oder Low ziehen.


Hier wird nur mit dem DDR - Register auf Low oder High umgeschalten 
nicht mit dem Port Befehl.

// Liest 1-Bit
uint8_t DS18S20_readbit(void)
{
  volatile uint8_t r_bit;            // Rückgabewert
  DS18S20_DDR |= 1 << DS18S20_wire;   // 1-wire Leitung auf LOW 
schalten. Start des Zeit Intervalls
  DS18S20_DDR &= ~(1<<DS18S20_wire); // Master gibt Leitung wieder frei.
  _delay_us(10);
  r_bit = (DS18S20_PIN & (1<<DS18S20_wire)) >> DS18S20_wire;// Bit 
einlesen
  _delay_us(105);
  return r_bit;
}


// Liest 1-Byte
uint8_t DS18S20_readbyte(void)
{
  volatile uint8_t i,rebit, rebyte = 0x00;

  for(i=0; i < 8; i++)
  {
    rebit=DS18S20_readbit();
    if (rebit == 1)
    {
      rebyte |= (1<<i);
    }
  }
  return rebyte;
}

von perlbastel (Gast)


Lesenswert?

Zu FTDI und Linux kann ich leider nichts sagen. :-(

Chris schrieb:
> auch wenn es inwzischen nervt sich es durchzulesen:
Wenn es nerven würde würde ich es nicht tun, mach dir da mal keine 
Sorgen!

Ich hab deinen Code mal kommentiert (jeweils nach dem -->):
1
int lesen(void) -->das passt
2
{
3
  int counter; //mitzählen, insgesamt 8 Bits pro Byte -->OK, hier würde aber uint8_t reichen (braucht weniger Platz, wir zählen ja nur bis 8)
4
  uint8_t byte; // defition for byte will be present into lcd -->Öh...? Verstehe ich jetzt nicht, soll das sowas wie "for byte that will be written to lcd" heissen?
5
6
  DDRC &= ~(1<<PC5); // als Eingang -->OK
7
  PORTC &= ~(1<<PC5); // Pullup auf Masse -->Pullup auf Masse ist unmöglich, Pullup impliziert dass der Widerstand auf VCC gelegt ist. Du schaltest hier den im µP integrierten Pullup AUS.
8
9
  for(counter=0;counter<8;counter++) //Jedes Bit einzelnd betrachten -->Kommentar ist wohl von meiner Schreibroutine übernommen, ich würde eher "insgesamt 8 Bit einlesen" oder so schreiben, aber gut...
10
    {
11
      if (PINC&(1<<PC5)) // pruefe ob PC5 auf 1 -->korrekt
12
      {
13
        byte = byte<<1; // schreibe 1 weg -->NEIN! S.U.
14
        _delay_us(1);  // warte
15
      }
16
      else // wenn PC5 nicht auf 1
17
      {
18
        byte = byte<<0; // schreibe 0 weg -->NEIN! S.U.
19
        _delay_us(1); // warte
20
      }
21
    }
22
          _delay_us(14); // warte gesamt --> ?
23
    return (byte); // gebe zurueck -->passt, geht auch ohne Klammern
24
}
Insgesamt tut deine Funktion überhaupt nicht das was sie soll... Die 
zwei Zeilen die ich mit NEIN gekennzeichnet habe sind leider großer 
Unsinn, bitte lese nochmal in deinen Büchern oder hier im Tutorial das 
Kapitel Bitmanipulation, speziell Schiebeoperationen, nach.

Back to the roots ähh to the Datenblatt (scnr): Seite 14 Read Time Slot

Beschränken wir uns erstmal auf das Einlesen eines einzigen Bits.

Grundgerüst:
1
uint8_t lese_bit(void) //Man kann kein einzelndes Bit zurückgeben, deshalb uint8_t
2
{
3
  uint8_t bit;
4
  
5
  //...
6
  
7
  return bit;
8
}

Alsoo: Zu Anfang den Bus für mindestens 1µs auf 0 ziehen. Dann 
spätestens 15µs nach der fallenden Flanke den Wert vom Bus holen und 
anschließend auf das Ende des Slots (60µs) warten. OK:
1
uint8_t lese_bit(void) //Man kann kein einzelndes Bit zurückgeben, deshalb uint8_t
2
{
3
  uint8_t bit;
4
  
5
  DDRC|=(1<<PC5); //Bus auf low ziehen
6
  _wait_us(2); //mindestens 1µs warten
7
  DDRC&=~(1<<PC5); //Bus wieder loslassen
8
  _wait_us(1); //zur Sicherheit, ein asm("nop") würde wohl auch reichen...
9
  
10
  if(PINC&(1<<PC5)) //Bus abfragen und Wert speichern
11
  {
12
    bit=1;
13
  }
14
  else
15
  {
16
    bit=0;
17
  }
18
  _wait_us(60-2-1+1); //auf das Ende vom Slot warten. 60µs Slotdauer minus die bereits gewarteten 3µs plus eine µs zur Sicherheit
19
  return bit; //und Bit zurückgeben
20
}

Sooo, jetzt ein ganzes Byte: Ich gehe davon aus das LSB (s.o.) kommt 
zuerst, dazu habe ich aber keine Bestätigung im Datenblatt gefunden...
1
uint8_t lese_byte(void)
2
{
3
  uint8_t zaehler;
4
  uint8_t byte=0;
5
  
6
  for(zaehler=0;zaehler<8;zaehler++) //ein Byte sind 8 Bit
7
  {
8
    byte=byte|lese_bit(); //Bit an Position 0 speichern
9
    byte=byte<<1; //Shift um eine Position nach links um Platz zu schaffen
10
    _wait_us(1); //eine µs recovery zwischen zwei Slots
11
  }
12
  return byte; //und Ergebnis zurückgeben
13
}

Den Code von Klaus bitte nicht betrachten, der ist nämlich vielleicht 
nicht ganz falsch aber zumindestens suboptimal... (@Klaus: Begründung 
aus Gründen der Übersichtlichkeit ausgegliedert und hier 
http://www.mikrocontroller.net/topic/260469#2702560 zu finden)


Wann der 18s20 überhaupt Daten zurückgibt und was man dafür senden muss 
habe ich offen gesagt noch nicht kapiert, das ist jetzt deine Aufgabe 
das Datenblatt zu lesen und dem 18s20 mit meinen Funktionen die 
richtigen Daten zu senden bzw. welche zu entlocken!

Ich hoffe es sind keine Fehler drin, bin schon recht müde (langen Tag 
gehabt)... Ich warte dann mal auf Reaktionen deinerseits.

von Chris (Gast)


Lesenswert?

Hallo Klaus,

Klaus schrieb:
> Ich verfolg den Tread ein bischen und stelle Fest, das du den o.g. Link
> keine beachtung schenkst. Dort ist sehr gut beschrieben wie der 1-wire
> Bus funktioniert vorallem das mit dem Time-Slot!

Ja, ich hatte den Link mit einem anderen verwechselt, das PDF was 
dahinter steckt hat es in Sich! Danke für den Hinweis!
Ich werde mir das zur gemüte führen jetzt.

Klaus schrieb:
> Der Pull-Up Widerstand zieht den Porteingang auf High also nicht
> versuchen den Port per Befehl auf High oder Low ziehen.
>
>
> Hier wird nur mit dem DDR - Register auf Low oder High umgeschalten
> nicht mit dem Port Befehl.
Aha, genau da haperts ich habe es noch nicht verinnerlicht wie ich was 
schalte beim µC. Es ist mir "entschuldigt bitte" mir noch nicht klar 
wann ich was schalte muss,ob nun Port (Okay input oder Output, aber da 
haperts an der Bitmanipulation), Register oder Pullupwiderstand.

Dann werde ich mir das PDF mal sorgfältig durchlesen.
Danke!

von Klaus (Gast)


Lesenswert?

@perlbastel

Danke für deine Konstruktive Kritik und hinweise zu Barrel-Shifter.
Die Deklarationen mit Volatile waren für Debugzwecken mit dem Dragon 
damit die nicht Wegoptimiert werden. (Bitte Auge zu drücken.)
Jetzt werde ich mich aber Ausklinken und nur noch verfolgen.

Auch von mir ein Großes Lob an dich perlbastel du kannst die Sache sehr 
gut erklären.

von Weingut P. (weinbauer)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Ich denk ja eh schon die ganze Zeit nach. Aber mir fällt auch nix
> gscheits ein. Fahnen auf Fahnenmasten mit denen von einem Berg zum
> anderen übertragen werden soll. Rauchzeichen. Passt halt alles nicht,
> weil wir nur 1 Leitung haben auf der Hin und Rück von statten geht. So
> was benutzt im täglichen Leben keiner. Die reine Übertragung kann man ja
> noch erklären: große Rauchwolke ist 1, kleine ist 0. Türklingel lang
> betätigt ist 1, kurz betätigt ist 0 (wer jetzt an Morsen denkt, liegt
> vom Prinzip her gar nicht so weit daneben): Aber den Presence Puls auf
> nur einer Leitung krieg ich überhaupt nirgends unter.

http://de.wikipedia.org/wiki/Morsecode

von Chris (Gast)


Lesenswert?

Hallo zusammen,

@perlbastel:

ich bin nun soweit (so behaupte ich), dass ich endlich ein ROM auslesen 
kann, stelle aber sofort fest, dass ich ein Problem mit den "delays" 
habe:

Denn wenn ich ein ROM (ohne printf Befehl) auslesen will, bekomme ich 
nur

"fe fe fe fe fe fe fe fe"

Wenn ich aber zwischen dem wr_byte ein printf setze bekomme ich diese 
Information:

"10d26aa48020074"

1
#define XTAL  8e6
2
#define F_CPU  XTAL
3
#define F_CPU 8000000UL //Your clock speed in Hz (3Mhz here)
4
#define LOOP_CYCLES 8 //Number of cycles that the loop takes
5
#define us(num) (num/(LOOP_CYCLES*(1/(F_CPU/1000000.0))))
6
7
// Include files for compile
8
#include <stdlib.h>
9
#include <stdio.h>
10
#include <avr/interrupt.h>
11
#include <util/delay.h>
12
#include <avr/io.h>
13
#include "uart.h"
14
15
void wr_bit(uint8_t byte) // Man kann kein einzelndes Bit zurückgeben, deshalb uint8_t
16
{
17
  printf(" \n byte"); //<<<<<<-----#####
18
  if(byte&(1<<0)==1)
19
    {
20
        //eine 1 ausgeben
21
        DDRC|=(1<<PC5);
22
        _delay_us(1);
23
        DDRC&=~(1<<PC5);
24
    }
25
    else
26
    {
27
      //eine 0 ausgeben
28
        DDRC|=(1<<PC5);
29
        _delay_us(60);
30
        DDRC&=~(1<<PC5);
31
    }
32
    byte=byte>>1; //nächstes Bit an Position 0 schieben
33
    _delay_us(15); //mindestens 15 µs warten
34
}
35
36
void wr_byte(uint8_t byte)
37
{
38
  uint8_t zaehler;
39
40
  for(zaehler=0;zaehler<8;zaehler++) //ein Byte sind 8 Bit
41
  {
42
    wr_bit(byte&1);
43
    byte>>=1; //Shift um eine Position nach links (rechts) um Platz zu schaffen
44
    _delay_us(1); //eine µs recovery zwischen zwei Slots
45
  }
46
47
}
48
49
uint8_t rd_bit(void) // Man kann kein einzelndes Bit zurückgeben, deshalb uint8_t
50
{
51
  uint8_t bit;
52
53
  DDRC|=(1<<PC5); //Bus auf low ziehen
54
  _delay_us(1); //mindestens 1µs warten
55
  DDRC&=~(1<<PC5); //Bus wieder loslassen
56
  _delay_us(1); //zur Sicherheit, ein asm("nop") würde wohl auch reichen...
57
58
  if(PINC&(1<<PC5)) //Bus abfragen und Wert speichern
59
  {
60
    bit=1;
61
  }
62
  else
63
  {
64
    bit=0;
65
  }
66
  _delay_us(60-2-1+1); //auf das Ende vom Slot warten. 60µs Slotdauer minus die bereits gewarteten 3µs plus eine µs zur Sicherheit
67
  return bit; //und Bit zurückgeben
68
}
69
70
uint8_t rd_byte(void)
71
{
72
  uint8_t zaehler;
73
  uint8_t byte=0;
74
  for(zaehler=0;zaehler<8;zaehler++) //ein Byte sind 8 Bit
75
  {
76
    byte=byte | rd_bit(); //Bit an Position 0 speichern
77
    byte=byte<<1; //Shift um eine Position nach links um Platz zu schaffen
78
    _delay_us(1); //eine µs recovery zwischen zwei Slots
79
  }
80
  return byte; //und Ergebnis zurückgeben
81
}
82
83
// Reset and presence together
84
int reset(void)
85
{
86
  //Pin als Eingang
87
  DDRC &= ~(1<<PC5);
88
  //internen Pullup aus bzw. Pin auf Masse ziehen wenn DDRC.5=1
89
  PORTC &= ~(1<<PC5);
90
  //Reset:
91
  DDRC |= (1<<PC5);
92
  //minimum 480µs
93
  _delay_us(480+20);
94
  //DDRC&=(1<<PC5);
95
  DDRC&= ~(1<<PC5);
96
  //es vergehen mindestens 15µs bevor der IC reagiert
97
  _delay_us(15);
98
99
  //Presence Pulse auswerten:
100
  int timeout=480-15; //nach 480µs-15µs sollte eine Reaktion erfolgt sein.
101
  int error=0;
102
  while(PINC&(1<<PC5)) //solange der Pin high ist
103
  {
104
    timeout--;
105
    if(timeout==0)  //480µs um?
106
    {
107
      error=1;
108
      break;
109
    }
110
    _delay_us(1);
111
  }
112
  if(error)
113
  {
114
    return 1;
115
  }
116
  else
117
  {
118
    return 0;
119
  }
120
}
121
122
// Beginn Programm
123
int main(void)
124
{
125
  // Umleiten der Standardausgabe stdout
126
  stdout = &mystdout;
127
  // initialisiere die UART schnittstelle
128
  uart_init();
129
130
        unsigned char ds1820[9];
131
  unsigned char read_rom[8];
132
  unsigned char i;
133
134
  int returncode = 0;
135
  int returnbyte;
136
137
    // 1. Reset
138
    returncode = reset();
139
    // pruefe returncode
140
    if (returncode == 0)
141
    {
142
      // schreibe SKIP ROM
143
      wr_byte(0x33);
144
      // lese byte ein ds1820
145
      for (i=0;i<8;i++)
146
      {
147
        read_rom[i] = rd_byte();
148
        printf ("\n %x ", read_rom[i]);
149
      }
150
    }
151
    else
152
    {
153
      // LED auf HIGH
154
      DDRB|=(1<<PB0);
155
      PORTB = 1;
156
    }
157
}

Zur Hardware, es ist ein Atmeg8 mit einem externen Oszillator von 8 Mhz.
Die include Datei uart.h wird die benötigt?

Ich habe mit den Delay nun 2 Tage rumgespielt und stelle erstaunliche 
unterschiede fest, zwischenzeitlich habe ich auch schon versucht eine 
Temperatur auszulesen, ich habe im Terminal immer nur eine 127.0 oder 
eine 85.0 ausgeschrieben bekommen.

von Chris (Gast)


Lesenswert?

>Wenn ich aber zwischen dem wr_byte ein printf setze bekomme ich diese
>Information:

ich meinte natürlich wr_bit.

von perlbastel (Gast)


Lesenswert?

Chris schrieb:
> Denn wenn ich ein ROM (ohne printf Befehl) auslesen will, bekomme ich
> nur
>
> "fe fe fe fe fe fe fe fe"
>
> Wenn ich aber zwischen dem wr_byte ein printf setze bekomme ich diese
> Information:
>
> "10d26aa48020074"
Korrekt ist wohl der untere Wert. Laut Datenblatt sind die untersten 8 
Bit 0x10, das würde ja passen (wenn man davon absieht dass der Code 
offensichtlich mit der falschen Bytereihenfolge ausgegeben wird). Ob die 
CRC stimmt müsste man mal nachrechnen. Mich wundert das, eigentlich 
sollte es nur ohne printf() funktionieren. Diese Funktion ist nämlich 
sehr rechenintensiv und zerhaut uns das ganze Timing.

Was mir bei deinem Quellcode auffällt:
>
1
> #define XTAL  8e6
2
> #define F_CPU  XTAL
3
> #define F_CPU 8000000UL //Your clock speed in Hz (3Mhz here)
F_CPU nur einmal definieren.

Und wozu dient das?
1
> #define LOOP_CYCLES 8 //Number of cycles that the loop takes
2
> #define us(num) (num/(LOOP_CYCLES*(1/(F_CPU/1000000.0))))
Für delays F_CPU definieren, delay.h einbinden und die dort 
verzeichneten Funktionen nutzen. Alles andere ist Murks.

> void wr_byte(uint8_t byte)
> ...
> byte>>=1; //Shift um eine Position nach links (rechts) um Platz zu
> schaffen <-- Kommentar falsch

Der Rest sieht soweit gut aus. Am besten mal das Oszilloskop dranhängen 
und die Timings mit denen im Datenblatt vergleichen.

von perlbastel (Gast)


Lesenswert?

Ach so, welchen Compiler nutzt du eigentlich? Sieht irgendwie nicht nach 
GCC aus.

von Chris (Gast)


Lesenswert?

Hallo Perlbastel,

> Korrekt ist wohl der untere Wert. Laut Datenblatt sind die untersten 8
> Bit 0x10, das würde ja passen (wenn man davon absieht dass der Code
> offensichtlich mit der falschen Bytereihenfolge ausgegeben wird).
Falsche byte Reihenfolge? Ich habe heute Nachmittag so etwas ähnliches 
schon überlegt. Werde ich mal umgehend testen bzw. ich muss endlich 
lernen das Datenblatt zu lesen - dann wäre ich vielleicht auch darauf 
gekommen.

> Ob die CRC stimmt müsste man mal nachrechnen.
Ich schaue mal ins Datenblatt vielleicht bekomme ich das heraus?!

> Mich wundert das, eigentlich
> sollte es nur ohne printf() funktionieren. Diese Funktion ist nämlich
> sehr rechenintensiv und zerhaut uns das ganze Timing.
Sehe ich genau so daher meine Frage, wobei ich froh bin wenigstens jetzt 
einen Anhaltspunkt gefunden zu haben.

> F_CPU nur einmal definieren.
> Für delays F_CPU definieren, delay.h einbinden und die dort
> verzeichneten Funktionen nutzen. Alles andere ist Murks.
Hier bräuchte ich ein wenig hilfe, da ich vermute das ich hier einen 
Fehler habe, wie binde ich die delay.h denn ein bzw. wo kann ich dieser 
her beziehen oder ist damit # include util/delay.h gemeint?

> Ach so, welchen Compiler nutzt du eigentlich? Sieht irgendwie nicht nach
> GCC aus.
Ich nutze den avr-gcc mit Eclipse (Indigo) unter Ubuntu 12.04...
Sollte ich doch das WinAVR nutzen? Ich finde das nur sehr sehr träge.

von Martin B. (martin_b35)


Lesenswert?

Zum Thema FT232 und Linux: Das geht bei den
meisten Distributionen innerhalb einer Sekunde nach dem Einstecken.
Taucht dan als /dev/ttyUSBx auf (X steht für die Nummer des Wandlers, 
meist 0)

Gruss, Martin

von perlbastel (Gast)


Lesenswert?

Chris schrieb:
>> Ob die CRC stimmt müsste man mal nachrechnen.
> Ich schaue mal ins Datenblatt vielleicht bekomme ich das heraus?!
Ich guck mal ob ich morgen Zeit finde das nachzurechnen, gegen CRC hab 
ich so eine Abneigung... (Ist eigentlich einfach aber ich strauchele 
doch immer wieder.)

Chris schrieb:
> ist damit # include util/delay.h gemeint?
Genau das. Die beiden Zeilen #define LOOP... und #define us... wegnehmen 
und fertig.

> Sollte ich doch das WinAVR nutzen?
Nene, ist schon OK. Ich fragte mich nur woher die zwei von mir 
angemerkten Zeilen und die englischen Kommentare kommen, jetzt weiß ich 
es: von der Vorlage in Eclipse.

Was das eigentliche Problem betrifft wie schon geschrieben Oszi dran und 
mit dem Datenblatt vergleichen.

von Chris (Gast)


Lesenswert?

Martin B. schrieb:
> Zum Thema FT232 und Linux: Das geht bei den
> meisten Distributionen innerhalb einer Sekunde nach dem Einstecken.
> Taucht dan als /dev/ttyUSBx auf (X steht für die Nummer des Wandlers,
> meist 0)
>
> Gruss, Martin

Danke Martin, nutze ich schon, eine Udev Regel ist auch schon drin damit 
ich mit Minicom kommunizieren kann.

Es handelt sich hierbei um ein "altes" Datenkabel mit PL2303.

Danke!!

von Klaus (Gast)


Angehängte Dateien:

Lesenswert?

@Chris und @perlbastel

>"10d26aa48020074"  Müsste richtig sein.

Im Anhang seht ihr als Beispiel wie das letzte Byte das eingelesen wurde
und wie sich dann der Familiencode zusammen setzt.

Der Familiencode setzt sich ja 64Bit bzw. 8Byte zusammen aber das wisst 
ihr ja.

Gruß
Klaus

von Klaus (Gast)


Lesenswert?

Klaus schrieb:
> Familiencode

Sollte ROM-Code heissen sorry!

von Chris (Gast)


Lesenswert?

@Klaus,

Danke!
Könntest du mir mitteilen, was das für ein Oszilloskop ist? Es sieht mir 
schwer nach einem PC Oszilloskop aus oder liege ich da falsch?

Viele Grüße!!

von Klaus (Gast)


Lesenswert?

@Chris!

> Könntest du mir mitteilen, was das für ein Oszilloskop ist?

Es ist ein RIGOL  DS1202CA

von Chris (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich stelle fest, dass ich beim schreiben 120µs überbrücken muss, was 
eigentlich nicht sein sollte.

Ich habe ein Bild angehängt, wo eigentlich gezeigt werden sollte wie der 
Befehl 0x33 zum DS1820 gesendet wird, mir fällt selber auf, dass ich 
zwar eine 0 sehe aber keine 1. Oder liegt es am Oszilloskop?
(Ich habe mal mit den werten von Klaus seinem Anhang verglichen, bzw. 
vergleichen wollen)
Die 120µS habe ich bei diesem Bild herausgenommen.

Ich habe für die Messung zwischen Reset Impuls und Read Rom Impuls 1 
Sekunde Zeit gelassen um den Read Rom Befehl zu sehen.

PS:
Kennt Jemand ein gutes Oszilloskop, damit ich endlich mal etwas sehe?
@Klaus danke für die Antwort aber 900,- Euro sitzt wirklich nicht drin.

von Chris (Gast)


Lesenswert?

Hallo zusammen,

ich habe mal oszilloskop gespielt und siehe da bei 20µS sekunden ehe ich 
endlich auch eine 1 also liegt es immer noch woanders dran.

von Chris (Gast)


Lesenswert?

Hallo zusammen,

könnte es eventuell am 8 Mhz Oszillator gelegen haben?
Wenn ich nun den internen RC nutze funktioniert die ROM Abfrage ohne 
delay.

Jetzt prüfe ich umgehend, was passiert, wenn ich Uart wieder dazu 
schalte.

von Chris (Gast)


Lesenswert?

Hallo,

Chris schrieb:
> Hallo zusammen,
>
> könnte es eventuell am 8 Mhz Oszillator gelegen haben?
> Wenn ich nun den internen RC nutze funktioniert die ROM Abfrage ohne
> delay.

Daran hat es nicht gelegen.

von perlbastel (Gast)


Lesenswert?

Sorry für die späte Reaktion, hier ist der Teufel los...

Klaus schrieb:
>"10d26aa48020074"  Müsste richtig sein.
Prima, dann kann ich mir das Nachrechnen sparen.

> Kennt Jemand ein gutes Oszilloskop, damit ich endlich mal etwas sehe?
Oszilloskop
speziell Oszilloskop: Vergleichstabelle digitale Tischoszilloskope
und dort speziell Rigol DS1052E

Was das eigentliche Problem betrifft: Ich verstehe die Beschreibung 
nicht... Zeig mal deinen kompletten compilierfähigen Code und 
beschreib genauer was es mit diesen 120µs auf sich hat. Die von mir 
verfassten Funktionen sind zeitkritisch, da darf kein Interrupt, kein 
UART und kein printf dazwischenfunken!

von Chris (Gast)


Lesenswert?

Hallo Perlbastel,

oben ist das komplette Script aufgelistet, ich werde aber nun selber 
versuchen dort den Fehler zu finden, nützt ja nix ich will es lernen.

Ich bekomme demnächst einen Logic Analyser, damit werde ich dann mal 
sehen können ( so denke ich ), wo bei mir der Fehler liegt.

Ich überlege schon ob ich mir nicht noch das Rigol zulege, denn ich 
werde ganz sicher nicht daran vorbei kommen.

Danke.

von perlbastel (Gast)


Lesenswert?

Dann mal viel Erfolg, sag Bescheid wenn du den Fehler gefunden hast.

von Chris (Gast)


Lesenswert?

Hallo Perlbastel,

ein Fehler scheint hier zu liegen:

Chris schrieb:
> int reset(void)
> {
>   //Pin als Eingang
>   DDRC &= ~(1<<PC5);
>   //internen Pullup aus bzw. Pin auf Masse ziehen wenn DDRC.5=1
>   PORTC &= ~(1<<PC5);
>   //Reset:
>   DDRC |= (1<<PC5);
>   //minimum 480µs
>   _delay_us(480+20);
>   //DDRC&=(1<<PC5);
>   DDRC&= ~(1<<PC5);
>   //es vergehen mindestens 15µs bevor der IC reagiert
>   _delay_us(15);
>
>   //Presence Pulse auswerten:
>   int timeout=480-15; //nach 480µs-15µs sollte eine Reaktion erfolgt sein.
>   int error=0;
>   while(PINC&(1<<PC5)) //solange der Pin high ist
>   {
>     timeout--;
>     if(timeout==0)  //480µs um?
>     {
>       error=1;
>       break;
>     }
>     _delay_us(1);
>   }
>   if(error)
>   {
>     return 1;
>   }
>   else
>   {
>     return 0;
>   }
> }

Nach dem prüfen wird in der Beschreibung / Dokumentation vom DS18S20 von 
424µs Wartezeit nach dem Presence gesprochen. Eingesetzt verglichen mit 
dem LogicAnalyzer scheint ok zu sein. Der Read ROM 0x33 wird danach auch 
richtig übertragen und der DS18S20 reagiert korrekt.

Ich prüfe mal weiter.

von Chris (Gast)


Lesenswert?

Hallo zusammen,

ich habe es seit Freitag am tippeln....
Ich kann einen DS18S20 ansteuern auslesen umrechnen und die Grad auf dem 
LCD Display anzeigen.

Jetzt aber mal eine ernsthafte Frage an die, die schon länger sich mit 
der Materie auseinander gesetzt haben.

Der Code verbraucht nun ca. 79% vom – 8Kbytes of In-System 
Self-programmable Flash program memory des Atmega8. Noch eine 
Uhrzeitfunktion rein und der Speicher ist 100.3% gefüllt und dieser kann 
dann nicht mehr übertragen werden.

Ist der C-Code so schlecht?
Okay, jedes umwandeln im Code des Float in einen Charakter kostet Platz, 
aber ich finde das echt heftig!
muss ich jetzt doch Assembler lernen? ;-)
Sorry, wahrscheinlich wurde diese Frage 100.000.000 mal gestellt, aber 
gebt mir bitte einen Tipp.

Vielen Dank!

von Chris (Gast)


Lesenswert?

Okay, nach einigen probieren und nicht genutzten Variablen habe ich 
wieder Platz, und ja

http://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung

der Link ist Gold wert!

Ich sehe auch das meine Umwandlungen von Float nach String viel Platz 
brauchen.

von perlbastel (Gast)


Lesenswert?

Chris schrieb:
> Ich kann einen DS18S20 ansteuern auslesen umrechnen und die Grad auf dem
> LCD Display anzeigen.
Prima dass es jetzt funktioniert!

Was die Codegröße betrifft: float sollte man meiden, stattdessen 
Festkommazahlen nehmen.

von Cyblord -. (cyblord)


Lesenswert?

Chris schrieb:

> Ist der C-Code so schlecht?
Ja genau, wenn man nicht schwimmen kann ist die Badehose schuld. Also 
mal ehrlich, wenn ich mir den Thread hier so angucke. Was ein rumgeiere 
für die Ansteuerung eines popligen DS18B20. Ich hab damals einen Abend 
mit dem Datenblatt verbracht und das Ding war angesteuert. Also da weiß 
ich schon wie DU programmierst und dann beschwerst du dich dass dein 
Code aufgebläht ist. Lern halt mal wie man mit Datentypen und 
Speicherplatz ordentlich umgeht.

gruß cyblord

von perlbastel (Gast)


Lesenswert?

cyblord ---- schrieb:
> [mecker]
Schlechten Tag gehabt? Sei nicht so aggressiv, jeder hat mal klein 
angefangen...

von Cyblord -. (cyblord)


Lesenswert?

perlbastel schrieb:
> cyblord ---- schrieb:
>> [mecker]
> Schlechten Tag gehabt? Sei nicht so aggressiv, jeder hat mal klein
> angefangen...

was heißt da "gehabt"? Er dauert an.

von Chris (Gast)


Lesenswert?

cyblord ---- schrieb:
> Chris schrieb:
>
>> Ist der C-Code so schlecht?
> Ja genau, wenn man nicht schwimmen kann ist die Badehose schuld. Also
> mal ehrlich, wenn ich mir den Thread hier so angucke. Was ein rumgeiere
> für die Ansteuerung eines popligen DS18B20. Ich hab damals einen Abend
> mit dem Datenblatt verbracht und das Ding war angesteuert. Also da weiß
> ich schon wie DU programmierst und dann beschwerst du dich dass dein
> Code aufgebläht ist. Lern halt mal wie man mit Datentypen und
> Speicherplatz ordentlich umgeht.
>
> gruß cyblord

Mhh,
eigentlich hat perlbastel alles schon geschrieben was man dazu sagen 
kann, aber genau solche Kommentare sind es die es Einsteigern sehr 
Schwer machen - vernünftige und sachliche Fragen zu stellen zusätzlich 
entmutigen diese Worte jeden Anfänger sofort.

Ich habe seit Beginn der versuchten Abfrage eines DS18S20 nichts mit C 
bzw. nur sehr wenig zu tun gehabt, ich bin froh gewesen, das perlbastel 
so viel Zeit in diesen Thread gesteckt hat und nicht aufgegeben hat mich 
zu unterstützen. Hierfür meinen Dank an dieser Stelle.

Ich hätte gerne gewusst wie Sie angefangen sind und wenn Sie sich 
erinnern können - denken Sie mal darüber nach. Egal wo, egal wann, jeder 
fängt mal klein an.

Schönen Abend.

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.