www.mikrocontroller.net

Forum: Compiler & IDEs DS18S20 gibt immer nur "2" aus


Autor: Paul P. (cesupa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

bin grad dabei mit Hilfe des DS18S20 die Temperatur auszulesen. Erstmal 
nur testweise. Benutze dafür einen Atmega32 mit 16MHz auf dem 
Pollinboard + Addonboard. Das ganze geschieht in C und sieht so aus:
/*
 * main.c
 *
 *  Created on: 15.07.2010
 *      Author: cesupa
 */

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include "lcd_addonboard.h"

/* Thermometer Connections (At your choice) */
#define PORT PORTD
#define DDR DDRD
#define PIN PIND
#define DQ PD6
/* Utils */
#define INPUT_MODE() DDR&=~(1<<DQ)
#define OUTPUT_MODE() DDR|=(1<<DQ)
#define LOW() PORT&=~(1<<DQ)
#define HIGH() PORT|=(1<<DQ)



uint8_t reset();
uint8_t write_bit(uint8_t bit);
uint8_t read_bit();
uint8_t read_byte();
unsigned char rom_c[8],scratch_pad[9];

void write_byte(uint8_t byte);

int main()
{
  uint8_t z=0;
  char string[20];

  lcd_init();
  if(!reset())
    lcd_str("DS18S20 found");
  else
    lcd_str("FAILURE");

  write_byte(0xcc);
  write_byte(0x44);
  _delay_ms(1000);

  if(!reset())
  {
    write_byte(0xcc);
    write_byte(0xbe);
    for(z=0;z<9;z++)
    {
      scratch_pad[z]=read_byte();
    }


    lcd_str(itoa(scratch_pad[8],string,10));
  }
  else
    lcd_str("FAILURE_2");

  while(1);
  return 0;
}

uint8_t reset()
{
  uint8_t i=0;
  //Pull line low and wait for 480uS

  OUTPUT_MODE();
  LOW();
  _delay_us(480);
  //Release line and wait for 60uS
  INPUT_MODE();
  LOW();

  _delay_us(70);

  //Store line value and wait until the completion of 480uS period
  i=(PIN & (1<<DQ));
  OUTPUT_MODE();
  LOW();
  _delay_us(410);

  //Return the value read from the presence pulse (0=OK, 1=WRONG)
  return i;

}

uint8_t write_bit(uint8_t bit)
{
  //Pull line low for 1uS
  OUTPUT_MODE();
  LOW();

  _delay_us(1);
  //If we want to write 1, release the line (if not will keep low)
  if(bit) INPUT_MODE();
  //Wait for 60uS and release the line
  _delay_us(119);
  INPUT_MODE();
return 0;
}

uint8_t read_bit()
{
  uint8_t bit;
  //Pull line low for 1uS
  OUTPUT_MODE();
  LOW();

  _delay_us(1);
  //Release line and wait for 14uS
  INPUT_MODE();
  _delay_us(14);
  //Read line value
  bit=PIN&(1<<DQ);
  //Wait for 45uS to end and return read value
  _delay_us(105);
  return bit;

}

unsigned char read_byte()
{
  uint8_t i=0;
  unsigned char n=0;

  for(i=0;i<8;i++)
  {
    if(read_bit()) n|=0x01 << 1;
  }
    return n;
}

void write_byte(uint8_t byte)
{
  uint8_t i=8;
  while(i--){
  //Write actual bit and shift one position right to make  the next bit ready
  write_bit(byte&1);
  byte>>=1;
  }

}

Wenn ich mir die Bytes des Scratchpads ausgeben lasse, steht auf dem LCD 
ständig eine "2" da....ich hab leider keine Ahnung woran das liegen 
könnte. Bitte um Hilfe.

Gruß
Paul

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fällt dir da was auf?
 if(read_bit()) n|=0x01 << 1;

Autor: Paul P. (cesupa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ok, statt 1 hätte ich i schreiben sollen. Jetzt hab ich aber das 
Problem, dass ständig 255 rauskommt also jedes Bit eine 1 ist. Stimmt da 
etwas in meiner Leseroutine nicht?

Gruß
Paul

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im reset beim present bit nicht auf Ausgang setzen. Was du an dieser 
Stelle in der Doku siehst ist die Aktion vom device.

Autor: Paul P. (cesupa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, es funktioniert, nachdem ich die Variable bit in der Funktion 
read_bit() mit 0 initialisiert habe funktioniert alles.

Danke für eure Hilfe :)

Gruß
Paul

Autor: 1ch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ok, statt 1 hätte ich i schreiben sollen.

1ch schre1be 1mmer 1 statt 1. Funkt1on1ert 
pr1ma!!!!!!11111111!!11!1!!!!1!!!!!1!!!!!

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

Bewertung
0 lesenswert
nicht lesenswert
Paul P. schrieb:
> ok, es funktioniert, nachdem ich die Variable bit in der Funktion
> read_bit() mit 0 initialisiert habe funktioniert alles.

Das ist zwar grundsätzlich eine gute Idee, erklärt aber das Problem 
nicht.

Autor: Armin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm, nicht wirklich.
In der Zeile "bit=PIN&(1<<DQ);" wird der Variablen "bit" ein Wert 
zugewiesen, ohne davor den Wert ausgelesen zu haben. Wenn man "bit" 
nicht mit 0 initialisiert, steht halt noch irgendetwas drin, wird dann 
aber eben einfach überschrieben.

Warum löst eine Initialisierung mit 0 das Problem?

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uint8_t write_bit(uint8_t bit)
{
  DDRD|=(1<<PD6);          // PD6 als Ausgang
  PORTD&=~(1<<PD6);        // PD6 auf low
  _delay_us(1);            // 1 µs warten
  if(bit) DDRD&=~(1<<PD6); // wenn bit != 0 dann PD6 auf low
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  _delay_us(119);          // 119 µs warten
  DDRD&=~(1<<PD6);         // PD6 als Eingang
return 0;
}

Bei read_bit ebenso. Was bringt denn das? Fehlt da jeweils ein 
else-Zweig? Ansonsten macht das if (bit) ja gar keinen Sinn und man kann 
gleich _delay_us(120) schreiben.

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, ja , zu schnell geschossen: DDRD& ist natürlich was anderes als 
PORT& ..., also den Post einfach irgnorieren!

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

Bewertung
0 lesenswert
nicht lesenswert
Lutz schrieb:

>   if(bit) DDRD&=~(1<<PD6); // wenn bit != 0 dann PD6 auf low
>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


> Bei read_bit ebenso. Was bringt denn das? Fehlt da jeweils ein
> else-Zweig? Ansonsten macht das if (bit) ja gar keinen Sinn und man kann
> gleich _delay_us(120) schreiben.

Der Kommentar mag ein bischen verwirrend sein. Falsch ist er auf jeden 
Fall. Du magst auch übersehen haben, dass hier das DDRD Register 
geschaltet wird und nicht das PORTD.

> Ja, ja , zu schnell geschossen: DDRD& ist natürlich was anderes
> als PORT& ..., also den Post einfach irgnorieren!

Nicht wirklich.
Er enthält nämlich ein Element, dessen Verständnis wichtig ist: Die 
Leitung wird über das DDR Register umgeschaltet. Dies deshalb weil es ja 
einen externen Pullup Wderstand gibt, der die Leitung auf 1 zieht.

Durch

   DDRD&=~(1<<PD6);

wird daher, anders als es der Kommentar suggeriert, die Leitung durch 
den externen Pullup auf 1 gezogen, indem der Pin auf Eingang geschaltet 
wird.

: Wiederhergestellt durch Moderator
Autor: Seb astian (seppelg85)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen

Auch wenn der Thread schon was älter ist, bräuchte ich hier mal Hilfe. 
Der Code ist übersichtlich und kompakt, daher habe ich den mal getestet.

Du hast geschrieben das der Code so funktioniert. Leider ist dem bei mir 
nicht so. Ich bekomme permanent eine 255 am LCD Display ausgegeben.

Hat hier noch jemand eine Idee was das Problem sein könnte?


Gruß

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.