Forum: Mikrocontroller und Digitale Elektronik Exakter Manchester Code mit ATmega328 generieren


von Andreas (Gast)


Lesenswert?

Hallo!

Ich suche eine Möglichkeit, um mit dem ATmega328 einen Manchester Code 
mit exaktem Timing zu erzeugen.
Bisher habe ich dazu Timer 1 verwendet und bei einem Überlauf das 
entsprechende Muster am Ausgang erzeugt.
Nachdem der Code aber immer komplexer wurde und viele Interrupt Routinen 
mehr Zeit benötigen, treten vereinzelt Phasen mit zu langer Bitdauer 
auf.
Ich habe es bereits mit der Compare Match Output Unit versucht, aber das 
Register ist nicht gebuffert und ich kann die Flanke nicht zum Zeitpunkt 
des Compare Events umstellen.
Gibt es eine andere Möglichkeit, einen exakten Code mittels Timer zu 
erzeugen?

Vielen Dank,
Andreas

von Εrnst B. (ernst)


Lesenswert?

Welche Frequenz, wie genau, wie lang, was muss der AVR nebenbei noch 
machen?

z.B. : Schnell, auf den Takt genau, aber keine Zeit für was anderes: 
Abgezählte ASM-Instruktionen bei abgeschalteten Interrupts...

Auch schnell & genau, aber wohl zu kurz: Das USI-Schieberegister 
missbrauchen.

von Conny G. (conny_g)


Lesenswert?

Ist denn sonst nur in Interrupt Routinen, was da unbedingt sein muss?

von Andreas (Gast)


Lesenswert?

Hallo,

der Timer Interrupt kommt alle 417us, das Ausgangssignal darf max. 10%, 
d.h. 40us abweichen. Im Normalfall ist das auch kein Problem, aber 
manchmal kommt der Timer Interrupt viel zu spät dran.
Der Controller soll nebenbei noch die serielle Schnittstelle mit 
115kBit/s bedinen und einige andere Dinge per Interrupt verwalten, daher 
kann ich die Interrupts nicht sperren.
Ich hätte gehofft, ich könnte es mit der internen Hardware lösen, aber 
das scheint nicht zu funktionieren.
Der Mega328 besitzt leider kein USI, und die Länge würde nicht 
ausreichen.

Gruß,
Andreas

von Peter D. (peda)


Lesenswert?

Andreas schrieb:
> ich kann die Flanke nicht zum Zeitpunkt
> des Compare Events umstellen.

Es reicht, wenn Du die Flanke irgendwann vor dem nächsten Compare 
umstellst.

von chris_ (Gast)


Lesenswert?

Hier habe ich eine "Empfänger"-Version mit relativ exaktem Timing:
http://www.hobby-roboter.de/forum/viewtopic.php?f=4&t=127#p544

Man muss das Neuladen des Timer1 an die richtige Stelle setzen.

von Andreas (Gast)


Lesenswert?

Conny G. schrieb:
> Ist denn sonst nur in Interrupt Routinen, was da unbedingt sein muss?

Die sind leider mit fortlaufender Projektdauer etwas angewachsen.
Vermutlich läufts auf eine Optimierung dieser hinaus...

von Andreas (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Es reicht, wenn Du die Flanke irgendwann vor dem nächsten Compare
> umstellst.

Leider nicht, das schlägt sofort auf den Ausgang durch. Steht auch im 
Datenblatt in Kapitel 16.7.3.

von Conny G. (conny_g)


Lesenswert?

Andreas schrieb:
> Conny G. schrieb:
>> Ist denn sonst nur in Interrupt Routinen, was da unbedingt sein muss?
>
> Die sind leider mit fortlaufender Projektdauer etwas angewachsen.
> Vermutlich läufts auf eine Optimierung dieser hinaus...

Genau das meine ich, dass evtl. das der bessere Weg ist.
Im Grunde sollte man immer so wenig wie möglich an Takten in den ISRs 
haben, sonst es nicht mehr überschaubar wieviel für die einzelnen 
eigentlich bleiben und es kommt zu zunehmenden Konflikten.

Oder die Generierung des Manchester auf den kleinsten Attiny auslagern 
und dem per SPI oder einem Protokoll ähnlich der Shift Register das 
Ganze rüberschieben. :-)

von Peter D. (peda)


Lesenswert?

Andreas schrieb:
> der Timer Interrupt kommt alle 417us, das Ausgangssignal darf max. 10%,
> d.h. 40us abweichen.

Mit dem Compare Output hast Du entweder 0µs oder 417µs Abweichung (oder 
834µs usw.), 40µs geht nicht.

Du mußt mindestens alle 417µs den Interrupt behandeln können. Bei 
18,432Mhz sind das 7686 Zyklen Zeit. Darfst halt in den anderen 
Interrupts nicht soviel float rechnen.

von ich (Gast)


Lesenswert?

Conny G. schrieb:
> Oder die Generierung des Manchester auf den kleinsten Attiny auslagern

Nur mal eine Anregung: Normalerweise reicht doch ein XOR-Gatter, warum 
dann zur "Auslagerung" einen Prozessor verwenden?

von chris_ (Gast)


Lesenswert?

Wie oft muss denn der Code gesendet werden?

Eventuell ließe sich Dein Programm umstricken

loop
  manchesterflanke ( state machine dependend )
  timer reload
  read/write serial interface ( state machine dependend )
end loop

Das Timing dürfte damit wesentlich besser als Deine geforderten 40us 
Genauigkeit werden.

von Conny G. (conny_g)


Lesenswert?

