Pausen-Problem

Gast #1421314
Lesenswert?

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
Gast #1421359
Lesenswert?

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?
Gast #1421366
Lesenswert?

> 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.
#1421369
Lesenswert?

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
Gast #1421380
Lesenswert?

@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.
Gast #1421383
Lesenswert?

>@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.
#1421390
Lesenswert?

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
Gast #1421391
Lesenswert?

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?
#1421394
Lesenswert?

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
#1421399
Lesenswert?

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...
#1421415
Lesenswert?

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.
Gast #1421572
Lesenswert?

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!
#1421578
Lesenswert?

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.
Moderator (Firma: Titel) Persönliche Seite #1421586
Lesenswert?

> 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.
#1421595
Lesenswert?

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.
Gast #1421596
Lesenswert?

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!
#1421598
Lesenswert?

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?
#1421601
Lesenswert?

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 :-)
#1421658
Lesenswert?

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
Moderator (Firma: Titel) Persönliche Seite #1421781
Lesenswert?

> 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   ;-)
Gast #1422787
Lesenswert?

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?
#1422799
Lesenswert?

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.
Gast #1422830
Lesenswert?

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!
Gast #1422888
Lesenswert?

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!
#1422899
Lesenswert?

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.
Gast #1422907
Lesenswert?

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!
#1422919
Lesenswert?

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.
Gast #1423185
Lesenswert?

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?
Gast #1424260
Lesenswert?

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?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren