Forum: Mikrocontroller und Digitale Elektronik zeitkritischer Pin-Interrupt bei 1-Wire


von Embrio (Gast)


Lesenswert?

Hallo zusammen,

ich wollte via µC (z.B. Atmel 324P,... mit 8 MHz Quarz) ein Signal über 
den Pin-Interrupt detektieren. Der Pin soll fallende und steigende 
Flanken erfassen und einen Interrupt erzeugen.

Es handelt sich um das 1-Wire Protokoll:

0-Signale und Reset/Presence-Signale werden detektiert. Das Problem sind 
die 1-Signale, da dort die fallende und steigende Flanke unmittelbar 
aufeinander folgen.

Also konkret:

Ich lege über ein Dallas-Demoboard einen Search-Algorithmus auf die 
Leitung; ist es das Reset/Presence-Signal oder eine '0', wird dies auch 
erkannt.
Aber das 1-Signal, welches maximal 1 us (in meinen Fall) anliegt, wird 
nicht detektiert. (Das Signal ist inklusive der Flanken 1 µs lang)
Ich vermute, dass der µC zu langsam ist, die fallende und steigende 
Flanke innerhalb einer µs zu erfassen.

Daher meine Frage: Wäre es möglich, das Signal um 4-5 µs zu verlängern, 
so dass der µC ausreichend Zeit hat dies zu detektieren? Vielleicht in 
Form einer Hardware (diese müsste natürlich entsprechend schnell sein)?
Ich habe da an einen Baustein gedacht, der bei Auftreten einer fallenden 
Flanke einen Timer startet und 4-5 µs die Leitung auf Low zieht. Gibt es 
so etwas?

Vielen Dank für eure Hilfe.

Mit freundlichen Grüßen
Embrio

von Peter D. (peda)


Lesenswert?

Einen 1-wire Master macht man üblicher Weise mit Delays. Das Datenbit 
wird etwa 10µs nach der 1-0 Flanke eingelesen:

1-0 Flanke
Delay 1µs
0-1 Flanke
Delay 9µs
Einlesen
Delay 50µs


Peter

von Embrio (Gast)


Lesenswert?

Oh, vielen Dank für die Antwort.

Ich programmiere aber keinen Master, sondern versuche einen Slave zu 
implementieren. Das habe ich noch vergessen zu erwähnen. Entschuldigung.

Und daher kommt dann auch das Problem, wenn die 1-0 Flanke auftritt und 
dann die 0-1 Flanke, dann sind gerade mal ~1µs vergangen. So wie es mir 
scheint, reicht die Zeit aber nicht aus, um den Interrupt aufzurufen und 
den Pin-Interrupt zu deaktiveren, dass die daruffolgende steigende 
Flanke nicht detektiert wird.

Ich hoff, ich habe nicht noch mehr vergessen.

Auf jeden Fall danke für die weitere Hilfe.


Mit freundlichen Grüßen
Embrio

von JoachimB (Gast)


Lesenswert?

Embrio schrieb:
> Ich habe da an einen Baustein gedacht, der bei Auftreten einer fallenden
> Flanke einen Timer startet und 4-5 µs die Leitung auf Low zieht. Gibt es
> so etwas?

Monostabiler Multivibrator
74 .. 121

Gruß
Joachim

von gatsby (Gast)


Lesenswert?

Hallo Embrio,

der ganze Ansatz, alle Flanken per Interrupt zu detektieren, ist falsch.
Denke mal in folgende Richtung:
- Erste 1-0 Flanke per interrupt detektieren
- Dann interrupt sperren und das 1-wire Signal im Polling Modus abtasten
- Immer wieder Plausibilität der Signale testen, um festzustellen, ob 
man mit dem ersten 1-0 interrupt auch wirklich den Anfang eines 1-wire 
Telgramms erwischt hat. Falls nicht, polling abbrechen und Interrupt 
wieder scharf machen.
- Wenn komplettes Telegramm empfangen, dann das Telegramm auswerten.