ich schrieb:
> Conny G. schrieb:
>> Oder die Generierung des Manchester auf den kleinsten Attiny auslagern
>
> Nur mal eine Anregung: Normalerweise reicht doch ein XOR-Gatter, warum
> dann zur "Auslagerung" einen Prozessor verwenden?

Das XOR-Gatter muss man ja auch mit einem Takt ansteuern und dem TO geht 
es genau darum, dass er vor lauter anderer Interrupts diesen Takt nicht 
mehr genau einhalten kann.
Eine Variante ist die anderen ISRs etwas reduzieren im Takte-Bedarf, die 
andere: er schiebt die Bytes raus an einen Attiny und der hat dann alle 
Zeit der Welt für sein Timing.

von Conny G. (conny_g)


Lesenswert?

chris_ schrieb:
> Wie oft muss denn der Code gesendet werden?
>
> Eventuell ließe sich Dein Programm umstricken
>
> loop
>   manchesterflanke ( state machine dependend )
>   timer reload
>   read/write serial interface ( state machine dependend )
> end loop
>
> Das Timing dürfte damit wesentlich besser als Deine geforderten 40us
> Genauigkeit werden.

Das ist eine Variante von dem was ich sagte: ISRs entschlacken und mehr 
Arbeit in der Hauptloop verrichten.

von ich (Gast)


Lesenswert?

Conny G. schrieb:
> Das XOR-Gatter muss man ja auch mit einem Takt ansteuern und dem TO geht
> es genau darum, dass er vor lauter anderer Interrupts diesen Takt nicht
> mehr genau einhalten kann.

Stimmt auch wieder. Das hatte ich nicht bedacht. Asche auf mein Haupt 
:-)

von lars (Gast)


Lesenswert?

Conny G. schrieb:
> Das XOR-Gatter muss man ja auch mit einem Takt ansteuern und dem TO geht
> es genau darum, dass er vor lauter anderer Interrupts diesen Takt nicht
> mehr genau einhalten kann.
> Eine Variante ist die anderen ISRs etwas reduzieren im Takte-Bedarf, die
> andere: er schiebt die Bytes raus an einen Attiny und der hat dann alle
> Zeit der Welt für sein Timing.

der XmegaE hat die tolle Funktion dass man das XCL Modul zu einem XOR 
konfigurieren kann, dieses dann mit dem USART verbindet und schwups gibt 
es einen HW manchester encoder/decoder - und das mit minimalem CPU 
aufwand.
schau mal app note:
http://www.atmel.com/Images/Atmel-42164-AT03335-Manchester-Transceiver-using-the-USART-and-XCL-Modules-on-XMEGA-E_Application-Note.pdf

vielleicht macht es sinn hier weiterzumachen

von c-hater (Gast)


Lesenswert?

Andreas schrieb:

> Der Mega328 besitzt leider kein USI

Aber mindestens eine USART, die fähig ist, im SPI-Mode zu arbeiten. 
Damit kann man natürlich auch Manchestercode 100%ig exakt ausgeben.

> und die Länge würde nicht
> ausreichen.

Es gibt keine Längenbegrenzung. Du mußt es nur schaffen, ungefähr alle 
8 Brutto-Bit (im Falle von Manchester also alle vier Netto-Bit) ein Byte 
in's UDR-Register schreiben.

Das sollte bei den bescheidenen Bitraten, um die es hier wohl geht, 
selbst in einem völlig vergurkten C-Programm irgendwie realisierbar 
sein.

von Leo C. (rapid)


Lesenswert?

Andreas schrieb:
> Peter Dannegger schrieb:
>> Es reicht, wenn Du die Flanke irgendwann vor dem nächsten Compare
>> umstellst.
>
> Leider nicht, das schlägt sofort auf den Ausgang durch. Steht auch im
> Datenblatt in Kapitel 16.7.3.

Doch, Peter Dannegger hat Recht. Wahrscheinlich hast Du den letzten 
Absatz des Kapitels falsch verstanden.

Eine Änderung von COM1x ändert nicht sofort den Ausgang, sondern wirkt 
sich auf den nächsten Compare Match aus. "double buffered together with 
the compare value." würde bedeuten, daß die neuen COM1x-Werte erst nach 
dem nächsten Compare Match übernommen werden.

von Andreas (Gast)


Lesenswert?

Danke für die zahlreichen Hinweise!
Ich werde es nochmal mit der Compare Match Output Unit versuchen und 
zusätzlich die Interrupt Funktionen optimieren (obwohl sie nicht 
besonders groß sind und auch keine Floats beinhalten ;-)

Grüße,
Andreas

von Conny G. (conny_g)


Lesenswert?

Andreas schrieb:
> besonders groß sind und auch keine Floats beinhalten ;-)

Aber selbst C-Standard-String-Funktionen oder bestimmte Integer 
Multiplikationen/Divisionen können ziemlich viel Zeit verbrauchen.
Es gibt für manche Dinge wie z.B. Zahl-nach-String-Umwandlung spezielle 
µC-optimierte Implementationen, die nicht alles können, dafür aber ein 
Vielfaches schneller sind.

von Andre (Gast)


Lesenswert?

da war der Tipp mit dem DALI vom Lars nicht schlecht, der TE hat aber 
nen ATmega328p damit würde ich mir eher die DALI Slave Implementierung
für den ATmega88 anschauen der ja dem ATmega328p am nächsten ist.
Dort wird ja die Manchester Codierung gemacht, kann man sich wohl 
abgucken
http://www.atmel.com/images/Atmel-42071-DALI-Slave-Reference_Design_Application-Note_AT1244.zip

http://www.atmel.com/Images/Atmel-42071-DALI-Slave-Reference_Design_Application-Note_AT01244.pdf

alles in source code verfügbar

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.