Hallo zusammen,
habe folgendes Problem!
Ich möchte eine 1 Wire Kommunikation zwischen einem Maxim-Baustein und
einem uc herstellen. Meinen Takt erhalte ich durch einen 4MHz Quarz. Ich
brauche eine genaue Pause von einer us. Jedoch scheinen die delay
Funktionnen nicht genau genug zu sein. Kann mir jemand einen Tipp geben,
wie ich eine us Sekundenpause in C realsieren kann?
Vielen Dank im voraus
__asm("nop"); (genaue gcc syntax hab ich gerad nicht im kopf) macht
einen Prozessortakt lang rein gar nix.
Muss man in C als inline-assembler oder asm func. einbinden. Einige
Compiler haben auch intrinsics dafür (z.B. __nop(); ).
VG,
/th.
ein No-Operation Befehl, d.h. dass dein uC genau ein Takt lang nichts
macht (sofern du ein AVR verwendest), wenn du bei 4MHz 4 Takte lang
nichts machst, hast du genau eine usec gewartet.
Befehl: _NOP()
NOP = No OPeration (http://de.wikipedia.org/wiki/NOP)
NOP ist ein Assembler Befehl, der genau einen Takt lang nichts macht.
Bei deinem Takt musst du 4 NOPs machen.
> das setzen und löschen braucht auch noch seine Zeit ...
und das while auch, wenn du es ganz genau machen willst/muss wirst musst
du dir den erzeugen asm-code anschauen und bei jedem Befehl die Takte
ermitteln.
ich denke erst 3 nops und dann 2 nops sind näher dran.
Tommy schrieb:
> Jetzt müsste doch eigentlich abwechselnd der PIN A0 eine us high und> dann low gehen oder?
Du hast das Prinzip des 1w nicht verstanden.
Der Pin darf nur zwischen low und tristate wechseln.
High ist verboten!
Nimm die Delayfunktion, die ist sehr genau.
Aber Genauigkeit brauchst Du nicht bei 1w.
Hauptsache es stören keine Interrupts.
Peter
Die Frage ist: Wie genau muss es denn sein?
Die wenigsten Bausteine sind so heikel, dass 1µs ganz exakt stimmen
muss. Normalerweise hat man da einen großen Spielraum. Gerade bei so
kleinen Zeiten.
Achso heisst das dann, dass ich den PORTA auf low setze und dann nur
noch mit dem Datenregister schalte? DDRA|=(1<<PA0) ist gleich setzen und
DDRA&=~(1<<PA0) ist gleich empfangen? Stimmt das dann?
Tommy schrieb:
> ja, so muss es sein, da die Zeit nicht bei mir stimmt! Wie soll man denn> dann das Timing genau hinbekommen?
Wie schon gesagt, das ist unnötig.
Schau Dir mal die Timings genau an, Du hast immer einen Spielraum von
1:4.
Peter
@Mat
> Port setzen alleine braucht ja z.b. schon 3 Takte ...> - Port einlesen> - Bit(s) ändern> - Port schreiben
zum Glück gibt es ein ASM-Befehl der das Setzen eines Bits direkt
übernimmt.
Dafür muss nichts gelesen werden.
>@Mat>> Port setzen alleine braucht ja z.b. schon 3 Takte ...>> - Port einlesen>> - Bit(s) ändern>> - Port schreiben>zum Glück gibt es ein ASM-Befehl der das Setzen eines Bits direkt>übernimmt.>Dafür muss nichts gelesen werden.
hmm, kenn ich gar nicht, dachte immer es kann nur Byteweise gearbeitet
werden.
Wenn du einen schnelleren Quarz nimmst, kannst du die Zeiten genauer
einhalten. Bei 4 Takten Pause für 1µs Wartezeit hast du bei einem Takt
zu früh oder zu spät schon +/-25% Abweichung des Timings!
Bei einem doppelt so schnellen Quarz sind es immernoch 12,5%.
Befasse dich mal damit wie eine Warteschleife in Assembler aufgebaut ist
und schau dir an wie lange die Befehle brauchen.
Du wirst schnell feststellen, das mit 4 Befehlen Pause eine
Warteschleife schlecht ist. Da musst du dann wirklich den Code an der
Stelle optimieren, damit du das Timing einhalten kannst.
Also mein Tip: auf ASM-Basis optimieren und/oder schnellerer Quarz für
mehr Spielraum.
@ Karl heinz Buchegger:
Ja, gute Frage. Wie genau muss denn typischerweise das Timing beim 1wire
eingehalten werden? Ich könnte mir vorstellen, das 25% Abweichung schon
zu viel sind.
Gruss Stefan
Also laut den Timings habe ich genug Zeit jedoch habe ich es noch nicht
ganz mit dem Richtungsregister verstanden.
Ich habe den Maximbaustein mit einem Pull up Widerstand am Pin PA0
angeschlossen. Jetzt will ich einfach erstmal nur ein Reset auslösen.
Das heisst, die Leitung muss 480 us auf low und dann 120 us auf high
gezogen werden. Danch liest man den PIN aus! Und wenn ich das jetzt
richitg verstanden habe muss das mit dem Richtungsregister gemacht
werden und nicht mit dem Portregister, ist das richtig?
Tommy schrieb:
> Achso heisst das dann, dass ich den PORTA auf low setze und dann nur> noch mit dem Datenregister schalte? DDRA|=(1<<PA0) ist gleich setzen und> DDRA&=~(1<<PA0) ist gleich empfangen? Stimmt das dann?
Ja.
Schau einfach mal hier:
Beitrag "DS1820, DS18B20 in C"
Da hatte ich die Delayfunktion selber geschrieben, da damals der AVR-GCC
noch nicht so weit war.
Die 15µs sollte man nicht so ausreizen (10µs ist besser).
Peter
Ja, du darfst eben nicht High-Low umschalten, sondern nur TriState-Low.
Das heisst du musst den Pin auf Eingang ohne Pull-up schalten für
Tri-State.
Low sollte ja klar sein^^
@ Mat: Bei den meisten MC's gibts im Datenblatt ein paar Seiten die mit
Instruction-Set betitelt sind^^ Da sind alle Befehle aufgelistet...
Mat schrieb:
>>@Mat>>> Port setzen alleine braucht ja z.b. schon 3 Takte ...>>> - Port einlesen>>> - Bit(s) ändern>>> - Port schreiben>>>zum Glück gibt es ein ASM-Befehl der das Setzen eines Bits direkt>>übernimmt.>>Dafür muss nichts gelesen werden.>> hmm, kenn ich gar nicht, dachte immer es kann nur Byteweise gearbeitet> werden.
Aber dein Compiler kennt die Befehle zum Glück.
Peter kannst du mir noch eine Frage beantworten?
Ich verstehe es immer noch nicht mit dem Reset! Ich bin jetzt soweit,
dass ich glaube, das es Hardwaremäßig funktioniert. Ich sehe auf meinem
Oszi mein low setzen, dann wieder high setzen und danach das Antworten
des Bausteins.
Aber was ich nicht verstehe ist folgendes. Um eine Bestätigung zu
erhalten, das der Baustein bereit ist, müsste der PIN doch low sein, da
ja der Baustein die Leitung runterzieht! Oder wartet man die
Resetprozedur komplett ab und wenn dann am ausgelesenen PIN high anliegt
ist alles in Ordnung? Aber dann würde man doch auch ein OKAY kriegen,
wenn überhaupt kein Baustein dran ist, da die Leitung ja high aktiv ist!
Tommy schrieb:
> Aber was ich nicht verstehe ist folgendes. Um eine Bestätigung zu> erhalten, das der Baustein bereit ist, müsste der PIN doch low sein, da> ja der Baustein die Leitung runterzieht! Oder wartet man die> Resetprozedur komplett ab und wenn dann am ausgelesenen PIN high anliegt> ist alles in Ordnung?
Das Datenblatt sagt dir, wie lange es dauert bis der Baustein anfängt
den Pin auf Low zu ziehen. Und es sagt dir auch, wie lange der Baustein
die Leitung auf Low ziehen wird, ehe er wieder loslässt. Du nimmst dir
jetzt einen Zeitpunkt irgendwo in der Mitte und siehst nach, ob die
Leitung tatsächlich Low ist.
Dann wartest du die Restzeit ab und siehst nach ob die Leitung wieder
High ist (nur zur Sicherheit, ob auch der Pullup Widerstand tatsächlich
drann ist :-)
> Aber dann würde man doch auch ein OKAY kriegen,> wenn überhaupt kein Baustein dran ist, da die Leitung ja high aktiv ist!
Nicht wenn du forderst, dass dein erstes Nachsehen, mitten im
Zeitfenster des Bausteins, ein Low ergeben muss und die Leitung nach
Ablauf der Zeit wieder High sein muss.
> Ich sehe auf meinem Oszi mein low setzen, dann wieder high setzen
Immer noch nicht verstanden :-/
Zitat:
>> Peter Dannegger schrieb:>>> Du hast das Prinzip des 1w nicht verstanden.>>> Der Pin darf nur zwischen low und tristate wechseln.>>> High ist verboten!
1) du schreibst in das Port-Register für den 1-Wire eine 0.
2) du schaltest nur noch mit dem Richtungsregister
zwischen Ein- und Ausgang um.
Eingang = Hochohmig
Ausgang = Aktive 0
Du gibst aber niemals eine aktive 1 aus.
Lothar Miller schrieb:
>> Ich sehe auf meinem Oszi mein low setzen, dann wieder high setzen> Immer noch nicht verstanden :-/> Zitat:>>> Peter Dannegger schrieb:>>>> Du hast das Prinzip des 1w nicht verstanden.>>>> Der Pin darf nur zwischen low und tristate wechseln.>>>> High ist verboten!>> 1) du schreibst in das Port-Register für den 1-Wire eine 0.> 2) du schaltest nur noch mit dem Richtungsregister> zwischen Ein- und Ausgang um.> Eingang = Hochohmig> Ausgang = Aktive 0>> Du gibst aber niemals eine aktive 1 aus.
Oder um es noch deutlicher zu sagen:
Eine 1 auf der Leitung entsteht dadurch, dass der Pullup Widerstand die
Leitung auf High zieht. Er und nur er alleine sorgt für die 1. Sind alle
Teilnehmer am Bus auf Eingang geschaltet (=Tristate), dann hat die
Leitung 1 Pegel. Will ein Teilnehmer die Leitung auf 0 ziehen, dann
schaltet er seinen Pin auf Ausgang und zieht die Leitung runter. Will er
die Leitung wieder zurück auf 1, dann geht er wieder auf Eingang und der
Pullup zieht die Leitung wieder hoch. Auf die Art kann es nie passieren,
dass 2 Ausgänge gegeneinander arbeiten.
Tommy schrieb:
> Doch wenn ich das so Programmiere ist result immer bei mir 1, da dort> die Leitung gerade wieder hoch gegangen ist!
Dann sind wahrscheinlich die 120 ein klein wenig zu lang. Geh auf 100
und dafür die 360 auf 380 (weil 100+380 gleich 480) Was sagt denn das
Datenblatt über das Timing?
Ich verstehe nicht, warum sie das dann so knapp kalkuliert haben! Würde
man nur 100 us warten, würde es dicke reichen. Oder hat das einen
anderen Grund?
Tommy schrieb:
> Ich verstehe nicht, warum sie das dann so knapp kalkuliert haben! Würde> man nur 100 us warten, würde es dicke reichen. Oder hat das einen> anderen Grund?
Keine Ahnung.
PeDa wartet in seinem Beispiel (DS1820) nur 66µs (für die krummen 66
gibt es sicherlich einen guten Grund). Also noch kürzer.
Und er sieht nach Ablauf der Zeit auch noch nach, ob die Leitung wieder
auf High gegangen ist :-)
Im Zweifel würde ich eher PeDa trauen als einem Datenblatt :-)
Karl heinz Buchegger schrieb:
> PeDa wartet in seinem Beispiel (DS1820) nur 66µs (für die krummen 66> gibt es sicherlich einen guten Grund).
Der Presence-Puls beginnt nach 15-60µs und dauert 60-240µs
(DS18B20, S.15, Figure 13. Initialization Timing).
D.h. er beginnt spätestens nach 60µs und endet frühestens nach 75µs.
Die Mitte ist 67µs, noch 1µs für Programmlaufzeiten abgezogen = 66µs.
Peter
> Kann es sein das manche Application Notes manch mal für den A.... sind?> Für mein Baustein gibt es folgende App Note (für Reset z.B.) ...
Ja, aber für welchen Prozessor? Ist das u.U. ein 8051-Derivat?
Die können gar keine aktive '1' ausgeben :-o
Bei denen gilt: entwder Low oder Pullup (30k).
> Im Zweifel würde ich eher PeDa trauen als einem Datenblatt :-)
Es ist gar nicht das DB, das diesen Pseudo-Fehler enthält.
Es ist eine AppNote ;-)
Hallo zusammen,
habe es jetzt soweit, das die 64 bit Net Adresse vom Maxim Baustein
ausgegeben wird. Wie wäre es jetzt am besten die Zahl zu speichern? Im
Moment bekomme ich nur die Bitfolge. Oder ist es am besten die Zahl in
einem array abzulegen?
Tommy schrieb:
> Hallo zusammen,> habe es jetzt soweit, das die 64 bit Net Adresse vom Maxim Baustein> ausgegeben wird. Wie wäre es jetzt am besten die Zahl zu speichern? Im> Moment bekomme ich nur die Bitfolge. Oder ist es am besten die Zahl in> einem array abzulegen?
Ich kann nur wieder die Empfehlung von weiter oben wiederholen: Sieh dir
das DS1820 Beispiel vom PeDa an. Da findest du so mancherlei, was dir
deine Fragen beantwortet.
Peter Danneggers Beispiel hat mir sehr fürs Verständnis geholfen.
Dadurch habe ich das Reset & Write verstanden, auch die einzelnen Bis
auslesen habe ich verstanden, aber dann hörts mit dem Verständnis auf!
Seine read Funktion verstehe ich nicht!
Aber genau darin besteht das Problem! Ich kann das nicht ganz ersehen!
So wie ich das verstehe, würde ich jetzt einen array von uint8_t
anlegen, und dort die Oktetts ablegen.
Bei mir würde das bedeuten:
Ich würde die 64 Bitfolge in 8 Oketetts wandeln und diese in einem Array
ablegen. Dann würde ich bei Bedarf z.B. CRC check die dementsprechene
Bitefolge rausnehmen und weiterverarbeiten. Jedoch bin ich mir nciht
sicher, ob er das so gemacht hat!
Tommy schrieb:
> Aber genau darin besteht das Problem! Ich kann das nicht ganz ersehen!> So wie ich das verstehe, würde ich jetzt einen array von uint8_t> anlegen, und dort die Oktetts ablegen.> Bei mir würde das bedeuten:> Ich würde die 64 Bitfolge in 8 Oketetts wandeln
Genau das macht eine der Routinen auf unterster Ebene.
8 Bits empfangen, in ein Byte (aka uint8_t) zusammenschieben und
zurückgeben.
Darüberliegende Softwareschichten arbeiten nur noch mit Bytes und nicht
mit einzelnen Bits.
Da gibt es die Funktion w1_bit_io. Die bringt 1 Bit auf den Weg, bzw.
empfängt eines. Benutzt wird sie in w1_byte_wr (was werden wohl die
ganzen 8-er in dieser Funktion sein?). Alles ausserhalb 1wire.c benutzt
nur noch die w1_byte_wr.
Einzige Ausnahme ist die rom_search Funktion. Die arbeitet noch auf
Bitebene. Aber das auch nur, weil sie bei mehreren Geräten die
Buskollisionen auseinanderklamüsern muss und das geht auf Bytebene nicht
mehr. Aber sobald die Ids aller Geräte feststehen, arbeitet alles nur
noch auf Bytebene.
Ah, okay!
Ich hätte da noch ne wahrscheinlich blöde Frage! Ist es eigentlich nötig
den CRC check zu machen, wenn eh nur ein Baustein dran ist? So wie es
bei mir aussieht kippt da kein Bit zufällig um! Oder ist es Standart,
dass man immer den CRC nachprüft!
Die Frage ist:
Wieviel Laufzeit kostet dir die CRC Prüfung (im Vergleich zum restlichen
Program, hast du die Zeit)?
Was passiert, wenn sich ungültige Daten durchmogeln?
(Wenn eine Thermometer-Anzeige deswegen falsch anzeigt ist das eine
Sache. Wenn dadurch aber der Ölbrenner die ganze Nacht lang durchfeuert,
ist das eine ganz andere Sache)
Letztenendes kann dir niemand vorschreiben, ob du die Prüfung machst
oder nicht. Aber Programmierer fürchten nichts so sehr, wie falsche
Eingangsdaten in ihre Algorithmen. Denn die haben sie nicht unter
Kontrolle.
Tommy schrieb:
> dann werde ich mir mal anschauen wie man so einen CRC check macht!
Im einfachsten Fall nimm _crc_ibutton_update aus der crc16.h.
Peter
Ich würde gerne den CRC check richtig verstehen, aber iregendwie werde
ich aus der App Note 27 nicht richtig schlau!
Wenn ich das richtig verstanden habe, ist das Generatorplynom
x^8+x^5+x4+1, sprich: 10011001. Hoffe das ist soweit schon mal richtig.
Jetzt mache ich mit den empfangenen Daten und dem Generatorpolynom eine
XOR Verknüpfung und wenn am Ende (alle empfangenen Daten inklusive der
Pruefsumme) kein Rest bleibt, dann ist kein Fehler aufgetreten.
Ist das so richtig?
Ich hätte da noch eine Frage,
Wenn die Net Addresse z.B. 8C00001221749830 lautet
Dann ist doch 8C die Prüfsumme und 30 der Family Code.
Wenn ich jetzt den CRC check machen will, muß ich dann die Inputdaten
umdrehen?
In diesem Fall beginnend mit 4 Nullen die würden dann wegfallen!
Bei der ersten 1 würde ich dann anfangen zu rechnen!
Kann mir da jemand helfen?