mikrocontroller.net

Forum: Compiler & IDEs DS1820


Autor: Sascha (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Ich will einen DS18S20 auslesen... Ich benutze ienen Controller von 
Atmel mit nem Takt von 7,37 MHz.

Die Prozeduren zum Reset, Schreiben und Lesen müssten eigentlich 
stimmen, hab mal ein Oszi dran gehangen... Doch irgendwie haut das noch 
nicht ganz hin...

Könnt ihr mir weiter helfen? Hab meinen C-Code angehängt...

Danke schön!

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mir würde auch schon reichen, wenn mir jemand sagen kann, wie ich die 
read_bit(); Anweisung gestalten kann???

MfG

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum versuchst du, Fahrräder noch einmal zu erfinden?  Die Funktion
delay1() wird auf einem GCC 4.x zu gar nichts mehr evaluieren, weil
sie laut Meinung des Compilers nichts macht.  Die Funktion delay_ms()
verzögert zwar irgendwas, aber was lässt dich annehmen, dass sie
etwas Millisekundenartiges darstellen würde?

Tu dir einen Gefallen, und nimm den Krempel aus <util/delay.h>, dafür
ist er nämlich da.

Ich hatte aus Interesse auch mit mit einem DS18S20 (?) angefangen,
hier das Resultat:
/*
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42):
 * <joerg@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return.        Joerg Wunsch
 * ----------------------------------------------------------------------------
*/
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>

#include <avr/io.h>
#include <util/crc16.h>

#include "1wire.h"

# define F_CPU 8000000UL
# include <util/delay.h>
# include <avr/io.h>
# include <avr/interrupt.h>

#define concat(a, b) a##b
#define indir(a, b) concat(a, b)
#define ow_port indir(PORT, OW_PORT)
#define ow_pin  indir(PIN, OW_PORT)
#define ow_ddr  indir(DDR, OW_PORT)

static inline void
clear_dq(void)
{
  ow_port &= ~(1 << OW_PIN);
  ow_ddr  |= (1 << OW_PIN);
}

static inline void
set_dq(void)
{
  ow_port &= ~(1 << OW_PIN);
  ow_ddr  &= ~(1 << OW_PIN);
}

static inline uint8_t
get_dq(void)
{
  return (ow_pin & (1 << OW_PIN)) == 0;
}

bool
ow_reset(void)
{
  bool presence;

  cli();
  clear_dq();
  _delay_ms(0.48);
  set_dq();
  _delay_ms(0.07);
  presence = get_dq();
  sei();
  _delay_ms(0.24);

  return presence;
}

static uint8_t
ow_read_bit(void)
{
  bool res;

  cli();
  clear_dq();
  set_dq();
  _delay_us(15);

  res = get_dq();
  sei();
  _delay_us(60);

  return res? 0: 1;
}

static void
ow_write_bit(bool bit)
{
  cli();
  clear_dq();
  if (bit)
    set_dq();
  _delay_ms(0.1);
  set_dq();
  sei();
}

uint8_t
ow_read_byte(void)
{
  uint8_t i;
  uint8_t val = 0, mask;

  for (i = 0, mask = 1; i < 8; i++, mask <<= 1)
    {
      if (ow_read_bit())
        val |= mask;
      _delay_ms(0.1);
    }

  return val;
}

void
ow_write_byte(uint8_t val)
{
  uint8_t i;
  uint8_t mask;

  for (i = 0, mask = 1; i < 8; i++, mask <<= 1)
    {
      ow_write_bit(val & mask);
    }
  _delay_ms(0.1);
}

uint8_t
ow_checkcrc(uint8_t *data, uint8_t nbytes)
{
  uint8_t crc = 0, i;

  for (i = 0; i < nbytes; i++)
    crc = _crc_ibutton_update(crc, data[i]);

  return crc; // must be 0
}

void
Read_Temperature(void)
{
  uint8_t get[9];
  uint8_t temp_lsb,temp_msb;
  uint8_t k;

  ow_reset();

  ow_write_byte(0xCC); //Skip ROM
  ow_write_byte(0x44); // Start Conversion

  for (uint16_t i = 0; i < 750; i++)
    _delay_ms(1);

  ow_reset();

  ow_write_byte(0xCC); // Skip ROM
  ow_write_byte(0xBE); // Read Scratch Pad

  printf("ScratchPAD DATA = ");
  for (k = 0; k < 9; k++){
    get[k] = ow_read_byte();
    printf("%02X ", get[k]);
  }
  k = ow_checkcrc(get, 9);
  printf(" (CRC %s)\n", k == 0? "OK": "FAIL");

  temp_msb = get[1]; // Sign byte + lsbit
  temp_lsb = get[0]; // Temp data plus lsb
  if (temp_msb <= 0x80){
    temp_lsb = (temp_lsb / 2);
  } // shift to get whole degree
  temp_msb = temp_msb & 0x80; // mask all but the sign bit
  if (temp_msb >= 0x80) {
    temp_lsb = (~temp_lsb)+1;
  } // twos complement
  if (temp_msb >= 0x80) {
    temp_lsb = (temp_lsb / 2);
  }// shift to get whole degree
  if (temp_msb >= 0x80) {
    temp_lsb = ((-1) * temp_lsb);
  } // add sign bit

  printf("T = %d °C\n", (int)temp_lsb ); // print temp. C
}

void
Read_ROMCode(void)
{
  uint8_t n;
  uint8_t dat[8];

  printf("Reading ROM Code\n");

  ow_reset();

  ow_write_byte(0x33);

  printf("ROM Code = ");
  for (n = 0; n < 8; n++) {
    dat[n] = ow_read_byte();
    printf("%02X ", dat[n]);
  }
  n = ow_checkcrc(dat, 8);
  printf(" (CRC %s)\n", n == 0? "OK": "FAIL");
}
Hier ist noch die 1wire.h:
#include <stdbool.h>

#define OW_PORT B
#define OW_PIN  7

extern bool ow_reset(void);
extern void Read_ROMCode(void);
extern void Read_Temperature(void);
Bitte mit -Os und -std=gnu99 compilieren.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie wärs mit nem Blick in die Codesammlung ?


Beitrag "DS1820, DS18B20 in C"


Peter

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich wollte eigentlich nur wissen warum mein code net geht! Die Beispiele 
ahbe ich ja bereits studiert und angewendet!

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha wrote:
> Ich wollte eigentlich nur wissen warum mein code net geht!

Du nimmst den ganzen Port C, Du darfst aber nur einen Pin nehmen.


Peter

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na das is doch egal ob nu ein Pin ausgang is oder net, den Status erfrag 
ich mit PINC0, also nur einem Pin...

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie du aber mit den aus der Luft gegriffenen Warteschleifen ein
definiertes Timing erreichen willst, haste mir immer noch nicht
verraten.  Timing ist aber zwangsweise bei 1-wire das A und O.

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dieses delay1(); ist eine von mir geschriebene Schleife, hab die so 
genannt... Sie zählt von 0 bis zum eingegebenen Wert... Muss im 
Quelltext wohl verloren gegangen sein...

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha wrote:

> Dieses delay1(); ist eine von mir geschriebene Schleife, hab die so
> genannt... Sie zählt von 0 bis zum eingegebenen Wert... Muss im
> Quelltext wohl verloren gegangen sein...

Nein, ist nicht verlorengegangen.  Wie ich dir aber schon einen
Kilometer weiter oben geschrieben habe (interessiert dich eigentlich,
welche Gedanken sich die Leute um dein Zeug machen?), macht sie nur
aus Sicht des Compilers rein gar nichts, folglich eliminiert er sie.
Das ist sein gutes Recht.  Du hast keinen Anspruch auf einen
bestimmten Assemblercode, sondern nur einen Anspruch darauf, dass der
generierte Assemblercode funktional genau das tut, was du in C
hingeschrieben hast.  Eine Zuweisung zu einer Variablen, die nie
wieder benutzt wird, hat funktional keinen Effekt.

Daher mein Hinweis, bitte doch statt deines selbstgerödelten und nicht
wirklich verstandenen (geschweige denn im Assemblercode getimeten)
Codes bitte die Funktionen aus <util/delay.h> zu benutzen.  Das Timing
ist das A und O bei 1-wire (das liegt in der Natur der Sache), da
solltest du besser auf Bewährtes zurückgreifen, statt sinnlose
Fahrräder noch einmal zu erfinden.  Als Beispiel dann mein Code, der
ungefähr dasselbe tun sollte wie deiner, außer dass ich eine minimale
Hardwareabstraktion bereits von vornherein eingeplant habe (die deinem
Code aber sicher auch gut zu Gesicht stünde).

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha wrote:
> Na das is doch egal ob nu ein Pin ausgang is oder net, den Status erfrag
> ich mit PINC0, also nur einem Pin...

Tust Du eben genau nicht !!!
unsigned char read_bit(void)
...
  bitstat=PINC;
  return(bitstat);
...
    if(read_bit())
                        value|=0x01<<i;


Peter

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie realisiere ich:

"Bitte mit -Os und -std=gnu99 compilieren."

mit AVR Studio4?

läuft das Programm?

MfG

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sebastian wrote:

> Wie realisiere ich:
>
> "Bitte mit -Os und -std=gnu99 compilieren."
>
> mit AVR Studio4?

Indem du dich durch die entsprechenden Optionen durchklickerst.

Oder gleich ein externes Makefile nimmst. ;-)

