Guten Tag, [Atmega 16/32] Ich möchte mehrere digitale Kanäle/Ausgänge (ca 8-16 Stück) zeitversetzt für eine variable Zeit (0,xms bis ca 5ms) schalten (Impulslänge variiert auch unter den einzelnen Kanälen). Zwischen den Schaltimpulsen der einzelnen Kanäle liegen in etwa 20ms. Daraus folgt ja, dass sich einzelne Impulse teilweise überschneiden. Ich habe mir schon einige Tutorials über den Timer durchgelesen, trotzdem weiß ich nicht, wie ich das realisieren kann mit der begrenzten Anzahl an Timern. Ich hoffe auf eure Hilfe, fluxkompensator
Kannst Du nicht den Timer auf die kleinste "Auflösung" stellen und dann bei jedem Tick entscheiden, welchen Impuls Du auslösen willst ? Also nicht ein Timer pro Impuls, sondern ein Timer für alle Impulse.
Hört sich logisch an. Kann ich bei der Abarbeitung dieser Vergleiche im main-programm einfach mit if-Befehlen arbeiten oder gibt es dann Probleme zwischen dem linearen Ablauf des Programms und der teilweisen Überlappung der Schaltzeiten?
Ich würde auch einen Timer mit einer Taktzeit von 1ms generieren und in der ISR dann über verschiedene Variablen einzelne Timer generieren. Wenn der Timer sofort wieder gestartet wird hast du da auch keine Zeitverzögerung.
vor dem schaltvorgang erstellt man sich eine tabelle erstellen mit dem portzustand sowie dem zeitstempel: zeit[] portausgabe[] 0 11110000 13 11100000 50 11100001 usw. den algorythmus kann man dann mit dem timer aufrufen (ein paar takte länger als die minimale ausführungszeit)
1 | if ( zeit[index+1] >= zähler) index++; |
2 | port = portausgabe[index]; |
3 | zähler++; |
wenn du das z.b. alle 0.1ms aufrufst hast du eine zeitliche auflösung von 0.1ms mit der du beliebig viele ausgänge ansteuern kannst ... vorrausgesetzt dein µC ist schnell genug.
Hallo, Die Idee von sam finde ich sehr gut. Ich hoffe, ich habe sie richtig verstanden: Man legt zunächst fest, wann welche Pins gesetzt werden und vergleicht dann mit der unteren Routine, ob es soweit ist? Ganz klar ist mir die Sache mit dem Index noch nicht. Und: Wie legt man so eine mehrspaltige Tabelle an? Ich benötige allerdings eine zeitliche Auflösung von 0.01ms, d.h. 10ns. Kann man irgendwie ausrechnen, ob bspw. ein ATmega16 oder ATmega32 mit 8/16MHz getaktet das hinbekommt? Viele Grüße, fluxkompensator
>Kann man irgendwie ausrechnen, ob bspw. ein ATmega16 oder ATmega32 mit >8/16MHz getaktet das hinbekommt? Ja. Wie groß ist denn die Periodendauer bei 8MHz? Vielfache davon passen in 10µs. Soviele Takte muß der Timer laufen, bis er einen Interrupt erzeugt (CTC-Mode). Bei 16MHz ist es halt die doppelte Anzahl.
Hallo STK500-Besitzer, Periodendauer bei 8MHz sind 125ns, dementsprechend bei 16MHz 62,5ns. Aber die Realisierbarkeit müsste ja auch noch davon abhängen, wie lange die Abarbeitung dieser Routine erfordert, oder? Und das kann ich halt überhaupt nicht einschätzen. Grüße, fluxkompensator
Der Timer arbeitet unabhängig von ISR-Länge. D.h. der Interrupt tritt auf jeden Fall auf, auch wenn die ISR noch abgearbeitet wird. Man sollte ISRs immer so kurz wie möglich halten. Bei einer Taktfrequenz von 8MHz hätte man dann zwei Interrupt Zeit für etwa 80 Befehle (Befehle mit 1 Takt Abarbeitungszeit). Man sollte also in die ISR nur eine Variable herunterzählen, die den Abstand zum nächsten Schaltpunkt angibt und dann den nächsten Wert an den Port schreiben. Das sollte sogar in C noch ohne besondere Optimierungseinstellungen gehen.
Ich glaube, für dieses Problem sind software-Timer gut geeignet, deren Anzahl ist im Gegensatz zu Hardware-Timern nicht beschränkt, Sie Dir mal Peter Danegger's Timer an, zB: Beitrag "Wartezeiten effektiv (Scheduler)" oder den von Jörg Wunsch: http://www.sax.de/~joerg/avr-timer/ . Die Timer-Tick-Rate legt die Auflösung fest. -Michael
die liste ist ein normales array in c ... int_array ist quasi der zeiger auf den anfang des speicherbereichs und der index in eckigen klammern ist das zu dem zeiger addiert wird vor der dereferenzierung
1 | int int_array[3]; |
2 | |
3 | int_array[0]=2; |
4 | int_array[1]=8; |
5 | int_array[2]=5; |
was mir noch einfiel : wenn sich diese einzelnen signale zyklisch wiederholen sollen, sollte man sich ein anderes system überlegen. wenn der schaltvorgang einmalig ist oder insgesamt zyklisch, muss man die hilfsvariablen ja nur zurücksetzen. dazu ist zu beachten, dass man mit mind. 16 bit zählen sollte und evtl eine 16 bit portmaske braucht ... und 16 bit auf einem 8 bit prozessor zu benutzen, braucht ja mind. doppelt soviel zeit zur ausführung. im avr-studio kann man ja in der simulation die ausfrührungszeit anschauen. der atmega48 oder atmega 88 läuft auch mit 20 MHz ... falls du noch etwas rauskitzeln willst.
Das ganze soll sich zyklisch wiederholen. Die Zyklen sind variabel zwischen 20ms und 200ms lang. (Regle ich mit einem ADC) In jedem Zyklus sollen alle ca 16 Signale zeitlich möglichst gut aufgeteilt, d.h. versetzt, ausgegeben werden. Dass sich die Signale dabei teilweise überschneiden ist mir klar. Grüße, fluxkompensator
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.