mikrocontroller.net

Forum: Compiler & IDEs DS18S20, Atmega8 und Winavr


Autor: Matthias V. (snailhouserock)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo *,

z.Z. versuche ich mich an der Temperaturmessung mit einem DS18S20 an 
einem Atmega8 16Mhz. Die Code-Beispiel die ich bisher gesehen habe, 
laufen bei mir nicht.

Im Prinzip kann ich auch Kontakt zwischen dem DS18S20 und dem Atmega8 
herstellen. Nur stoße ich auf folgendes Problem (siehe Auszug der 
Debugausgabe):

>>Read Scratchpad
>>Read Scratchpad.Done
0X1E 0X20 0XA 0XFE 0XFE 0X8C 0X96 0X0 0X6E
>>Calculate Temperature
>>check crc failed
55 Celsius
>>Read Scratchpad
>>Read Scratchpad.Done
0X96 0X20 0X8 0XFE 0XFE 0X8C 0X96 0X0 0X6E
>>Calculate Temperature
>>check crc failed
55 Celsius

1. die Messung fällt durch die CRC-Prüfung
2. Bytes 4 und 5 sollten eigentlich per default auf 0xFF stehen hier 
fehlt wohl in bit
3. die 55 Grad Celsius sind natürlich gefühlt nicht nachvollziehbar ;-)
Meine Code hab ich am Anhang gepostet!
Also, ich bin langsam ratlos und verbringe schon ein weilchen mit dem 
Problem. Was läuft hier falsch?
Vielen Dank schonmal fürs Anschauen, für Kommentare und 
Hilfstellungen!!!
Gruss,
Matthias

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

void uDelay(u8 count)
{
    while(count--);                 
}

void iDelay(unsigned int count)
{
    while(count--); 
}

Diesen Code kannste voll in der Pfeife rauchen, sowas macht man nicht.
Der AVR-GCC lacht sich nen Ast darüber und optimiert ihn weg.

Und für die Delays schreibt man keine kryptische Zahlen.
Die stimmen, wenn überhaupt, nur für eine bestimmte CPU, bei einer 
bestimmten Frequenz mit einer bestimmten Compilerversion und einer 
bestimmten Optimierungsstufe.
Das ist völlig unportabler und unzuverlässiger Code.


Du mußt die Bibliotheksfunktion void _delay_us(double __us) aus delay.h 
benutzen (vorher natürlich F_CPU definieren).


Warum nimmst Du nicht Code aus der Codesammlung?


Peter

Autor: Matthias V. (snailhouserock)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

Danke fürs Schauen. Die Delays hab ich mit dem Speicheroszilloskop 
kalibriert. Hätte der Compiler diese "wegoptimiert" hätte ich auf dem 
DSO nichts gesehen, gelle?
Ich will nicht ausschließen, daß das Problem im Timing sitzt. Aber Deine 
Annahme kann ich leider nicht bestätigen.

Ich hab mich an Deinem Code versucht, ihn aber nicht zum Laufen 
gebracht. Ferner ist die Temperaturmessung ein Add-On zu einem weiteren 
Programmmodul. Mit dem Code hier komme ich vom Speicher her hin. Die 
portable Variante von Dir würde vom Speicher schon nicht in Frage 
kommen.

Viele Grüße,
Matthias

Autor: Matthias V. (snailhouserock)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rehi, klar ist es so schwierig, den Code auch praktisch zu testen. Kein 
Zweifel, sorry, Matthias

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias V. wrote:

> Die Delays hab ich mit dem Speicheroszilloskop kalibriert.

Sobald du die Optimierung des Compilers einschaltest sind die Schleifen 
weg. Versprochen. Nur solange du mit -O0 arbeitest werden sie 
funktionieren.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde das Beispiel auf einem Pollin Funk-AVR-Evaluationsboard 
ausprobieren. Allerdings mit 12 MHz Atmega8 statt 16 MHz. Sensor D18S20 
ist vorhanden, denn ich wollte eh was damit experimentieren.

Schickst du mir Infos, wie du den Sensor passend zu deiner Source 
angeschlossen hast?

Auf die Schnelle habe ich diesen Abschnitt gefunden

// configure your port here
// set pin mask
#define wmask     0x00
// set 1-wire pin for output
#define wOut      DDRC |= wmask
// set 1-wire pin for input (bus released)
#define wIn       DDRC &= ~wmask
// set 1-wire bus high
#define wH        PORTC |= wmask
// set 1-wire bus low
#define wL        PORTC &= ~wmask
// get 1-wire bus input (bus released)
#define wR        PINC & wmask

