Forum: Mikrocontroller und Digitale Elektronik ATmega1284P und Maxim 1-wire in Hardware


von Christian R. (cmrudolph)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich möchte in einem Projekt Temperatursensoren (DS18B20) über das Maxim 
1-wire Protokoll benutzen.
Da der Mikrocontroller, ein ATmega1284P, noch eine ganze Menge anderer 
Aufgaben übernimmt, möchte ich den zweiten USART Port des Controllers 
verwenden, um das USART Modul asynchron mit den Temperatursensoren 
kommunizieren zu lassen. Atmel hat in dem Dokument AVR318 beschrieben, 
wie man das realisieren kann. Ich habe das Dokument und den von Atmel 
veröffentlichten Quellcode nachfolgend verlinkt.
http://www.atmel.com/Images/doc2579.pdf
http://www.atmel.com/Images/AVR318.zip

Ich habe die Schaltung von Seite 3 aus der PDF auf einem Steckbrett 
nachgebaut. RXD geht bei mir zu Pin 16 und TXD zu Pin 17.

Da der Quellcode von Atmel ein wenig alt ist, habe ich ihn ein wenig 
angepasst (richtige includes und die Interruptroutinen angepasst). Den 
Modifizierten Quellcode habe ich angehängt.
Der uC ist mit 4MHz getaktet. An Port A habe ich 8 LEDs gehängt, um eine 
Ausgabe produzieren zu können.

Nun zum eigentlichen Problem:
der uC scheint einzufrieren, denn sobald
1
OWI_DetectPresence();
 einmal aufgerufen wird, passiert gar nichts mehr.
Die letzte Funktion die ausgeführt wird, ist
1
ISR(OWI_UART_UDRE_VECT)
 in OWIIntFunctions.c, Zeile 246. Um das festzustellen habe ich den Port 
A in Zeile 263 derselben Datei auf 0xFF gesetzt. Die LEDs flackern 
einmal ganz kurz auf, dann passiert nichts mehr.
Ich besitze leider keinen Hardware-Debugger, daher fällt mir die 
Diagnose sehr schwer. Ich konnte keine Programmierfehler finden, obwohl 
ich den gesamten Quellcode mehrfach durchgegangen bin. Ich habe das 
Gefühl, dass mit den Interruptroutinen irgend etwas nicht ganz richtig 
ist.

Für Hilfestellung wäre ich sehr dankbar!

Viele Grüße
Christian

von Kübelkotzer (Gast)


Lesenswert?

Christian Rudolph schrieb:
> Da der Mikrocontroller, ein ATmega1284P, noch eine ganze Menge anderer
> Aufgaben übernimmt, möchte ich den zweiten USART Port des Controllers
> verwenden, um das USART Modul asynchron mit den Temperatursensoren
> kommunizieren zu lassen.

Ist lächerlich, wenn du denkst, dass du den ATmega1284P mit ein paar 
1-Wire Sensoren "überlasten könntest".

Fall der doch - ich glaube es aber nicht - doch an seine Grenzen käme, 
wäre es immer noch die leichteste Übung, dem ein 16 oder 20 MHz Quarz zu 
verpassen.

von Thomas R. (Gast)


Lesenswert?

Ich habe mir den von dir verwendeten Code nicht angeschaut.
Während der 1-wire-Kommunikation musst du die IRQs sperren, sonst stimmt 
das Timing nicht mehr. Hast du das berücksichtigt?

von Frank K. (fchk)


Lesenswert?


von Christian R. (cmrudolph)


Lesenswert?

Kübelkotzer schrieb:
> Ist lächerlich, wenn du denkst, dass du den ATmega1284P mit ein paar
> 1-Wire Sensoren "überlasten könntest".

es geht nicht ums überlasten, sondern darum, dass der uC andere Aufgaben 
erledigt, die blocken. Und da ich noch einen USART Port frei habe, 
möchte ich diesen gerne nutzen, um die 1-wire Kommunikation asynchron zu 
erledigen.

Thomas R. schrieb:
> Während der 1-wire-Kommunikation musst du die IRQs sperren, sonst stimmt
> das Timing nicht mehr. Hast du das berücksichtigt?
Sobald die Kommunikation stattfindet wird das UDRIE1 (Data Register 
Empty Interrupt) Flag entfernt.
Der Interrupt Receive Complete wird, soweit ich es beobachten konnte, 
nicht ausgelöst. Der sollte ja theoretisch auch erst ausgelöst werden, 
wenn ein Byte übertragen wurde.

Was mich wundert ist, dass der uC nach Verlassen der Interruptroutine 
und dem Versenden von einem Byte nicht mehr ansprechbar ist.

Viele Grüße
Christian

von reflex (Gast)


Lesenswert?

