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
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.
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!
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
inttimeout=480-15;//nach 480µs-15µs sollte eine Reaktion erfolgt sein.
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.
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...
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!
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...
>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.
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.
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.
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
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!
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. :-)
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!
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.
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!
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
intDS18S20_Init(void)
2
{
3
uint8_terr=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
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.
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.
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.
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.
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!
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!
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.
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.
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!
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
voidsenden(unsignedcharbyte)
2
{
3
intcounter;//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?
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 :).
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
voidsenden(unsignedcharbyte)
2
{
3
intcounter;//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.
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.
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?
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.
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.
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. :-)
> 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!
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.
@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
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...
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.
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
intlesen(void)
2
{
3
intcounter;//mitzählen, insgesamt 8 Bits pro Byte
4
uint8_tbyte;// 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!
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;
}
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
intlesen(void)-->daspasst
2
{
3
intcounter;//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_tbyte;// 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_tlese_bit(void)//Man kann kein einzelndes Bit zurückgeben, deshalb uint8_t
2
{
3
uint8_tbit;
4
5
//...
6
7
returnbit;
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_tlese_bit(void)//Man kann kein einzelndes Bit zurückgeben, deshalb uint8_t
2
{
3
uint8_tbit;
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
returnbit;//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_tlese_byte(void)
2
{
3
uint8_tzaehler;
4
uint8_tbyte=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
returnbyte;//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.
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!
@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.
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
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
voidwr_bit(uint8_tbyte)// 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
voidwr_byte(uint8_tbyte)
37
{
38
uint8_tzaehler;
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_trd_bit(void)// Man kann kein einzelndes Bit zurückgeben, deshalb uint8_t
50
{
51
uint8_tbit;
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
returnbit;//und Bit zurückgeben
68
}
69
70
uint8_trd_byte(void)
71
{
72
uint8_tzaehler;
73
uint8_tbyte=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
returnbyte;//und Ergebnis zurückgeben
81
}
82
83
// Reset and presence together
84
intreset(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
inttimeout=480-15;//nach 480µs-15µs sollte eine Reaktion erfolgt sein.
101
interror=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
return1;
115
}
116
else
117
{
118
return0;
119
}
120
}
121
122
// Beginn Programm
123
intmain(void)
124
{
125
// Umleiten der Standardausgabe stdout
126
stdout=&mystdout;
127
// initialisiere die UART schnittstelle
128
uart_init();
129
130
unsignedchards1820[9];
131
unsignedcharread_rom[8];
132
unsignedchari;
133
134
intreturncode=0;
135
intreturnbyte;
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.
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
>#defineXTAL8e6
2
>#defineF_CPUXTAL
3
>#defineF_CPU8000000UL//Your clock speed in Hz (3Mhz here)
F_CPU nur einmal definieren.
Und wozu dient das?
1
>#defineLOOP_CYCLES8//Number of cycles that the loop takes
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.
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.
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
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.
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!!
@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
@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!!
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.
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.
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.
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!
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.
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.
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!
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.
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.
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
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.
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.