Aber ich kann nicht sehen, wie das mit wmask 0x00 arbeiten soll. Hier 
müsste IMHO ein Bit gesetzt sein - das Bit für den Pin, an dem der 
Sensor hängt.

Und nochwas brauche ich zum Nachstellen der Situation, damit wir über 
das gleiche reden: hast du den Sensor direkt anschlossen oder noch 
zusätzliche Hardware verwendet? Wenn letzteres, schick bitte eine 
Skizze/Schaltplan.

BTW: Ist das von dir angepasster Fremdcode? Wenn ja, schick auch einen 
Link oder einen Hinweis, wo das Original zu finden ist. Danke.

Autor: Martin L. (melvin_the_moose)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das "Wegoptimieren" könnte man verhindern, indem man die Signatur der 
Funktionen zu
void uDelay(u8 count)

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe mal eine deiner Schleifen nachgezählt. uDelay(0) frisst beim 
GCC 4.1 bereits ca. 43 Takte. Bei 4.3 sind's noch ein paar mehr. Mit 
welcher Taktfrequenz arbeitest du?

Autor: Matthias V. (snailhouserock)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo *,

ich arbeite mit -O0. Eben weil der Compiler die while-Schliefen 
zerflückt.

In den Sourcen ist ein Bug. Man kann wmask auf 0xFF setzen. Für einen 
Sensor reicht das. Ich hatte den Fehler zu spät bemerkt und fehlerhafte 
Sourcen gepostet. Die Ausgaben oben sind mit wmaxk 0xFF entstanden.

Vielen Dank und Gruss,
Mattahis

Autor: Matthias V. (snailhouserock)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Andreas,

> Ich habe mal eine deiner Schleifen nachgezählt. uDelay(0) frisst beim
> GCC 4.1 bereits ca. 43 Takte. Bei 4.3 sind's noch ein paar mehr. Mit
> welcher Taktfrequenz arbeitest du?

Mit 16 MHz arbeitet der Atmega im STK.

Zur Beschaltung. Ich ziehe VCC vom STK500 und lege GND auf das STK500.
Über VCC zur Datenleitung hängt noch ein Pull-Up-Widerstand mit 4,7 
kOhm.

Viele Grüße,

Matthias

Autor: Martin L. (melvin_the_moose)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uups...
"Vorschau" und "Abschicken" verwechselt...

Das "Wegoptimieren" könnte man verhindern, indem man die Signatur der
Funktionen in
void uDelay(volatile u8 count)
und
void iDelay(volatile unsigned int count)
ändert.
Dennoch muß dann für jede Compilerversion / Optimierungsstufe neu 
"kalibriert" werden, da der Compiler verschiedenen Möglichkeiten hat, 
die Schleifen in Maschinencode zu übersetzen.
Also: wie man es dreht, nicht zu empfehlen...

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias V. wrote:

> ich arbeite mit -O0. Eben weil der Compiler die while-Schliefen
> zerflückt.

Falscher Ansatz.

Bei uDelay() frisst jede Iteration je nach Compiler 10 oder 21 Takte. 
Viel Vergnügen beim Update des Compilers.

Autor: Matthias V. (snailhouserock)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo *,

soeben hab ich mir Peters Code nochmal angeschaut. Der Code lief nicht, 
weil ich lediglich in 1WIRE.C die Ports angepaßt hatte. Ganz übersehen 
hatte ich die Definitionen in main.h.

Meanwhile liest der DS18S20 die richtige Temperatur und damit ist mein 
Ziel erreicht.

Fazit: Mit diesem Fehler wieder was gelernt.

Daher Euch und ganz besonders Peter vielen Dank für die Anregungen und 
Hinweise!!!!!

Damit geht mein DS18S20 Projekt nach /dev/null ;-)

Und wie ich gerade sehe, gibt es Überschneidungen im Timer-Interrupt. 
Ich nutze den gleichen Timer fürs PWM zur Ansteuerung eines Motors. 
Shit.

Viele Grüße,

Matthias

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sensor läuft. Ich habe beim Aufbau gesehen, dass es ein DS1820 ist und 
kein DS18S20. Ausgabe s.u. Allerdings merke ich von den 48 °C nichts ;-)

