Exakter Manchester Code mit ATmega328 generieren

Gast #3554789
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
#3554807
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.
Gast #3554821
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
#3554844
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. :-)
#3554850
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.
Gast #3554860
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.
#3554870
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.
#3554877
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.
Gast #3554922
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
Gast #3555163
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.
#3555369
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.
Gast #3558559
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
#3558568
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.
Gast #3558965
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

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