> läuft das Programm?

Es ist keins, sondern nur ein paar Funktionen.  Ein lauffähiges
Programm musst du dir schon selbst drumschreiben.

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, danke...

Würde es gehen, wenn ich in eine Mainfunktion Read_Temperature(); 
schreibe, rein theoretisch müsste doch dann ein Tempwert heraus kommen?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe ungefähr sowas in meinem Testprogramm:
  bool ow_presence;

...
  ow_presence = ow_reset();

  printf("Hello, there, 1-wire device is%s present!\n",
         ow_presence? "": " not");
  if (ow_presence)
    {
      Read_ROMCode();
      Read_Temperature();
    }

Autor: Michael Rubitschka (rubi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Sascha

Ich würd ja den Code vom Jörg nehmen da er vorbildlich programmiert ist.
Wenn Du jedoch probieren möchtest ob dein Code funzt, dann definiere
die Variablen im delay Unterprogramm zusätzlich mit der volatile
Anweisung. Die sagt dem Compiler nämlich das er die Variable nicht 
wegoptimieren darf.

LG
Michael

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mmmh ich hab das Programm 1 zu 1 übernommen...
funzt aber net... ich seh aufm Oszi nicht, dass das scratchpad 
ausgegeben wird... Ich benutze nen Quarz mit 7,3728MHz... Des Weiteren 
benutze ich Port G0...

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich benutze nen Quarz mit 7,3728MHz...

Hast du dann auch F_CPU angepasst?

Außerdem solltest du wohl auch die printf()s rausnehmen, es sei denn,
du hast stdio irgendwie ohnehin bereits konfiguriert.

Autor: Michael Rubitschka (rubi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wundert mich das das ohne die Datei "1wire.h" überhaupt compiliert.
Ein Codefragment soll in der Regel nur zeigen wie es gehen würde.

LG
Michael

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wundert mich das das ohne die Datei "1wire.h" überhaupt compiliert.

Steht doch mit dabei...

Autor: Michael Rubitschka (rubi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ups entschuldige, habe ich übersehen,...

LG
Michael

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Ja ich habe das auf 7372800 geändert, die printf hab ich alle 
rausgenomen... Ich probier morgen nochma ein bissel... meld mich dann 
wieder... Was ich fragen wollte: die Anweisung _delay_ms(0.48); müsste 
doch 480µs verzögern... laut Oszi ist das aber weit mehr...? Hängt das 
eventuell von meiner Hardware ab?

MfG

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> die Anweisung _delay_ms(0.48); müsste
> doch 480µs verzögern...

Genau.

> laut Oszi ist das aber weit mehr...?

Zufällig 3.53 ms?

.

.

.

.

.

.

.

.

.

.
Schalt deinen Quarz bitte ein, dein AVR läuft noch mit dem 1-MHz-
RC-Oszillator...

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

Zeit liegt bei 1ms... hab geschaut interner Oszillator müsste 
deaktiviert sein...

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Optimierung ist aber eingeschaltet, oder?

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... Das weiß ich nicht... Wo kann man denn diese Optimierung 
einstellen... bzw. wie muss ich sie konfigurieren?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wer generiert denn dein Makefile?  (Ich vermute mal, du hast es sicher
nicht mit der Hand geschrieben.)

Bei Mfile:

Makefile -> Optimization level -> s  (ist aber dort die Voreinstellung)

Bei AVR Studio musste mal selbst gucken, hab' ich hier nicht.

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es geht... besten dank!

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine Frage hätte ich dann doch noch :-)
die Temperatur wird in ganzen grad ausgegeben? Wie kann ich jetzt den 
Wert auf Kommastellen ausgeben?

Autor: Fisch (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich versuche jetzt schon seit gestern den ds18s20 zum laufen zu 
bekommen, es gelingt mir aber nicht. Ich wollte ganz einfach anfangen 
und erstmal den Presence Puls abfragen und genau da liegt schon das 
Problem. Der Sensor antwortet einfach nicht. Am Sensor kann es 
eigentlich nicht liegen, da ich schon andere ausprobiert habe. Ein Oszi 
hab ich leider auch nicht zur Hand. Zum testen habe ich den Code von 
Jörg Wunsch benutzt und nur per main()die Funktion ow_reset() aufgerufen 
(siehe Anhang). Ich benutze eine AtMega32@16MHz und betreibe den Sensor 
mit eigener Spannungsversorgung und 4,7k Pullup an der Datenleitung. Wer 
schön wen jemand von euch eine Idee hat.

Gruß Fisch

Autor: Fisch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo.
Nachdem ich den Sensor jetzt parasitär angschlossen funktioniert es 
schon besser. Ich kann selbst die Register auslesen. Aber es ist schon 
wieder ein neues Problem aufgetaucht. Wenn ich die Temperaturregister 
auslese bevor ich eine Wandlung durchgeführt habe, sendet der DS mir 85° 
was ja auch seine Richtigkeit hat. Nur wenn ich vorher eine Messung 
mache, zeigt er mir immer 127° (bzw. 00 FF) an. Ich warte zwischen 
Messung und dem Auslesen >1s. Hat jemand von euch solch ein Problem 
schonmal gehabt?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.