>>Reset device
>>device found!
>>Skip Rom
>>Start conversation
>>Reset device 2
>> device found!
>>Skip Rom
>>Read Scratchpad
>>Read Scratchpad.Done
0 0 0XA0 0XF0 0XF0 0X60 0XB0 0 0X60
>>Calculate Temperature
>>check crc failed
48 Celsius

Wegen der anderen Taktrate (12 MHz statt 16 MHz) musste ich _delay_us 
verwenden. Weitere Anpassungen betreffen die vielen Warnings.

Ich fuxe mich jetzt ins DS1820 Datenblatt rein.

EDIT: Oder auch nicht.

> Damit geht mein DS18S20 Projekt nach /dev/null ;-)

Ich will ja keine Leiche fleddern ;-)

Autor: Matthias V. (snailhouserock)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Stefan,

dann bleib ich mal mit am Ball. Bin gespannt! Obwohl Peters Projekt nun 
bei mir läuft würde ich schon gerne doch mein Projekt weiter im Auge 
behalten, weil ich zur Steuerung eines Motors schon den Timer 1 
verwende. Und ich fühle mich im Moment nicht sicher genug Peters und 
mein Geraffel zusammen zu führen.

Viele Grüße,

Matthias

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan "stefb" B. wrote:

> Allerdings merke ich von den 48 °C nichts ;-)

Sei froh, dass es kein DS18B20 ist. Dann wären es 384°.

Autor: Stefan B. (stefan) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
In meiner Bude sind es 19,5 °C. Die Fehlerursache ist fies zu finden. 
Der Sensor liefert korrekte Daten (s. Anhang) aber die Ausgabe meldet 
Schrott und CRC Probleme. Der Fehler steckt in diesem Codestück:

// configure your port here
// set pin mask
#define wmask     (1<<PC4);
// set 1-wire pin for output
#define wOut      DDRC |= wmask
// get 1-wire bus input (bus released)
#define wR        PINC & wmask
// ...

u8 wRxbit (void)
{
   u8 data;

   wOut;wL;
   DELAY__1US;       // 10.58us
   wIn;
   DELAY_10US;       // Lesen innerhalb der ersten 15 uS
   data=wR;
   DELAY_60US;       // 61.82us
   return data;
}

u8 wRxbyte (void)
{
    u8 i;
    u8 bit;
    u8 data;

    data=0x00;
    for (i=0; i<8; i++)
    {
#if 1
        // Ohne Fehler
        // allerdings auch nicht multipinfähig! 
        data >>= 1;
        bit=wRxbit();
        if ( bit )
          data |= (1<<7);
#else
        // Mit Fehler
        // Das geht nur gut, wenn wRxbit() 1 oder 0 zurückliefert
        // Das geht schief, wenn über wmask mehrere Pins im Spiel 
        // sind (z.B. bei dir "Man kann wmask auf 0xFF setzen") 
        // oder der 1-Wire-Pin nicht Pin 0 (z.B. bei meinem Aufbau 
        // an PC4) ist...
        bit=wRxbit();
        data |= bit<<i;
#endif
    }
    return data;
} 


Die _delay_us arbeiten gut auch mit 12 MHz. Ich sehe keinen Grund für 
die handausgemessenen Schleifen.

Autor: Matthias V. (snailhouserock)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Stefan,

das nenne ich konstruktiv!!! Dir vielen Dank an der Stelle.
Ich habe versucht die Delays mit der avrlib umzusetzen.

Dabei ist mir aufgefallen, daß ein _delay_us (480) tatsächlich 48 us 
benötigt. Allerdings arbeite ich mit 16 MHz. Ähnliches gilt auch für 
_delay_us(410).
Ich habe das wieder entsprechend angepaßt bzw. kalibriert und
jetzt funktionierts!!!

Dir nochmal vielen Dank, dass Du dir noch mit dem Problem die Nacht um 
die Ohren geschlagen hast!!!

Das erspart mir jetzt die Umschreiberei der restlichen Module.
Multipin Fähigkeit ist eh nicht gefragt, von daher bin ich mit der 
Lösung absolut zufrieden.

Viele Grüße,

Matthias

Autor: Andreas K. (a-k)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Matthias V. wrote:

> Dabei ist mir aufgefallen, daß ein _delay_us (480) tatsächlich 48 us
> benötigt.