Hast Du den Code selbstgeschrieben (bzw. von Atmel übernommen)?

Wenn ja, schau doch einfach mal in die Codesammlung, dort gibt es guten, 
stabilen Code, der sich sicher einfacher einbauen lässt, als jetzt den 
Fehler zu suchen.

von Christian R. (cmrudolph)


Lesenswert?

Ich habe den Code von Atmel übernommen und einige Anpassungen an meine 
Plattform vorgenommen.
Ich werde mal in die Codesammlung schauen und sehen, ob mir das 
weiterhilft.

Noch eine Frage: ist es problematisch, dass die Ausgabe vom TX Port 
direkt auf den RX Port wieder ankommt?

Edit: der Ansatz in der Codesammlung ist auch ein reiner Softwareansatz. 
Mir geht es darum mittels UART-Modul 1-wire zu "reden".

von Christian R. (cmrudolph)


Lesenswert?

Ich habe jetzt die Atmel-Version vom Quellcode mit Polling statt mit 
Interrupts gewählt. Damit kann ich die Temperatursensoren auslesen.
Also scheint das Problem irgendwie mit den Interrupts zusammenzuhängen.
Kann mir vielleicht irgendjemand einen Hinweis geben, was in dem oben 
geposteten Code falsch läuft? Die Interruptroutinen befinden sich in der 
Datei OWIIntFunctions.c

Danke und viele Grüße
Christian

von holger (Gast)


Lesenswert?

>Kann mir vielleicht irgendjemand einen Hinweis geben, was in dem oben
>geposteten Code falsch läuft?

Das hier?

>Der uC ist mit 4MHz getaktet.

von Christian R. (cmrudolph)


Lesenswert?

Inwiefern sollten die 4 MHz Taktrate ein Problem darstellen? Die per 
UART gesendeten Signale liegen alle locker im Toleranzbereich der 
1-wire-Spezifikation, auch wenn die Abweichung der Baudrate bei bis zu 
8,5% liegt.

von Kübelkotzer (Gast)


Lesenswert?

Christian Rudolph schrieb:
> es geht nicht ums überlasten, sondern darum, dass der uC andere Aufgaben
> erledigt, die blocken.

Also wenn das so ist, dann ist das Hauptproblem ja erkannt.
Lösung: nicht blockierenden Code schreiben, z.B. Scheduler verwenden.

von Christian R. (cmrudolph)


Lesenswert?

Das Problem mit einem Scheduler ist aber, dass die "parallel" laufenden 
Tasks auch recht präzises Timing benötigen, welche ich dann 
wahrscheinlich nicht mehr einhalten kann.
Ich weiche auch schon weitestgehend auf Timer mit Interrupts aus, aber 
es geht eben nicht überall.

Zu den 4MHz nochmal: falls das das Problem wäre, hätte auch der Code mit 
Polling nicht funktioniert.

von holger (Gast)


Lesenswert?

>Zu den 4MHz nochmal: falls das das Problem wäre, hätte auch der Code mit
>Polling nicht funktioniert.

250ns pro Taktzyklus. Bei den 1 Zyklus Befehlen schafft er da
gerade mal 4 Befehle pro 1us.

Hast du ne Ahnung wie lange es dauert bis der ATMega bei 4MHz
überhaupt mal im Interrupt landet?
Dann noch ein paar PUSHs usw. Da geht schon einiges ab.

Versuchs doch einfach mal mit 16MHz Takt.

Ansonsten hab ich aber auch nur geraten.

von Michael (Gast)


Lesenswert?

Christian Rudolph schrieb:
> es geht nicht ums überlasten, sondern darum, dass der uC andere Aufgaben
> erledigt, die blocken.

Dann solltest du die Code-Teile mal überdenken.

von Christian R. (cmrudolph)


Lesenswert?

holger schrieb:
>>Zu den 4MHz nochmal: falls das das Problem wäre, hätte auch der Code mit
>>Polling nicht funktioniert.
>
> 250ns pro Taktzyklus. Bei den 1 Zyklus Befehlen schafft er da
> gerade mal 4 Befehle pro 1us.
>
> Hast du ne Ahnung wie lange es dauert bis der ATMega bei 4MHz
> überhaupt mal im Interrupt landet?
> Dann noch ein paar PUSHs usw. Da geht schon einiges ab.
>
> Versuchs doch einfach mal mit 16MHz Takt.

