Hallo,
ich habe mir eine Funktion geschrieben die mehrmals mit
unterschiedlichen Übergabewerten aufgerufen werden soll.
Diese Funktion gibt etwas auf der seriellen Schnittstelle aus.
In meinen Fall merke ich, dass nur Eine alleine funktioniert. Sobald ich
eine zweite
1
TasterDimmenAufAb (xx,xx);
aufrufe, funktioniert das nicht mehr. Auch der, der schon funktioniert
hat streikt.
Weiss jemand wodran das liegen könnte und mir dieses mitteilen?! Danke!
Stefan schrieb:> Diese Funktion gibt etwas auf der seriellen Schnittstelle aus.
An welcher Stelle gibt die Funktion denn etwas auf der seriellen
Schnittstelle aus?
Woher weißt du, dass die Funktion nur einmal funktioniert?
Deine Fehlerbeschreibung finde ich etwas dürftig.
Lass eine LED kurz aufleuchten, wenn du in die funkion springst, schiebe
den Aufleuchtbefehl schritweise durch die Funktion, wenn du meinst, es
läge an der Funtkion - kurz gesagt - such dir ein Mittel für einfaches
debuggen und stell fest, was eigentlich nicht so funktioniert, wie es
geplant war
Wieso nutzt du in deiner Funktion Statische Variablen?? Das verursacht
Seitenefekte die nicht immer gewünscht sind also das Schlüsselwort
"static" nur gut überlegt verwenden.
tripod schrieb:> Wieso nutzt du in deiner Funktion Statische Variablen?? Das verursacht> Seitenefekte die nicht immer gewünscht sind also das Schlüsselwort> "static" nur gut überlegt
Glaub da ist auch mein Fehler. Was genau passiert mit den Static wenn
die Funktion das zweite mal, mit anderen Übergabewerten, aufgerufen
wird?
Generell steht Static ja für:
Im Kontext einer Variablendeklaration innerhalb einer Funktion sagt
dieses Schlüsselwort, dass diese Variable auf einer festen
Speicheradresse gespeichert wird. Daraus ergibt sich die Möglichkeit,
dass eine Funktion, die mit static-Variablen arbeitet, beim nächsten
Durchlauf die Informationen erneut nutzt, die in der Variablen
gespeichert wurden (wie in einem Gedächtnis).
Gilt das denn auch wenn die Funktion das zweite mal mit anderen
Übergabewerten aufgerufen wurd? Dann sollen natürlich neue Variablen
angelegt werden. Die dann jeweils in der Funktion benutzt werden können.
Stefan schrieb:> Glaub da ist auch mein Fehler. Was genau passiert mit den Static wenn> die Funktion das zweite mal, mit anderen Übergabewerten, aufgerufen> wird?
Normal werden lokale Variablen innerhalb einer Funktion erst beim
Aufrufen der Funktion erzeugt und nach dem Verlassen wieder freigegeben.
Dadurch kann man die Funktion z.B. mehrfach verschachtelt (rekursiv)
aufrufen, ohne dass es zu Problemen kommt.
Mit dem Ausdruck "static" ändert sich dieses Verhalten. Die Variablen
innerhalb der Funktion sind permanent im Speicher, quasi wie globale
Variablen. Verlässt man die Funktion, bleiben die Werte erhalten. Ruft
man die Funktion zweimal "gleichzeitig" auf, zB einmal im Hauptprogramm,
einmal im Interrupt, knallts so richtig ;-)
Gruß
Björn
Stefan schrieb:> Gilt das denn auch wenn die Funktion das zweite mal mit anderen> Übergabewerten aufgerufen wurd?
Selbstverständlich. Was der Funktion beim Aufruf übergeben wird hat
keinerlei Einfluss darauf, wo Variablen abgelegt werden, die die
Funktion nutzt. Statische Variablen existieren genau einmal.
> Dann sollen natürlich neue Variablen angelegt werden.
Dann kannst Du dafür keine statischen Variablen verwenden, sondern musst
automatische Variablen nutzen (die halt nur während der Laufzeit der
Funktion gültig sind und bei jedem Aufruf neu angelegt werden).
DirkB schrieb:> Und die Initialisierung wird nur einmal (beim ersten Aufruf oder davor)> durchgeführt. Danach behalten die static-Variablen ihren Wert.
Die Variablen werden noch vor dem start von main() initialisiert. Genau
wie normale globale Variablen. Deswegen kann man die static variablen
auch nur mit (zum Compilierzeitpunkt) konstanten Werten initialisieren,
und nicht etwa in der Funktion erst berechnen.
static Variablen in einer Funktion sind also eigentlich völlig identisch
zu normalen globalen Variablen. Mit einem Unterschied: du kannst nur
innerhalb der Funktion drauf zugreifen. Außerhalb sind sie unsichtbar.
Stefan schrieb:> Gilt das denn auch wenn die Funktion das zweite mal mit anderen> Übergabewerten aufgerufen wurd? Dann sollen natürlich neue Variablen> angelegt werden.
Den als Static deklarierten Variablen ist es schnurzpiepegal, mit was
für Übergabewerten die Funktion aufgerufen wird.
Leider funktioniert es doch nicht. Ich dachte erst, dass wäre der Fehler
mit dem "static". Habe es Spaßeshalber mal so gelöst (s.unten). Keine
Änderung des Fehlers
Ich merke, dass die "---4---" auf der seriellen Sschnittstelle dauernd
kommt, obwohl da nur die steigende Flanke abgefragt wird. Das darf also
nicht passieren, wird wohl mit dem Fehler zu tun haben. Im Main siehts
so aus:
Die "---0---" oder "---8---" ommt wie zu Erwarten nur bei steigender und
fallender Flanke.
Ich weiss nicht wie ich das hin bekomme, was mache ich nur flasch?
Vielleicht beschreibst Du mal in Worten, was das Programm überhaupt
machen soll.
Ein PAP wäre natürlich noch besser.
Es sieht doch alles irgendwie aus, wie einfach drauflos programmiert.
Ich vermute mal, mit meiner Tastenroutine (kurz, lang, repeat) würde
sich ein Großteil des Codes in Luft auflösen.
Peter
Hallo Stefan!
Hab' jetzt nicht alles om Datail gelesen, aber:
Versuchst Du eine Funktion, die EINE UART verwendet mehrere male
aufzurufen?
Das könnte zu großen Problemen führen!
Was macht eigentlich R_TRIG?
Alles in allem finde ich deinen COde extrem unübersichtlich.
Meherer Arrays parallel zu führen ist immer eine etwas problematische
Sache. Fasse doch erst mal ALLE Werte, die zu einem Eingang gehören in
eine gemeinsame Struktur zusammen (und benutze ein paar vernünftige
kurze Namen für die Member)
damit hast du alle Werte beisammen, die du für EINEN Eingang benötigst
(wenn noch was fehlt: nur zu, ruhig ergänzen.
Jetzt hast du aber nicht 1 Taste, sondern du hast 50 davon
1
InputDescInputs[50];
und um die Taste mit der Nummer 5 bearbeiten zu lassen, übergibst du 1
derartige Struktur (per Pointer) an die Funktion
Das hat jetzt 2 Vorteile
* zum einen hast du in der Funktion immer alle Werte eines Eingangs
mit. Du brauchst nicht wegen einer Erweiterung groß umändern.
Einfach den neuen Member in die Struktur einfügen und du hast
den Member in der Funktion zur Verfügung. Und zwar immer den
richtigen, den der zum jeweiligen Eingang gehört
* zum anderen läufst du nicht Gefahr, dass du dich in der Array-
Indexierung irgendwo verhaust und irgendwo den falschen Index
benutzt. Du hast in der Funktion nur 1 Eingang (in Form eines
Pointers) und alle Werte gehören unter Garantie zu diesem
Eingang
(Ich hab jetzt deinen Code nur auf eine Struktur umgeändert. An der
Logik hab ich nichts verändert. D.h. dein Fehler wird immer noch drinnen
sein.
Deine Form des Source Codes sieht zwar nicht schlecht aus, mir
persönlich ist das aber zu unübersichtlich, zu sehr in die Länge
gezogen. Die vielen if am Funktionsanfang kommen mir aber spanisch vor.
Ich denke da stimmt was nicht. Entweder das, oder so wie du dir R_TRIG
vorstellst, funktioniert das nicht (und ich kann mir erhlich gesagt
nicht vorstellen, wie R_TRIG funktionieren soll. Um eine Flanke zu
erkennen, benötigt man 'alte' Information von einem Eingang um
vergleichen zu können, ob sich der Eingang verändert hat - aber von
diesem EINEN Eingang. Nicht von irgendeinem Eingang. D.h. diese "alte"
Information müsste ebenfalls in der Struktur sein. Ich kann aber in
deinem Code nicht erkennen wie das über R_TRIG funktionieren könnte -
und ich kann mir ehrlich gesagt ach nicht vorstellen wie das überhaupt
funktionieren soll.
PS: Mach dasselbe nochmal für deine Lichter - Struktur einführen, in der
du dir alle Kennwerte für ein Licht zusammenfasst.
Wartbare und überschaubare Programme zu schreiben, hat auch damit zu
tun, dass man sich selbst Struktur ins Programm bringt. Einfach einen
Haufen Variablen zu haben, vielleicht noch das eine oder andere Array -
das ist noch lange keine Programm-Struktur. Wo das hinführt, siehst du
jetzt ja: Nichts funktioniert und du hast keine Ahnung warum.
Und das wirklich witzige an der Sache ist, dass wenn du die PeDa
Entprellung benutzen würdest, dann wäre dieser Teil mit Tastenauswertung
und Key Repeat regelrecht pipifax.
Hi Karl Heinz und dem Rest...
Supervielen dank schonmal vorab... Das hilft und lehrt mich sehr
weiter...
Ich werde das morgen noch einmal neu aufsetzen und testen!
Schonmal so gesagt:
Ich will eine Funktion schreiben die dafür ist eine Lampe zu dimmen, per
Tastschalter. Auf-abdimmen per gedrückt halten des Tasters.
Ein-ausschalten per kurzem drücken. Gesinnt wird im anderen
Mikrocontroller der an der seriellen hängt!
Der R_Trig ist die PeDa EntprellRoutine... Im Eingang[x] ist die
jeweilige Taste. Bei gedrückt "True" bei losgelassen "False".
Ich meld mich morgen wieder, danke!
Stefan schrieb:> Hi Karl Heinz und dem Rest...> Supervielen dank schonmal vorab... Das hilft und lehrt mich sehr> weiter...> Ich werde das morgen noch einmal neu aufsetzen und testen!> Schonmal so gesagt:> Ich will eine Funktion schreiben die dafür ist eine Lampe zu dimmen, per> Tastschalter. Auf-abdimmen per gedrückt halten des Tasters.> Ein-ausschalten per kurzem drücken. Gesinnt wird im anderen> Mikrocontroller der an der seriellen hängt!
EIn paar Gedanken dazu.
Wenn die Taste niedergedrückt wird .... kannst du erst mal noch gar
nichts aussagen, was passieren soll. Weder in der einen Form noch in der
anderen. Das einzige was du beim Niederdrücken tun kannst ist: die
Zähler auf 0 setzen.
Warum ist das so?
Weil du beim Niederdrücken noch nicht weißt, wie lange die Taste
gedrückt gehalten werden wird (Zukunft).
D.h. das ist schon mal dein erster Fall:
Wird die Taste niedergedrückt?
Ja ---> alle bereit machen bzw. initialisieren
Der zweite Fall, an dem du eine Unterscheidung einbauen musst, ist der
Fall: ist die Taste gedrückt?
In diesem Fall geht dann die Unterscheidung weiter:
Wie lange ist die Taste schon gedrückt?
Ist das noch zu kurz, dann tust du wieder gar nichts.
Bist du über der Grenze drüber, dann wird gedimmt
Und der Schlussendlich letzte Fall ist das Loslassen der Taste.
AUch hier gibt es wieder 2 Fälle. Nämlich
War die Zeit des Niederdrückens zu kurz, so dass das Dimmen nicht
eingesetzt hat, dann schalte den Ausgang um. (Allerdings würde ich da
noch eine gewisse Mindestdauer fordern. Das ist dann auch gleich
automatisch dein Entprellen. Verging vom Niederdrücken bis zum Loslassen
zu wenig Zeit, dann war das ein Tastenpreller und kein gezieltes
Niederdrücken).
War die Zeitg aber lang genug, dann tu gar nichts, denn dann hat das
Dimmen vom Fall-2 bereits die Aktion erledigt.
Das ganze ein wenig vernünftig angeschrieben und eigentlich ist das dann
kein Problem mehr.
Funktionieren tat mein Programm für einen Taster auch schon. Aber nicht
wenn ich die Funktion zweimal aufgerufen hatte für einen zweiten
Taster...
Ich verinnerliche erst einmal das mit der Struktur und schreibe die
Funktion um!
Meld mich...
Stefan schrieb:> Funktionieren tat mein Programm für einen Taster auch schon. Aber nicht> wenn ich die Funktion zweimal aufgerufen hatte für einen zweiten> Taster...
Also hat es nicht funktioniert :-)
(Im Ernst: Ich hab zwar die Funktion überflogen, aber nichts gesehen,
was dein spezifisches Problem verursachen könnte. Das einzige ist das
Makro R_TRIG, das mir ein in seiner Verwendung ein wenig dubios
vorkommt.
Und bei der Gelegenheit ist mir aufgefallen, dass der Anfang deiner
Funktion nicht besonders leicht zu durchschauen ist - falls er überhaupt
richtig ist. Für eine eigentlich einfache Sache sollte das nicht so
sein, dass man den Code 10 Minuten studieren muss, ehe man rausfindet
was da eigentlich die Idee in diesem Codestück ist. Sowas ist oft ein
Hinweis darauf, dass da in der ganzen Codestruktur was nicht stimmt. Und
wenn ich dann sehe, dass in jeder Zeile mindestens einmal auf ein Array
(jeweils ein anderes) mit dem immer gleichen Index zugegriffen wird,
dann seh ich schon mal das Problem, dass die Datenstruktur nicht
durchdacht wurde. Gewöhn dich daran: Für ein hinreichend komplexes
'Objekt' baut man sich eine struct, in der die Daten dieses Objekts
zusammengefasst werden. VIele Arrays, die parallel gehalten werden
müssen, sind irgendwann ein 'pain in the ass'. Ich hab hier auch Code
von einem Vorgänger, der anscheinend ausser Arrays keine anderen
Möglichkeiten zur Datenstrukturierung kannte. Entsprechend mühsam ist
es, zu kontrollieren ob er bei Manipulationen in der Reihenfolge in den
Arrays auch wirklich immer alle entsprechend umsortiert hat. Da gibts
dubiose Fehler. Nur mit dem Unterschied, dass der Code hier ein paar
tausend Zeilen hat :-) Ich hab dann gleich mal eine struct eingezogen,
mit dem Erfolg dass viele duibose Fehler verschwunden sind und dafür im
Gegenzug neue aufgetaucht sind. Und siehe da: die neuen Fehler sind zu
einem großen Teil dadurch entstanden, dass er bewusst falsch in die
Arrays zugegriffen hat, weil er wusste, dass an dieser Stelle die
Reihenfolge schon falsch ist und er auch weiß, wie sie falsch ist.
Manchmal möchte man wirklich mit dem nassen Fetzen ....
Die Repeat-Funktion bei mir funktioniert nur bei einer Person, d.h. eine
Taste drücken zur Zeit.
Wenn Du aber 50 Tasten anschließen willst, sollen die vermutlich auch
mehrere Personen drücken. Dann braucht jede ihren eigenen Repeat-Zähler.
Ich würde dann aber jeder Taste + PWM ihren eigenen ATtiny13 spendieren
und nicht alles einen AVR machen lassen. Das verringert auch erheblich
das ganze Kabel-Wirrwarr.
Peter
bekomme dann aber die Fehlermeldung:
Compiling: main.c
avr-gcc -c -mmcu=atmega1284p -I. -Os -funsigned-char
-funsigned-bitfields -fpack-struct -fshort-enums -Wall
-Wstrict-prototypes -Wa,-adhlns=main.lst -fno-inline-small-functions
-fno-split-wide-types -fno-move-loop-invariants -mcall-prologues
-ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax
-std=gnu99 main.c -o main.o
In file included from main.c:21:
main.h:63: error: expected ';', ',' or ')' before '&' token
make.exe: *** [main.o] Error 1
Wenn ich eine Struktur/Pointer einer Funktion übergeben wollte hatte ich
das bis dato so gelöst: uint16_t Test( struct TestStrukt* theStruktur
Stefan schrieb:> Hier ist der Code(PeterDanneger)
Schön, das nach so vielen Postings endlich mal zu erfahren :-(
Stefan schrieb:> Warum geht das denn nicht für zweit Eingänge?!?
Weil Du die Beschreibung dazu nicht gelesen hast!
Sie darf je Taste nur an einer Stelle aufgerufen werden.
Sie muß für jede Taste separat aufgerufen werden.
3-mal aufrufen und mit Taste als Variable ist also doppelt falsch.
Und 50 Tasten gehen ohne größere Änderungen schon mal garnicht.
Peter
Hi Peter,
Ok, ich habe mir jetzt mal eine steigende und fallende Flanke selber
gebastelt.
Ich merke jedoch wenn ich die Funktion in der main hin schreibe
funktioniert es. Die steigende Flanke und fallende Flanke wird genau
einmal erkannt. "---1---" und "---2---" werden passend ausgegeben.
Rufe ich jedoch die Funktion noch einmal auf (memm2 = TasterDimmenAufAb
(Eingang[1], &Eingang_1);) Sehe ich auf der seriellen ganz oft
"---1---" und "---2---" wenn ich den Taster - egal ob 0 ooder 1 -
gedrückt halte.
Wodran kann das denn wohl liegen ? Das ist das gleiche Verhalten wie mit
deiner Entprellroutine
in der main.c Hauptschleife
Hallo Stefan,
die Funktion ist aus meiner Sicht nur etwas für einen schnelle
Entprellung eines Tasters.
Für viele hat Peter einen richtige gute Bibliothek geschrieben.
Hier ist der Einstieg in das Thema:
Beitrag "Universelle Tastenabfrage"