Die Delay-Funktionen der avr-libc haben leider einen eingebauten aber 
immerhin dokumentierten Webfehler. Jenseits von 768/Clock (48µs bei 
16MHz) wird (in halbwegs aktuellen Versionen) auf _delay_ms 
umgeschaltet, allerdings wird bei der fälligen Umrechnung abgerundet, so 
dass _delay_ms(0) rauskommt. Ganz alte Versionen sind in dem Fall 
komplett undefiniert.

Damit sind die für 1-Wire Delays ebensowenig einsetzbar, wie deine 
handkalibierten.

Weshalb ich eine andere Version der Delay-Routinen einsetze. Die stammt 
letztlich aus der Martin Thomas'schen Version von Peter Daneggers 1-Wire 
Routinen. Anbei.

Autor: Matthias V. (snailhouserock)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi, hab Sie ersetzt. Sie waren ja schon in Peters Projekt enthalten.
Etwas angepaßt noch auf dem Parameter F_CPU.
Läuft einwandfrei.
Vielen Dank und Gruss,
Matthias

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welche Version von WinAVR verwendest du?

> allerdings wird bei der fälligen Umrechnung abgerundet,

In dem Punkt muss ich mich korrigieren. Ich hatte übersehen, dass der 
Kram in "double" gerechnet wird. Die aktuelle Version von <util/delay.h> 
sollte eigentlich auch funktionieren.

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias V. wrote:

> Hi, hab Sie ersetzt.

Netter Versuch, aber so leicht lasse ich mich nicht ersetzen. ;-)

Autor: Matthias V. (snailhouserock)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach, ja ;-) SIE-lowercase! Nach lustig kommt doof (reine Selbstkritik).

Nun zu Deiner Frage...
Im Einsatz ist ....... WinAVR-20070525.
Aktuell ist    ....... WinAVR-20080411.

Ich sehe aber gerade, daß die util/delay.h auch in der eingesetzten 
Version erhalten ist. Dennoch tritt das Phänomen dort auf. Klar #include 
<avr/delay.h> führt intern auf <util/delay.h>.
Greets,
Matthias

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

Bewertung
0 lesenswert
nicht lesenswert
Hallo
ich habe die Software von Matthias heruntergeladen (vielen Dank!!) und 
versucht für den ATMEGA8 zu complimieren.
Leider bekomm ich immer einen Fehler:

uint8_t  docrc8 ( uint8_t number_of_bytes_to_read )  /// HIER ist der Fehler
{
  uint8_t   crc;
  uint16_t loop_count;
  uint8_t  bit_counter;
  uint8_t  data;
  uint8_t  feedback_bit;
  
  crc = CRC8INIT;

  for (loop_count = 0; loop_count != number_of_bytes_to_read; loop_count++)
  {
    data = ow_buffer[loop_count];
    
    bit_counter = 8;
    do {
      feedback_bit = (crc ^ data) & 0x01;
  
      if ( feedback_bit == 0x01 ) {
        crc = crc ^ CRC8POLY;
      }
      crc = (crc >> 1) & 0x7F;
      if ( feedback_bit == 0x01 ) {
        crc = crc | 0x80;
      }
    
      data = data >> 1;
      bit_counter--;
    
    } while (bit_counter > 0);
  }
  
  return crc;
}
Mit folgender Fehlermeldung:
../crc8.c:10: error: expected '=', ',', ';', 'asm' or '__attribute__' 
before 'uint8_t'

Ich weis leider nicht wiso, ich habe die h - Files includiert und denke 
das diese passen müssten.
Weis jemand von euch an was dies liegen könnte?

Ich habe das komplette Projekt hochgeladen, vl ist es einfacher was zu 
finden. ( Ich verwende AVR Studio 4.16 und WinAVR-20090313)

Grüße
Luke

Autor: Luke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Pardon hab am falschen Thread gepostet :(

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Luke schrieb:

> Mit folgender Fehlermeldung:
> ../crc8.c:10: error: expected '=', ',', ';', 'asm' or '__attribute__'
> before 'uint8_t'


File: global.h

letzte Definition
EXTERN          uint8_t rx_received      // die Variable wird in ein Register verlegt, spart ca. 30 Byte

da fehlt der ;

Bei Fehlermeldungen für die du keine Erklärung findest, immer auch die 
unmittelbar vorhergehenden Zeilen untersuchen. Wenn die aus einem Header 
File kommen, dann auch ins Header File schauen.

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.