Autor |
Mehr als 4 Timer realisieren Suche nach: timer (2124) |
|
|
|
|
BID = 685310
gerhard54 Gelegenheitsposter
Beiträge: 76 Wohnort: Wien
|
|
Hallo
ich möchte folgende Funktion mit einem Atmega realisieren:
Nach dem Setzen eines Eingangs soll ein Ausgang für eine bestimmte Zeit (einige Sekunden) gesetzt und dann wieder gelöscht werden. Und zwar sollte diese Funktionalität für meher E/A-Paare gleichzeitig, aber mit unterschiedlichen Startzeiten möglich sein.
Ein Beispiel, mit einer Verzögerung von 5 Sekunden
Sekunde 1: Eingang 1 wird gesetzt, Ausgang 1 schaltet ein
Sekunde 2: Eingang 2 wird gesetzt, Ausgang 2 schaltet ein
Sekunde 6: Ausgang 1 schaltet ab
Sekunde 7: Ausgang 2 schaltet ab
Alles kein Problem, wenn nicht mehr E/A-Paare gleichzeitig aktiv sind, als der ATMEGA Timer hat. Es sollen aber mehr sein! Etwa 20, die EA's werden über einen Bus gesteuert...
Und jetzt meine Frage:
hat jemand schon einmal dieses Problem gelöst? Gibt's Code Schnipsel dafür?
Ich bin für jede Anregung dankbar, die es mir erspart die Sache von Grund auf zu programmieren.
Grüße
Gerhard |
|
BID = 685315
Her Masters Voice Inventar
Avatar auf fremdem Server ! Hochladen oder per Mail an Admin
Beiträge: 5308 Wohnort: irgendwo südlich von Berlin
|
|
da braucht man nur einen einzigen Timer. Der macht seine Interrupte in regelmässigen Intervallen und bei Jedem kann man eigene Zähler hochzählen wie man mag. Ausserhalb des Interrupts werden die Zähler dann ausgewertet und die entsprechenden Pins gesetzt oder gelöscht. Wo soll da das Problem sein?
_________________
Tschüüüüüüüs
Her Masters Voice
aka
Frank
***********************************
Der optimale Arbeitspunkt stellt sich bei minimaler Rauchentwicklung ein...
*********************************** |
|
BID = 685327
Nukeman Schriftsteller
Beiträge: 754 Wohnort: bei Kleve
|
Ich lass für sowas aus nem Timer-Interrupt z.B. mit einer Schleife immer Elemente
aus einem Array bis 0 runterzählen. Nur wenn Array-Element noch nicht 0, wird eins
runtergetickt.
Der Vorteil ist dann, dass man
a) aus main() die Laufzeit individuell und variabel bestimmen kann
b) im Interrupt nicht auf bestimmte Werte checken muss, wenn untersch. Laufzeiten
gewünscht sind.
Gruß
Stefan
edit: Schleife, nicht Schleide ( bin froh, dass ich nicht noch einen Fehler mehr
in dem Wort untergebracht hatte )
[ Diese Nachricht wurde geändert von: Nukeman am 20 Apr 2010 22:58 ]
|
BID = 685328
gerhard54 Gelegenheitsposter
Beiträge: 76 Wohnort: Wien
|
Hallo,
ja so ungefähr hab' ich es mir auch vorgestellt.
NUR: "Hochzählen bei Interrupts verwalten" ist bei einer im vorhinein nicht bekannten Anzahl von Instanzen ist ein ziemlicher Programieraufwand, mit einer recht beachtlichen Möglichkeit Fehler zu machen...
Daher meine Frage: hat so etwas schon wer programmiert?
Wenn nicht, muß ich's eh selber machen.
Ich versuche mir einfach eine Menge Schreib- und Debugaufwand zu ersparen.
Also:
Wenn jemand ein bißchen Input spendet, verspreche ich, das Ergebnis hier zu veröffentlichen....
LG
Gerhard
|
BID = 685334
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Zitat :
|
einer im vorhinein nicht bekannten Anzahl von Instanzen ist ein ziemlicher Programieraufwand
|
Dann geh von der maximal möglichen Anzahl aus. Dann haste halt ein paar Byte RAM zuviel statisch alloziiert, wenn nicht alle genutzt werden.
Der Aufwand, vor allem an Rechen, RAM- und ROM-Ressourcen für eine dynamische Verwaltung ist auf nem Mega8 zu groß.
P.S.: in der ISR würde ich die Berechnungen nicht durchführen. Erstens, weil dann die Codegröße enorm hochgeht, zweitens weil es ein paar µs dauert und drittens weil die Zeitintervalle recht groß sind und so ein paar ms mehr oder weniger egal sind.
-> Flagge in der ISR setzten und im Hauptprogramm erledigen.
_________________
|
BID = 685335
gerhard54 Gelegenheitsposter
Beiträge: 76 Wohnort: Wien
|
Hallo Stefan,
Deine Antwort hat sich mit meiner auf die an "Her Masters Voice" gekreuzt.
Ein Array, in dem heruntergezählt wird: der Ansatz gefällt mir sehr gut!
Programmierst Du das "Hard Core" oder hast Du da Klassen definiert, die die Sache ein bißchen abstrahieren?
Ich träume von einer Lösung, wo man eine Instanz eines Timers erstellt und das Array und die Sache mit dem Herunterzählen wird vom Konstruktor erledigt...
In der main-Schleife frage ich dann ab, ob der Timer abgelaufen ist, während im Hintergrund der Destruktor aufräumt...
Grüße
Gerhard
|
BID = 685337
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
*Zonk*
Sowas kann man mit 20 Assemblerbefehlen erledigen (übern Daumen gepeilt) und du kommt mit C++...
_________________
|
BID = 685340
Nukeman Schriftsteller
Beiträge: 754 Wohnort: bei Kleve
|
Hallo Gerhard,
soll's C, Bascom oder ASM sein?
Bei Timern im Sekundenbereich würde ich das sogar eher noch ohne Interrupts machen.
Timer-Überläufe (des Hardware-Timers) kann man dann auch in einer Hauptschleife
abfragen und somit trotzdem sehr genau bleiben.
Gruß
Stefan
Für c so in etwa:
Code : |
char timer[20];
void main( void )
{
char x;
( hw-timer 0 entsprechend konfigurieren..)
while( 1) // hauptschleife
{
// Timer-Kram
if( (TIFR & (1<<TOV0)) ) // T0 ovfl?
{
TIFR |= (1<<TOV0); // T0-ovfl wieder löschen
for( x=0; x<sizeof(timer); x++ )
{
if( timer[x] )
{
if( --timer[x] == 0 )
{
( aktion fuer timer x ausführen )
}
} // timer noch aktiv
} // for
} // if
// externe Bedingung-Kram
if( externe Bedingung erfolgt )
{
timer[0] = 20; // Time
timer[1] = 4;
...
}
} // while
}
|
|
1.Huch, wird hier schnell gepostet, wenn man mal kurz Kram zusammenschreibt
2.Klammerfehler im Pseudocode
[ Diese Nachricht wurde geändert von: Nukeman am 20 Apr 2010 23:23 ]
|
BID = 685387
hajos118 Schreibmaschine
Beiträge: 2453 Wohnort: Untermaiselstein
|
1) Kann der WinAVR C - Compiler tatsächlich C++ ?
2) Wie groß wird der Code ?
Ich verwende ausschließlich Standard C - das genügt!
Zum Problem:
Array und dekrementieren - wegen Geschwindigkeit wenn möglich im 8-Bit Bereich bleiben ...
alternativ:
1 Zentraler Zähler (in ISR inkrementiert = "jetzt"), Timerwerte[x] beim setzten auf tick[x] = (jetzt + dauer) setzten und in der Hauptschleife mit
if "jetzt > tick[x]" abfragen.
Vorteil: nur 1 inkrement + 1 Abfrage pro Timer.
Achtung: hoher Aufwand bei Überlauf des "jetzt".
edit:
Wahrscheinlich kannst Du den einzelnen Aufgaben feste Indizes zuordnen - damit wird dann die Verwaltung der Unterroutinen einfacher.
z.B.
if jetzt > tick[1] work1();
if jetzt > tick[2] work2();
if jetzt > tick[3] work3();
if jetzt > tick[4] work4();
...
_________________
Interpunktion und Orthographie dieses Beitrags sind frei erfunden.
Eine Übereinstimmung mit aktuellen oder ehemaligen Regeln wäre rein zufällig und ist nicht beabsichtigt.
Wer einen Fehler findet, darf ihn behalten!
[ Diese Nachricht wurde geändert von: hajos118 am 21 Apr 2010 10:16 ]
|
BID = 685390
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Hallo Hajos,
Zitat :
|
1) Kann der WinAVR C - Compiler tatsächlich C++ ?
2) Wie groß wird der Code ?
|
zu 1:
Ja, kann er.
Das Backend bzw. den ganzen Toolchain-Rattenschwanz dafür kannst du, analog zum 'normalen' GCC C++-Backend (g++) mit avr-g++ aufrufen.
C++ wird allerdings nicht komplett unterstützt (kaum ein Compiler unterstützt alles, was C++ rein theoretisch können sollte... ).
Exceptions, new, new[], delete und delete[] sind nicht implementiert, wobei man sich letztere mit der libc zusammenbauen könnte, indem man new und delete überlädt und intern dann mit malloc und free arbeitet.
Weiterhin ist die STL und die STDC++ nicht vorhanden...
Die ist auch wesentlich größer als der ROM der kleineren AVRs und dafür auch schlicht und ergreifend nicht gemacht.
Achja, alle Arten von virtuellen Methoden/Konstruktoren etc. tunlichst vermeiden.
Auch RTTI und andere nette Dinge nicht verwenden. Braucht alles zuviel Ressourcen.
zu 2:
Ansich ist der Code recht gut, wobei er auch bei bester Optimierung auf Codegröße etwas größer wird. Das liegt vor allem daran, dass man in C++ gerne objektorientiert programmiert und in den Klassen permanent der this-Zeiger mitgeschleppt wird. Rein imperative Dinge wie in C gehen in C++ dann ähnlich flott.
Und wenn wirklich dynamische Speicherverwaltung über die libc genutzt wird, kannst du dich auf gigantische Codegröße einstellen...
Ansonsten habe ich einige, auch den Mega8 und Mega48 in C++ programmiert. Da ging es aber um "Luxus".
Es macht ein Programm schöner, wenn ich mit eigenen Datentypen auch eigene Operatoren einführen kann. Aber wie gesagt, alles zu lasten der Codegröße.
(Performant bleibt es dennoch, wenn man es ordentlich macht!)
Edit:
Zitat :
|
Ich verwende ausschließlich Standard C - das genügt!
|
Jau, sauberes C z.B. nach ansi ist eigentlich das beste.
Einige Programme laufen bei mir auf AVRs, ARMs, AVR32s und x86. Ohne eine Zeile am C-Kode zu ändern...
_________________
[ Diese Nachricht wurde geändert von: DonComi am 21 Apr 2010 10:49 ]
|
BID = 686232
gerhard54 Gelegenheitsposter
Beiträge: 76 Wohnort: Wien
|
Also einmal schönen Dank für die vielen Anregungen.
Nur der Vollständigkeit halber: eigentlich schreibe ich die meisten Programme in ANSI C. Ich versuch' nur seit 15 Jahren den Einstieg in C++ zu machen, und da habe ich mir gedacht: so eine Timer-Klasse wär doch was für den Angfang...
Liebe Grüße aus Wien
Gerhard
|
BID = 686254
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Hallo Gerhard,
ist auch machbar. Ich habe aber leider nichts passendes zur Hand.
Bei einer Sekunde Intervall kommt es nicht auf ein paar ms an, die ein C++-Handler benötigt.
Ich hätte da sogar was im Kopf, aber ich habe keine Zeit.
Dazu zählt eine abstrakte Timerklasse, an die man Funktionen über deren Adresse anhängen kann. Läuft die Zeit der entsprechenden Methode/Funktion ab, wird sie aufgerufen.
Man kann es aber ganz schön kompliziert machen...
_________________
|
BID = 687090
gerhard54 Gelegenheitsposter
Beiträge: 76 Wohnort: Wien
|
Natürlich kann man es nicht nur, sondern man sollte es auch... sonst machts ja keinen Spaß.
Gerhard
|