Ich habe hier leider nur einen 8MHz Oszillator, damit werde ich es noch 
einmal versuchen.
Aber trotzdem habe ich noch ein Verständnisproblem. Für den Code mit 
Polling stimme ich zu, da hätte es Probleme geben können, wenn die 
Taktung zu niedrig wäre.
Ich dachte, dass das UART Modul im uC zwar durch den Haupttaktgeber 
getaktet wird, aber von der Hauptrecheneinheit unabhängig ist und echt 
parallel arbeitet.
Die zu sendenden und empfangenen Daten landen einfach in einem Register, 
auf welches dann bei Gelegenheit zugegriffen wird (ob durch Interrupt 
oder zyklische Prüfung ausgelöst ist dabei ja erstmal egal).
Um die erforderliche Taktrate im UART Modul zu erzielen, reichen 2,17MHz 
bereits aus. Die von mir errechnete Baudrate liegt bei 125kbit/s, was 
für einen High- oder Low-Takt bedeutet, dass er 8us lang ist. Damit 
lassen sich die mindestens 15us langen Takte problemlos treffen.

von Geiz ist noch immer geil (Gast)


Lesenswert?

Christian Rudolph schrieb:
> Ich habe hier leider nur einen 8MHz Oszillator, damit werde ich es noch
> einmal versuchen.

Ein 16MHz Quarz würde ja das Budget sprengen. Die lassen sich ja jedes 
Hz extra bezahlen.

von Christian R. (cmrudolph)


Lesenswert?

Hi,

ich finde es traurig, dass hier der Großteil der Kommentare 
unqualifiziert ist. Ich habe doch noch einen 16MHz Oszillator gefunden, 
mit dem sich das Problem allerdings auch nicht löst - nichtsdestotrotz 
macht es keinen Sinn Oszillatoren in großer Stückzahl vorzuhalten, die 
nicht meiner Zieltaktfrequenz von 4MHz entsprechen...

In diesem Sinne viele Grüße
Christian

von MWS (Gast)


Lesenswert?

Christian Rudolph schrieb:
> ich finde es traurig, dass hier der Großteil der Kommentare
> unqualifiziert ist.

Liegt wohl an der unqualifizierten Fragestellung. Hättest Du 
beispielsweise Deine Interpretation der AN als .c/.h angehängt, könnte 
man auch von 'nem Tablett 'nen Blick drauf werfen, ohne erst enzippen zu 
müssen. Aber so halt nicht.

Dann gab's Vorschläge, dass vielleicht das Timing des restlichen Codes 
überdacht werden sollte, da gab's auch keine qualifizierte Antwort von 
Dir. Was erwartest Du ? Ein Thread ist zur Diskussion gedacht, und nicht 
dass Dir einer den Knecht macht.

Wenn man die Flussdiagramme der RXD/TXD ISR's aus der AN ansieht, stellt 
man fest, dass die Ausführung linear ist, also kein Warten auf eine 
Bedingung stattfindet. Damit kann zumindest die ISR nicht blockieren. 
Möglich wäre allerdings, dass Du das falsche UDR abholst, in so einem 
Fall wird die ISR bis St. Nimmerlein aufgerufen, da das richtige UDR 
nicht geleert wird.

Aber wie gesagt, in ein Zip seh' ich jetzt nicht rein.

von Peter D. (peda)


Lesenswert?

Der Trick an der UART ist doch, daß sie immer funktioniert ohne lange 
Interruptsperren. Die 10 UART-Bits machen das 1wire-Timing.
Der Nachteil ist aber, daß man externe Hardware braucht, da die UART 
nicht Open-Drain kann.

von Uwe B. (Firma: TU Darmstadt) (uwebonnes)


Lesenswert?

Peter Dannegger schrieb:
> da die UART
> nicht Open-Drain kann

Beim STM32 schon !

von Christian R. (cmrudolph)


Angehängte Dateien:

Lesenswert?

MWS schrieb:
> Liegt wohl an der unqualifizierten Fragestellung. Hättest Du
> beispielsweise Deine Interpretation der AN als .c/.h angehängt, könnte
> man auch von 'nem Tablett 'nen Blick drauf werfen, ohne erst enzippen zu
> müssen. Aber so halt nicht.
Dass Entzippen so kompliziert ist, war mir nicht bewusst. An meinem 
Rechner öffnet sich 7-Zip automatisch und nach einem Doppelklick auf die 
darin enthaltene Datei kann ich mir den Quellcode ansehen. Und der 
Quellcode ist doch nur im Ganzen sinnvoll.

> Dann gab's Vorschläge, dass vielleicht das Timing des restlichen Codes
> überdacht werden sollte, da gab's auch keine qualifizierte Antwort von
> Dir.
Das geht doch vollkommen an meiner Fragestellung vorbei... Der Code 
funktioniert komplett ohne dass anderen Aufgaben vom uC erledigt werden 
schon nicht. Ich habe begründet, warum ich einen Hardware-Ansatz möchte 
und keinen Softwareansatz, worauf die Änderung des Timings des anderen 
Codes abzielt.