gruss
gatsby

von Embrio (Gast)


Lesenswert?

gatsby schrieb:
> Hallo Embrio,
>
> der ganze Ansatz, alle Flanken per Interrupt zu detektieren, ist falsch.
> Denke mal in folgende Richtung:
> - Erste 1-0 Flanke per interrupt detektieren
> - Dann interrupt sperren und das 1-wire Signal im Polling Modus abtasten
> - Immer wieder Plausibilität der Signale testen, um festzustellen, ob
> man mit dem ersten 1-0 interrupt auch wirklich den Anfang eines 1-wire
> Telgramms erwischt hat. Falls nicht, polling abbrechen und Interrupt
> wieder scharf machen.
> - Wenn komplettes Telegramm empfangen, dann das Telegramm auswerten.
>
>
> gruss
> gatsby

Danke für die Info. Nur damit ich dich richtig verstehe:
Ich detektiere die 1-0 Flanke per ISR, dann ISRs deaktivieren und warten 
bis sich das Signal am Pin geändert hat. Je nachdem wie lange gewartet 
wurde, wurde ein Reset-Signal erkannt und man kann die weiteren Bits 
abwarten, ansonsten wieder die ISR aktivieren
- ist das so richtig?

JoachimB schrieb:
> Monostabiler Multivibrator
> 74 .. 121

Danke für die Info. Den werde ich mir mal anschauen.

Viele Grüße
Embrio

von Peter D. (peda)


Lesenswert?

Embrio schrieb:
> Ich programmiere aber keinen Master, sondern versuche einen Slave zu
> implementieren. Das habe ich noch vergessen zu erwähnen. Entschuldigung.

Auch kein Problem.
Der Master sendet eine 0 für >=60µs, eine 1 nach dem 1µs 0-Puls für 
>=59µs.
Das Bit ist also mindestens 59µs gültig.

Interrupt 1-0 Flanke
Delay 30µs
Bit einlesen.


Peter

von JoachimB (Gast)


Lesenswert?

Das zeitkritischste Problem besteht, wenn der Slave eine "0" senden 
möchte.

Der Master legt zuerst den Bus auf GND. Ein Dallas-Slave legt dann 
innerhalb einer µs ebenfalls den Bus auf GND.
Eine Softwarelösung dafür ist schwierig zu erreichen (s.o.).

Da der Master den Bus dabei jedoch für mindestens 6µs auf GND legt und 
es ausreicht, wenn ein Busteilnehmer den Bus auf GND legt, muss der 
Slave nicht innerhalb einer µs agieren. Der Slave kann sich etwas mehr 
Zeit lassen und muss nicht so schnell sein, wie der Dallas-Slave.

Gruß
Joachim

