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.
okay, dann würde ja dann folgendes bedeuten:
1 | #define nop() asm volatile("nop")
|
2 | |
3 | DDRA|=(1<<PA0); |
4 | while(1) |
5 | {
|
6 | PORTA|=(1<<PA0); |
7 | nop(); |
8 | nop(); |
9 | nop(); |
10 | nop(); |
11 | PORTA&=~(1<<PA0); |
12 | nop(); |
13 | nop(); |
14 | nop(); |
15 | nop(); |
16 | }
|
Jetzt müsste doch eigentlich abwechselnd der PIN A0 eine us high und dann low gehen oder?
> 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
ja, so muss es sein, da die Zeit nicht bei mir stimmt! Wie soll man denn dann das Timing genau hinbekommen?
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.
Port setzen alleine braucht ja z.b. schon 3 Takte ... - Port einlesen - Bit(s) ändern - Port schreiben
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.
Verstehe! 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.)
1 | int Reset(void) |
2 | {
|
3 | int result; |
4 | |
5 | outp(PORTADDRESS,0x00); //Drives DQ low |
6 | Waitx(480); //480us |
7 | outp(PORTADDRESS,0x01); //Releases the bus |
8 | Waitx/(120); |
9 | |
10 | //Sample and return the Presence Detect
|
11 | result = inp(PORTADRRESS) & 0x01; |
12 | Waitx(360); |
13 | |
14 | return result; |
15 | }
|
Doch wenn ich das so Programmiere ist result immer bei mir 1, da dort die Leitung gerade wieder hoch gegangen ist!
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 :-)
Verstehe!! Gut werde mich jetzt mal ans Write und Read begeben! Mal gucken ob ich es jetzt hin bekomme
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!
Du kannst dir ja bei ihm zb. einmal ansehen, was er mit der Id vom Baustein macht. Wie er sie speichert, wie er sie weiterbenutzt etc.
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.
Hab's verstanden, dann werde ich mir mal anschauen wie man so einen CRC check macht!
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 brauch den 8 bit CRC check! Den du meinst ist doch ein 16 Bit CRC check, oder?
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?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.