> Was erwartest Du ? Ein Thread ist zur Diskussion gedacht, und nicht
> dass Dir einer den Knecht macht.
Ich habe von niemandem verlangt mir den Knecht zu machen. Ich habe meine 
Analysen geschrieben, darauf hingewiesen, dass ich glaube, dass es an 
den Interrupts liegt, weil ein Pollingbasierter Ansatz funktioniert und 
geschrieben, in welcher Datei sich die Interruptroutinen befinden, sogar 
inklusive Zeilenangabe.

> Wenn man die Flussdiagramme der RXD/TXD ISR's aus der AN ansieht, stellt
> man fest, dass die Ausführung linear ist, also kein Warten auf eine
> Bedingung stattfindet. Damit kann zumindest die ISR nicht blockieren.
> Möglich wäre allerdings, dass Du das falsche UDR abholst, in so einem
> Fall wird die ISR bis St. Nimmerlein aufgerufen, da das richtige UDR
> nicht geleert wird.
Der Hinweis, dass ich vielleicht die falsche UDR abhole ist ganz gut. 
Ich habe daraufhin noch einmal meine gerätespezifischen Angaben zu den 
Registern etc. überprüft und irgendwann bin ich dann darauf gekommen, 
dass der Fehler in der Bezeichnung der Receive Complete ISR lag. Denn 
der Interrupt heißt nicht USART1_RXC, sondern nur USART1_RX.

Ich habe den funktionierenden Quellcode nochmal als Zipdatei 
hochgeladen. Vielleicht kann ihn ja jemand gebrauchen.

von MWS (Gast)


Lesenswert?

Christian Rudolph schrieb:
> MWS schrieb:
>> man auch von 'nem Tablett 'nen Blick drauf werfen, ohne erst enzippen zu
> Dass Entzippen so kompliziert ist, war mir nicht bewusst. An meinem
> Rechner öffnet sich 7-Zip automatisch und nach einem Doppelklick auf die

Musst lesen, ich schrieb Tablett und Tablett <> PC, da gibt's 
Einschränkungen, das bedeutet nicht "unmöglich", sondern komplizierter. 
Und dann ist die Neigung reinzuschauen eben geringer.

Ein passend gemachtes kleines Beispiel passt in ein paar Dateien, die 
man nicht unbedingt verzippen muss.

Ansonsten, schön dass es geht ;-)

von Christian R. (cmrudolph)


Lesenswert?

MWS schrieb:
> Musst lesen, ich schrieb Tablett und Tablett <> PC, da gibt's
> Einschränkungen, das bedeutet nicht "unmöglich", sondern komplizierter.
> Und dann ist die Neigung reinzuschauen eben geringer.
Jetzt hab ichs verstanden. Ich habe bei Tablett nicht an ein Tablet 
gedacht, sondern an an ein Gerät, auf dem man Speisen serviert ;-) 
Komischerweise tauchte in meinem Kopf dann die Redewendung "auf dem 
Silbertablett servieren" auf, was mich zu der Annahme verleitete, dass 
die Zipdatei zu kompliziert zu bedienen sei.

Was mich auch noch wundert ist, dass man im Internet recht wenig zu 
1wire über UART findet. Der Ansatz erscheint mir doch recht elegant, 
sofern man noch einen UART Port frei hat. Die Kosten für die benötigte 
zusätzliche Hardware hält sich ja auch in Grenzen (dürften etwa 10 Cent 
sein: ein zusätzlicher Widerstand und zwei Standardtransistoren).
Maxim hat dazu übrigens auch ein Tutorial (TUTORIAL 214), allerdings 
ohne Quellcode.

von MWS (Gast)


Lesenswert?

Christian Rudolph schrieb:
> Jetzt hab ichs verstanden. Ich habe bei Tablett nicht an ein Tablet
> gedacht, sondern an an ein Gerät, auf dem man Speisen serviert ;-)

Diese Assoziation ist trotz meiner nicht-angelsächsische Schreibweise 
recht interessant. ;D

> Was mich auch noch wundert ist, dass man im Internet recht wenig zu
> 1wire über UART findet. Der Ansatz erscheint mir doch recht elegant,
> sofern man noch einen UART Port frei hat. Die Kosten für die benötigte
> zusätzliche Hardware hält sich ja auch in Grenzen (dürften etwa 10 Cent
> sein: ein zusätzlicher Widerstand und zwei Standardtransistoren).

Aber da's auch ohne externe Beschaltung, an jedem Pin und ohne 
zusätzliches UART geht, wird eben die klassische Vorgehensweise 
bevorzugt.

von Uwe B. (Firma: TU Darmstadt) (uwebonnes)


Lesenswert?

Ethernut (SVN) kennt One-Wire mit UART und  GPIO.

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.