von Embrio (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Auch kein Problem.
> Der Master sendet eine 0 für >=60µs, eine 1 nach dem 1µs 0-Puls für
> >=59µs.
> Das Bit ist also mindestens 59µs gültig.
>
> Interrupt 1-0 Flanke
> Delay 30µs
> Bit einlesen.

Danke für die Hilfe.
Ok, die 59 µs sind ja auch nicht das Problem, sondern den kurzen 1µs 
Puls zu detektieren. Ich habe den Pin-Interrupt auf Pinchange gestellt, 
also fallende und steigende Flanke.
Da ja die fallende Flanke kommt und direkt hinterher die steigende, 
scheint der erste Interrupt noch nicht richtig aufgerufen worden zu 
sein, was dann zu Fehlern führt. Kann das sein?

So wie es aussieht, muss ich wohl auf den INT0..2 Interrupt umsteigen 
und nur fallende Flanken detektieren und in speziellen Fällen dann die 
steigende.

JoachimB schrieb:
> Das zeitkritischste Problem besteht, wenn der Slave eine "0" senden
> möchte.
>
> Der Master legt zuerst den Bus auf GND. Ein Dallas-Slave legt dann
> innerhalb einer µs ebenfalls den Bus auf GND.
> Eine Softwarelösung dafür ist schwierig zu erreichen (s.o.).
>
> Da der Master den Bus dabei jedoch für mindestens 6µs auf GND legt und
> es ausreicht, wenn ein Busteilnehmer den Bus auf GND legt, muss der
> Slave nicht innerhalb einer µs agieren. Der Slave kann sich etwas mehr
> Zeit lassen und muss nicht so schnell sein, wie der Dallas-Slave.

Was passiert, wenn kein anderer Slave vorhanden ist? Dann müsste ich 
hier auch wieder mein oben genanntes Problem haben, vermute ich mal.

Auf jeden Fall danke für die vielen Tipps.

Viele Grüße
Embrio

von gatsby (Gast)


Lesenswert?

Hallo Embrio,

nehmen wir mal an, der Bus ist im Ruhezustand (Dauersignal = 1).
Nun kommt eine 1-0 Flanke, die den Interrupt auslöst.
Es gibt nun 3 Möglichkeiten, wie dein signal aussehen könnte.
- Es ist ein "1" bit.
Dann ist der Signalpegel für ca. 15usec auf 0 und für mindestens 45usec 
auf 1.
- Es ist ein "0" bit.
Dann ist der Signalpegel für ca. 60usec auf 0 und für mindestens 1usec 
auf 1.
- Es ist ein "Reset"
Dann ist der Signalpegel für ca. 480usec auf 0.

Also, wenn der Interrupt kommt, wartet man mal 30usec und polled dann 
das 1-wire-bus Signal. Ist es auf high, dann ist das empfangene bit eine 
"1". Ist es auf low, wartet man wieder 30usec. Dann polled man wieder. 
Ist das Signal nun auf high, dann ist das empfangene bit eine "0". Ist 
das Signal nun aber auf low, dann muss das Signal ein "Reset" Signal 
sein.
Das setzt natürlich voraus, dass sich der Master an dieses timing hält. 
Falls er davon abweicht müssen natürlich die Wartezyklen darauf 
angepasst werden.
Wenn nun beim pollen irgendetwas von diesem Schema abweicht, verwirft 
man alles, wartet 480usec (minus der bereits empfangenen bit Zeiten 
n*60usec) und schaltet den Interrupt wieder scharf.

Viel Erfolg
gatsby

von Uwe Bonnes (Gast)


Lesenswert?

OWI Signale ueber UART auswerten:
 http://www.maxim-ic.com/appnotes.cfm/an_pk/214

Dann ist nichts mehr zeitkritisches im Programmpfad...

von Embrio (Gast)


Lesenswert?

gatsby schrieb:
> Also, wenn der Interrupt kommt, wartet man mal 30usec und polled dann
> das 1-wire-bus Signal. Ist es auf high, dann ist das empfangene bit eine
> "1". Ist es auf low, wartet man wieder 30usec. Dann polled man wieder.
> Ist das Signal nun auf high, dann ist das empfangene bit eine "0". Ist
> das Signal nun aber auf low, dann muss das Signal ein "Reset" Signal
> sein.
> Das setzt natürlich voraus, dass sich der Master an dieses timing hält.
> Falls er davon abweicht müssen natürlich die Wartezyklen darauf
> angepasst werden.
> Wenn nun beim pollen irgendetwas von diesem Schema abweicht, verwirft
> man alles, wartet 480usec (minus der bereits empfangenen bit Zeiten
> n*60usec) und schaltet den Interrupt wieder scharf.

Danke für die Hilfe. Ich werde es mal in Betracht ziehen, wobei ich 
keinen Master habe, der bestimmte Timings voraussetzt; soll heißen, es 
könnten heute die Standardtimings sein und morgen ein wenig abweichend.
Da muss ich mir dann noch mal was einfallen lassen.

Uwe Bonnes schrieb:
> OWI Signale ueber UART auswerten:
>  http://www.maxim-ic.com/appnotes.cfm/an_pk/214
>
> Dann ist nichts mehr zeitkritisches im Programmpfad...

Daran habe ich auch schon gedacht. Aber das kann ich mir noch nicht so 
ganz vorstellen.
Vielen Dank dafür.

Viele Grüße
Embrio

von Peter D. (peda)


Lesenswert?

Embrio schrieb:
> Danke für die Hilfe. Ich werde es mal in Betracht ziehen, wobei ich
> keinen Master habe, der bestimmte Timings voraussetzt; soll heißen, es
> könnten heute die Standardtimings sein und morgen ein wenig abweichend.

Wenn Du nicht an Maxims 1-wire gebunden bist, es gibt noch mehrere 
Möglichkeiten, mit einem Draht auszukommen, z.B.:

Beitrag "mehrere MC seriell über Datenbus verbinden (1Draht)"

Der Vorteil ist, daß alles im Hintergrund im Interrupt abgehandelt wird.


Peter

von Embrio (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Wenn Du nicht an Maxims 1-wire gebunden bist, es gibt noch mehrere
> Möglichkeiten, mit einem Draht auszukommen, z.B.:
>
> Beitrag "mehrere MC seriell über Datenbus verbinden (1Draht)"
>
> Der Vorteil ist, daß alles im Hintergrund im Interrupt abgehandelt wird.

Hey,

danke für die Antwort.
Ich bin leider an den Timings vom Dallas 1-wire gebunden, die können ja 
einige Toleranzen haben, was ich bisher so in den Application Notes 
gelesen habe.
60-120 µs kann ein Bit lang sein, usw. .
Daher meinte ich ,dass die Variante mit dem Pollen evtl. noch 
modifiziert werden muss.

Aber deine Entwicklung habe ich auch schon gesehen, ist leider nur nicht 
passend. Vielen Dank!

Viele liebe Grüße
Embrio

von Embrio (Gast)


Lesenswert?

Guten Morgen zusammen,

ich habe mich jetzt mal ein wenig mit dem UART beschäftigt und denke, 
dass das darüber nicht so einfach möglich ist, zumindest nicht als 
Slave.

Würde ich als Slave eine Datenrate einstellen, so dass ein Byte 60 µs 
benötigt, könnte ich dann überhaupt einen Reset detektieren? Schließlich 
benötigt der UART ja ein Start- und Stopbit.
Wenn also ein Reset anliegt, würde der UART kein Stopp erfassen können, 
da die Leitung ja immer noch auf Low liegt oder irre ich mich da? Und 
ein Reset kann ja jederzeit auftreten.
Als Master ist die Methode natürlich super, da initiiert man ja selbst 
den Reset und das bedeutet, dass man dann die Baudrate umstellen kann, 
um diesen Reset zu übertragen.
Aber als Slave sehe ich da ein großes Problem.

Ich hoffe, ich habe da nichts übersehen. Vielleicht kann mir jemand mit 
mehr Erfahrung auf die Sprünge helfen. Vielen Dank für eure Hilfe.

Viele Grüße
Embrio

von Peter D. (peda)


Lesenswert?

Man könnte als Slave einen ATtiny mit USI nehmen.

Im letzten I2C-Mode wird der SCL-Pin nach der 1-0 Flanke auf low 
gehalten, bis das Interruptbit gelöscht wird.
Mit dem USIWMO schaltet man dann um (1 oder 0 senden).


Peter

von gatsby (Gast)


Lesenswert?

Hallo Embrio,

wenn du wechselnde Master mit unterschiedlichen timing Verhalten hast, 
kannst du folgendes tun.
Wie JoachimB bereits schrieb, ist das Erkennen des "0" bits das 
kritische bit.

Beim "1" bit ist das 1-wire Signal nach Ablauf von 30usec bereits auf 
high und du kannst davon ausgehen, wenn keine Störungen auf dem bus 
sind, dass das Signal für mindestens die nächsten 30usec auf high 
bleibt.

Beim "0" bit könnte der Master zu langsam sein und nach Ablauf der 
zweiten 30usec das 1-wire Signal noch nicht auf high gelegt haben.

Lösung:
Du wartest nur 20usec und pollst dann das 1-wire Signal. Das sollte nun 
auf low sein (bei "0" bit). Nun schickst du den Slave in eine 
Zählschleife, die einen Zähler hochzählt und das 1-wire Signal abfragt. 
Die Zählschleife wird verlassen, wenn das 1-wire Signal high wird oder 
wenn ein maximaler Zählerstand erreicht ist (bis max. 120usec 
verstrichen sind). Jetzt wertest du den Zählerstand aus.
Ist der Maximalwert erreicht -- "Reset" erkannt
Ist der Wert kleiner         -- "0" bit erkannt

Viel Erfolg
gatsby

von Embrio (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Man könnte als Slave einen ATtiny mit USI nehmen.
>
> Im letzten I2C-Mode wird der SCL-Pin nach der 1-0 Flanke auf low
> gehalten, bis das Interruptbit gelöscht wird.
> Mit dem USIWMO schaltet man dann um (1 oder 0 senden).

Das hört sich sehr gut an. Vielen Dank.
Gibt es USI auch für die ATmega Versionen?

gatsby schrieb:
> wenn du wechselnde Master mit unterschiedlichen timing Verhalten hast,
> kannst du folgendes tun.
> Wie JoachimB bereits schrieb, ist das Erkennen des "0" bits das
> kritische bit.
>
> Beim "1" bit ist das 1-wire Signal nach Ablauf von 30usec bereits auf
> high und du kannst davon ausgehen, wenn keine Störungen auf dem bus
> sind, dass das Signal für mindestens die nächsten 30usec auf high
> bleibt.
>
> Beim "0" bit könnte der Master zu langsam sein und nach Ablauf der
> zweiten 30usec das 1-wire Signal noch nicht auf high gelegt haben.
>
> Lösung:
> Du wartest nur 20usec und pollst dann das 1-wire Signal. Das sollte nun
> auf low sein (bei "0" bit). Nun schickst du den Slave in eine
> Zählschleife, die einen Zähler hochzählt und das 1-wire Signal abfragt.
> Die Zählschleife wird verlassen, wenn das 1-wire Signal high wird oder
> wenn ein maximaler Zählerstand erreicht ist (bis max. 120usec
> verstrichen sind). Jetzt wertest du den Zählerstand aus.
> Ist der Maximalwert erreicht -- "Reset" erkannt
> Ist der Wert kleiner         -- "0" bit erkannt

Vielen Dank. Auch diese Lösung werde ich weiter verfolgen. So ähnlich 
habe ich es mir auch eigentlich vorgestellt.

Nochmals vielen Dank für die ganzen Hilfestellungen

Viele Grüße
Embrio

von Peter D. (peda)


Lesenswert?

Embrio schrieb:
> Gibt es USI auch für die ATmega Versionen?

Der 1-wire ist ja nicht auf große Datenmengen optimiert. Daher sollte es 
ausreichen, wenn der Slave-AVR nur 8 .. 20 Pins hat.


Peter

von Embrio (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Der 1-wire ist ja nicht auf große Datenmengen optimiert. Daher sollte es
> ausreichen, wenn der Slave-AVR nur 8 .. 20 Pins hat.

Danke sehr. Ich entnehme deiner Antwort, dass es für den ATMega keinen 
USI gibt. Dann wird wohl der Tiny genügen müssen :-)

Viele Grüße
Embrio

von Peter D. (peda)


Lesenswert?

ATmega169


Peter

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
Noch kein Account? Hier anmelden.