Hallo in die Runde!
Ich habe insgesamt sieben Taster an meinem INT0 angeschlossen. Je
nachdem welcher gedrückt wird, soll etwas anderes passieren.
Nun stehe ich aber vor der Frage, wie ich das in meinem Code umsetzen
soll, da ich bisher immer nur mit einem Taster pro Interrupt gearbeitet
habe.
Meine erste Idee war es, im ISR die Taster mit if-Bedingungen
voneinander zu trennen.
Dies habe ich schon auf verschiedene Weisen getestet.
Sowohl
1
if(~(PIND&(1<<PD0)))
2
{
3
//Ausführung
4
}
5
6
if(~(PIND&(1<<PD1)))
7
{
8
//Ausführung
9
}
als auch
1
if(PORTD|=(1<<PD0))
2
{
3
//Ausführung
4
}
5
6
if(PORTD|=(1<<PD1))
7
{
8
//Ausführung
9
}
Nur ist das Problem, dass auch beim Betätigen des zweiten Tasters die
Anweisungen vom ersten Taster ausgeführt werden. Wie kann ich die beiden
denn voneinander trennen?
Die Taster sind mit Dioden angeschlossen und mechanisch entprellt.
Liebe Grüße!
Lampion :)
Dein Grundgedanke ist schon richtig.
Alle Taster springen in das gleiche Interrupt und im Interrupt musst du
dann den Eingangs-Port einlesen und bei Bedarf maskieren. Am besten
einfach den Port in ein Byte schreiben und dann kannst du in deiner
Main, wo dann die Auswertung stattfindet, auf den richtigen Taster
maskieren. Dann hast du ein Flag, dass der Zustand eines Tasters
geändert wurde und ein Byte, in dem du dann herausfinden kannst, welcher
es war.
Lampion schrieb:> Die Taster sind mit Dioden angeschlossen
Welche Taster sind da wie angschlossen? Gibt es irgendwelche
Pullups/-downs?
> und mechanisch entprellt.
Sind sie mit dieser mechanischen Entprrellung auch garantiert
elektrisch entprellt?
> Nur ist das Problem, dass auch beim Betätigen des zweiten Tasters die> Anweisungen vom ersten Taster ausgeführt werden.
Warum?
> Wie kann ich die beiden denn voneinander trennen?
Es läuft immer wieder darauf hinaus: wie sind sie denn miteinander
verschaltet?
>Ich habe insgesamt sieben Taster an meinem INT0 angeschlossen.
Fernbedienung? Schließ die sieben Taster an sieben Pins an und verwenden
den Pin Change Interrupt. Dafür gibt es ihn.
Huch, das sind aber schnelle Antworten ^^'
Sebastian R. schrieb:> Alle Taster springen in das gleiche Interrupt und im Interrupt musst du> dann den Eingangs-Port einlesen und bei Bedarf maskieren. Am besten> einfach den Port in ein Byte schreiben und dann kannst du in deiner> Main, wo dann die Auswertung stattfindet, auf den richtigen Taster> maskieren.
Danke, das probiere ich gleich mal aus, ob ich das so hinbekomme :)
Lothar M. schrieb:> Warum?
na das frag ich ja.
LostInMusic schrieb:> Fernbedienung? Schließ die sieben Taster an sieben Pins an und verwenden> den Pin Change Interrupt. Dafür gibt es ihn.
Die Taster sind natürlich an PINS angeschlossen, sollen aber über den
Interrupt aufgerufen werden.
Von dem Pin change Interrupt hab ich noch nie gehört. Kannst du mir
evtl. eine Seite geben, wo das gut erklärt ist?
Ich hoffe, dass der Plan, den ich angehängt habe, der aktuellste ist ^^'
LostInMusic schrieb:> Schließ die sieben Taster an sieben Pins an und verwenden> den Pin Change Interrupt. Dafür gibt es ihn
... an neueren ATmegas als den vom TO verwendeten ATmega16.
Oliver
Hi
>Von dem Pin change Interrupt hab ich noch nie gehört. Kannst du mir>evtl. eine Seite geben, wo das gut erklärt ist?
Besitzt der ATMega16 nicht.
MfG Spess
Deine if Bedingung stimmt einfach nicht.
Der Taster zieht die Leitung auf 0 und deswegen steht in PIND dann sowas
wie 0b11111110, wenn der Taster an D0 gedrückt wird. Also:
1
defineMYTASTER=0b01111111;// es sind nur 7 Taster, D7 ist frei
Lampion schrieb:> Ich hoffe, dass der Plan, den ich angehängt habe, der aktuellste ist
Hoffentlich nicht 😀.
Deine Entprell-Hardware wird so nichts bewirken.
R und C sind ja dauerhaft kurzgeschlossen. Du müsstest den R mit 1k auf
der anderen Seite des Tasters anschließen. Außerdem würde ich den R
wesentlich kleiner wählen, nämlich nur so groß, dass der Spitzenstrom
für den Taster nicht überschritten wird. Ohne den Taster zu kennen,
würde ich mal 100Ω vorschlagen ...
Ob man hier in SW eine perfekte Entprellroutine benötigt glaube ich
nicht. Ein einfaches kurzes Delay mit ein paar ms und dann erst den
Zustand des Ports lesen, sollte fast reichen. Zugegeben, blöd, das Delay
wäre in der ISR. Da aber der Rest der SW und der Aufgabe nicht bekannt
ist, kann das stören oder eben auch nicht.
Lampion schrieb:> Dies habe ich schon auf verschiedene Weisen getestet.> Sowohl ... als auch ...
Warum Herumprobieren, wenn Mitdenken auch eine Option ist?
Wenn der Taster nicht gedrückt ist, dann ist der Pin '1', wenn der
Taster gedrückt ist, dann ist er '0'.
Also musst du den Port einlesen, ihn invertieren (um aus der '0' eine
'1' zu machen) und mit dem einen Bit verUNDen, das dem gewünschten
Portpin entspricht: if((~PIND)&(1<<PD0))
Und weil der "~" Operator eine höhere Priorität hat als das "&", kann
man die Klammern drumrum auch weglassen: if(~PIND&(1<<PD0))
Die Klammern um den zweiten Ausdruck kann man aber nicht weglassen, weil
"<<" eine niedrigere Priorität als "&" hat.
Siehe:
https://de.wikibooks.org/wiki/C-Programmierung:_Liste_der_Operatoren_nach_Priorit%C3%A4t
Und mit ein wenig Nachdenken und dem Vergleich der Unterschiede zu
deinem
> if(~(PIND&(1<<PD0)))
kommst du jetzt selber auf den Fehler...
Lampion schrieb:> Die Taster sind natürlich an PINS angeschlossen, sollen aber über den> Interrupt aufgerufen werden.
Dein Programm verlässt sich darauf, dass die Hardware ok ist. Welchen
Pegel kannst du im Fehlerfall an diesen Pins messen? Ist da
tatsächlich nur 1 einziger Pin Low?
HildeK schrieb:> Ob man hier in SW eine perfekte Entprellroutine benötigt glaube ich> nicht.
Ganz sicher nicht, wenn, wie zu vermuten ist, die (hardwaremäßig
deutlich verbesserungswürdige) Konstruktion dazu dienen soll, aus dem
PowerDown aufzuwachen. Dann kann man die Aufwachzeit so fusen, dass sie
als Entprellzeit dienen kann.
Je nach Anwendung genügt das schon völlig, nämlich immer dann, wenn ein
Tastendruck immer nur eine kurze Aktion auslöst, nach der das Teil
gleich wieder im Tiefschlaf versinkt.
Nur dann, wenn längere Laufzeiten der Anwendung erforderlich sind und
währenddessen weiterhin Tasten abgefragt werden müssen, dann lohnt eine
klassische Entprellung per Timer zusätzlich dazu.
HildeK schrieb:> Hoffentlich nicht 😀.> Deine Entprell-Hardware wird so nichts bewirken.
Oh nein, tatsächlich ist die Version mittlerweile auch schon veraltet.
Die R und C sind nicht mehr kurzgeschlossen :)
Danke für eure Antworten, ich setze mich heute nochmal richtig ran und
versuche das Ganze zum Laufen zu bringen!
LG Lampion
Lampion schrieb:> if(~(PIND&(1<<PD0)))
Code hat keinen Effekt (always true).
Lampion schrieb:> if(PORTD |= (1<<PD0))
Code hat keinen Effekt (always true).
Und Ausgänge sind keine Eingänge.
Du solltest schon etwas überlegen und nicht Statements zufällig per
Gießkanne ausschütten.
Wenn Du nicht in C denken kannst (was offensichtlich ist), erstelle
erstmal einen Programmablaufplan. Der läßt sich dann viel besser in Code
umsetzen und prüfen.
Lampion schrieb:> Ich hoffe, dass der Plan, den ich angehängt habe, der aktuellste ist ^^'
Ist er sicher nicht, die gezeigte Entprellung ist noch ähm,
"verbesserungsfähig"
Am Ende hat man dann irgendwann seine Debouncer-Lib mit dynamisch
einladbaren ijmp-Tabellen und aktiver Zeitmessung, wie lange ein Taster
schon gedrückt gehalten wird. All das braucht man nämlich, wenn man
dynamisch Apps einladen will, die dann ein anderes Key-Mapping benötigen
und die auch die Funktion "erst langsam Wert ändern, dann schneller
werden" erfüllen können sollen.
c-hater schrieb:> HildeK schrieb:>>> Ob man hier in SW eine perfekte Entprellroutine benötigt glaube ich>> nicht.>> Ganz sicher nicht, wenn, wie zu vermuten ist, die (hardwaremäßig> deutlich verbesserungswürdige) Konstruktion dazu dienen soll, aus dem> PowerDown aufzuwachen. Dann kann man die Aufwachzeit so fusen, dass sie> als Entprellzeit dienen kann.
Ja, das meinte ich. Häufig ist durchaus: Taste drücken - Aktion
ausführen - wieder schlafen bis zum nächsten Tastendruck.
Da reicht eine Abfrage des Ports nach einer Schutzzeit, um evtl. einen
der Hardwareentprellung entgangenen Störpuls noch auszufiltern. Den
Ansatz mit den über Dioden veroderten Weckinterrupt mache ich auch
gelegentlich.
Da aber weder die Aufgabe noch die SW insgesamt bekannt ist, kann man
eben nur vermuten / glauben, dass eine einfache Entprellung reicht 😀.
Peter D. schrieb:> Lampion schrieb:>> if(~(PIND&(1<<PD0)))> Code hat keinen Effekt (always true).
Hinweis an den TO:
if (!(PIND&(1<<PD0)))
ist (fast) richtig, noch besser schreibt man jedoch
if (!(PIND&(1<<PIND0)))
Weil: PD0 und PIND0 müssten nicht zwangsweise den selben Wert bei allen
Prozessoren haben, auch wenn mir noch nichts gegenteiliges begegnet ist.
Man sollte deshalb PDx für die Ausgänge, PINDx für die Eingänge und
DDRDx für die Richtung verwenden.
> Lampion schrieb:>> if(PORTD |= (1<<PD0))>> Code hat keinen Effekt (always true).
Da ist deine sbit.h hervorragend geeignet, um übersichtlich Pins zu
lesen oder zu setzen.
Da muss man nicht mal in C denken können 😉.
LostInMusic schrieb:>>und aktiver Zeitmessung>> Bist Du ganz sicher, dass passive Zeitmessung hier nicht ausreichend> wäre?
Ja, da bin ich ganz sicher, denn mit passiver Zeitmessung kann sich der
µC in den deep sleep legen, und da laufen die Timer nicht mehr :p
Mit aktiver Zeitmessung ist gemeint, dass man dem µC über global states
mitteilt, dass er jetzt nicht in den power-down sleep gehen darf.
Glaub mir, dahingegend habe ich schon alles durchleben dürfen.
>denn mit passiver Zeitmessung kann sich der µC in den deep sleep legen, und>da laufen die Timer nicht mehr :p
Mhh, no comprendo... Also wenn gar kein Timer mehr läuft, kann der µC
auch keine Zeit mehr messen. Das wäre dann eine unmögliche Zeitmessung.
Da Du es aber nicht so nennst, sondern "passive Zeitmessung", scheint es
doch zu gehen. Aber wie denn?
>Mit aktiver Zeitmessung ist gemeint, dass man dem µC über global states>mitteilt, dass er jetzt nicht in den power-down sleep gehen darf.
Für mich bedeutet "Zeitmessung": Man inkrementiert (oder dekrementiert)
eine Speicherstelle ("Counter-Register") in einem festgelegten
Zeitintervall, liest dessen Wert zu zwei verschiedenen Zeitpunkten aus,
und bildet die Differenz.
Was Du beschreibst, ist eine banale Mehrfach-UND-Bedingung für das
Enablen bzw. Disablen des Sleep-Modus, wobei in der Bedingung globale
Variablen ausgewertet werden. Das ist doch keine Zeitmessung?
LostInMusic schrieb:> Für mich bedeutet "Zeitmessung": Man inkrementiert (oder dekrementiert)> eine Speicherstelle ("Counter-Register") in einem festgelegten> Zeitintervall, liest dessen Wert zu zwei verschiedenen Zeitpunkten aus,> und bildet die Differenz.
Ich werde mich nicht mit dir um Terminologien streiten. Hier
funktioniert die Zeitmessung gleich, wie du es beschreibst, aber ich
unterscheide mit aktiv/passiv die Eigenart, ob ich in den
Hauptprogrammfluss durch globale state changes eingreife oder nicht.
@Jan: OK. Ich fragte nur, weil mir die Attribute "aktiv" und "passiv" im
Zusammenhang mit Zeitmessung noch nie begegnet sind. Hätte sich ja was
Interessantes dahinter verbergen können. Aber nun ist es geklärt
(Privat-Sprachgebrauch von Dir). Danke.
HildeK schrieb:> PD0 und PIND0 müssten nicht zwangsweise den selben Wert bei allen> Prozessoren haben, auch wenn mir noch nichts gegenteiliges begegnet ist.
Egal wie viel Zeug ich mir reinziehe, ich kann mit keinen AVR
Mikrocontroller vorstellen, bei dem PD0 und PIND0 nicht den selben Wert
haben.
Wie bitteschön soll das möglich sein?
Stefan ⛄ F. schrieb:> Egal wie viel Zeug ich mir reinziehe, ich kann mit keinen AVR> Mikrocontroller vorstellen, bei dem PD0 und PIND0 nicht den selben Wert> haben.
Warum sind dann in allen Files getrennte Definitionen für PDx, PINDx und
DDRDx vorhanden. Lässt doch nur den Schluss zu, dass es anders sein
könnte.
> Wie bitteschön soll das möglich sein?
Ein Registerinhalt bedient die Steuersignale eines Ports. Wie die
verdrahtet sind ist letztlich frei. Wenn auch nur verwirrend, wenn man
es durcheinander würfeln würde.
Stefan ⛄ F. schrieb:> Eben, das würde kein normaler Mensch machen.
Es gibt leider nicht nur normale Menschen 😀.
Die Frage blieb aber offen:
HildeK schrieb:> Warum sind dann in allen Files getrennte Definitionen für PDx, PINDx und> DDRDx vorhanden?
Stefan ⛄ F. schrieb:> Egal wie viel Zeug ich mir reinziehe, ich kann mit keinen AVR> Mikrocontroller vorstellen, bei dem PD0 und PIND0 nicht den selben Wert> haben.>> Wie bitteschön soll das möglich sein?
Du Freak! Das ist bei JEDEM AVR8 sogar der Normalfall! Zumindest für
einen Takt. Und das ist in JEDEM AVR8-Datenblatt auch so dokumentiert.
c-hater schrieb:> Und das ist in JEDEM AVR8-Datenblatt auch so dokumentiert.
Dazu kommt natürlich noch das, was man mittels äusserer Beschaltung
bewirken kann. Insbesondere, wenn der Pin per DDR auf Input geschaltet
ist (ansonsten muss man natürlich, um "ungewöhnliches" zu bewirken,
typisch die Specs verletzen).
Aber einen hab' ich noch: Bei XMega und deren Erben wird der Pullup
nicht über das Portregister konfiguriert. Hier ergeben sich also
beliebige Abweichungen zwischen PORT und PIN, solange der der Pin als
Eingang konfiguriert ist.
HildeK schrieb:> Stefan ⛄ F. schrieb:>> Egal wie viel Zeug ich mir reinziehe, ich kann mit keinen AVR>> Mikrocontroller vorstellen, bei dem PD0 und PIND0 nicht den selben Wert>> haben.> Warum sind dann in allen Files getrennte Definitionen für PDx, PINDx und> DDRDx vorhanden. Lässt doch nur den Schluss zu, dass es anders sein> könnte.
Weil die Files automatisiert aus den Registerbeschreibungen erstellt
werden, und da haben alle Bits eindeutige Namen haben. Es ändert aber
nichts daran, daß PDn, PORTn, DDRn und PINDn für einen I/O-Pin
grundsätzlich immer den gleichen Wert haben.
Oliver
c-hater schrieb:> Dazu kommt natürlich noch das, was man mittels äusserer Beschaltung> bewirken kann. Insbesondere, wenn der Pin per DDR auf Input geschaltet> ist (ansonsten muss man natürlich, um "ungewöhnliches" zu bewirken,> typisch die Specs verletzen).
Hast du was missverstanden?
Es ging nur um die Tatsache, ob in den Headerfiles für die Port-, Pin-
und Richtungsdefinitionen immer die selbe Zahl zugeordnet ist, wie
z.B. hier in iotn861a.h für PINBx, DDBx und PORTBx, weil ich dem TO
empfahl, diese Bezeichnungen zu verwenden:
1
#define PINB0 0
2
#define PINB1 1
3
.
4
.
5
#define DDB0 0
6
#define DDB1 1
7
.
8
.
9
#define PORTB0 0
10
#define PORTB1 1
11
.
12
.
Ich habe nur daraus die Vermutung abgeleitet, dass es nicht immer so
sein muss.
Sonst würde eine generische Definition reichen, die man für alles
verwenden kann, also
Oliver S. schrieb:> Weil die Files automatisiert aus den Registerbeschreibungen erstellt> werden, und da haben alle Bits eindeutige Namen haben.
Zu spät gesehen.
Ja, das wäre eine brauchbare Erklärung!
Oliver S. schrieb:> Weil die Files automatisiert aus den Registerbeschreibungen erstellt> werden, und da haben alle Bits eindeutige Namen haben. Es ändert aber> nichts daran, daß PDn, PORTn, DDRn und PINDn für einen I/O-Pin> grundsätzlich immer den gleichen Wert haben.
Zumindest ist mir bisher kein gegenteiliger Fall bekannt. Und es ist
wohl auch tatsächlich davon auszugehen, dass es niemals dazu kommen
wird.
Aber eins ist trotzdem insofern korrekt: Es wäre möglich, ohne gegen die
Specs zu verstoßen. Atmel/MC garantierten zu keiner Zeit, das es
tatsächlich immer und unter allen Umständen so bleiben wird.
c-hater schrieb:> Zumindest ist mir bisher kein gegenteiliger Fall bekannt.
Ok, mir auch nicht (schrieb ich ja oben). Aber ich habe bisher auch nur
mit wenigen Typen gearbeitet.
c-hater schrieb:> Aber eins ist trotzdem insofern korrekt: Es wäre möglich, ohne gegen die> Specs zu verstoßen. Atmel/MC garantierten zu keiner Zeit, das es> tatsächlich immer und unter allen Umständen so bleiben wird.
Daher war meine Empfehlung an den TO durchaus berechtigt. Es vermeidet
vordergründige Verwirrungen, die es z.B. hier geben könnte:
c-hater schrieb:> Aber eins ist trotzdem insofern korrekt: Es wäre möglich, ohne gegen die> Specs zu verstoßen. Atmel/MC garantierten zu keiner Zeit, das es> tatsächlich immer und unter allen Umständen so bleiben wird.
Das stimmt zwar, aber solange auf dem Chip AVR draufsteht, wird das so
bleiben. Die Grundstruktur der Registeransteuerung mit den drei
Registern dürfte „ikonisch“ für die Prozessorfamilie sein.
Oliver
c-hater schrieb:> Du Freak!
Sage mal hast du noch Tassen im Schrank, mich so anzugehen?
HildeK schrieb:> PD0 und PIND0 müssten nicht zwangsweise den selben Wert bei allen> Prozessoren habenStefan ⛄ F. schrieb:> ich kann mir keinen AVR Mikrocontroller vorstellen,> bei dem PD0 und PIND0 nicht den selben Wert haben.> Wie bitteschön soll das möglich sein?c-hater schrieb:> Du Freak! Das ist bei JEDEM AVR8 sogar der Normalfall!
Nein c-hater, da liegst du mal wieder völlig falsch. Offenbar steckt da
wieder dein Trieb hinter, mich als Idioten hinzustellen.
PIND0 und PD0 sind beides definierte Konstanten mit dem Wert 0. Sieh
selbst in der Datei iom328p.h sowie portpins.h nach!
> Zumindest für einen Takt.
Mit Takten hat das nichts zu tun. Es sind Konstanten.
Nachtrag: Ich habe die Datei für den ATmega16 auch angehängt, damit du
dich vergewissern kannst das das auch bei dem nicht anders ist. Wenn du
willst kannst du dir den avr-gcc installieren und sämtliche *.h Dateien
durchsuchen. Du wirst keinen Fall finden, wo der Wert nicht 0 ist.
Ich empfehle dir, dich aus Threads bezüglich C/C++ (also fast alle)
heraus zu halten. Dann haben wir unsere Ruhe und für dich wird es nicht
immer wieder so peinlich. In letzter Zeit ist es ja extrem geworden mit
dir.
Stefan ⛄ F. schrieb:> PIND0 und PD0 sind beides definierte Konstanten mit dem Wert 0.
Jetzt macht ihr mich aber auch ganz jeck und das liegt hoffentlich nicht
am Karnevalsvirus, der gerade ausbricht :-) Sind also 2 Konstante mit 2
Namen, die aber dasselbe Bit in der Realität beschreiben?! Wenn das so
ist, dann könnte ich also auch PIND0 mit dem Wert 0 und PD0 mit dem Wert
1 belegen? Und was passiert dann in der Realität? Gilt dann der Wert,
der zuletzt kommt oder wie oder steigt der Kompiler einfach mit einer
Fehlermeldung aus?
Ich glaube, ich brauche jetzt ein Bier! Gruß Rainer
Rainer V. schrieb:> Sind also 2 Konstante mit 2 Namen, die aber dasselbe Bit in der Realität> beschreiben?!
Es sind defines, Textersetzungen, sie beschreiben kein Bit.
> Wenn das so ist, dann könnte ich also auch PIND0 mit dem> Wert 0 und PD0 mit dem Wert 1 belegen?
Ja, könnte man ohne einen Konflikt mit dem Compiler. Dem ist es egal, ob
du eine Zuweisung mit 0 oder 1 machst. Nur deinem Programm ist es meist
nicht egal.
Wie es wahrscheinlich ist, sind PORTnx=PINnx=DDnx=Pnx ein Ersatz für die
Zahl 0. Solange das sichergestellt ist, bräuchte man eigentlich nur die
defines von Pnx.
Der Chip innen könnte jedoch auch so aufgebaut sein, dass PORTnx,
PINnx und DDnx je ein anderen Wert haben müssen, um den gewünschten
Hardwarepin richtig anzusprechen.
Leider habe ich die ganze Diskussion dadurch angestoßen, weil ich
empfahl, für PORTn die mit PORTnx definierten Werte, für PINn die mit
PINnx und für DDRn die mit DDNx zu nehmen. Sollte oben genanntes
vorkommen, ist es von Vorteil, wenn man sich angewöhnt hat, die drei
defines passend zu den Registern PORTn, PINn und DDRn zu verwenden.
(n steht für A, B, C...; x für 0...7)
HildeK schrieb:> Der Chip innen könnte jedoch auch so aufgebaut sein, dass PORTnx,> PINnx und DDnx je ein anderen Wert haben müssen, um den gewünschten> Hardwarepin richtig anzusprechen.
Ok, danke, ja, du hast die Verwirrung angestossen...
Rainer
Rainer V. schrieb:> Jetzt macht ihr mich aber auch ganz jeck und das liegt hoffentlich nicht> am Karnevalsvirus, der gerade ausbricht :-) Sind also 2 Konstante mit 2> Namen, die aber dasselbe Bit in der Realität beschreiben?!
Nein. Weder noch, egal, was du auch immer gemeint hast.
Das sind alles defines, und die Namen kommen aus dem Datenblatt. PD0 ist
der Name des I/O-Pins, und PORTD0, DDRD0 und PIND0 sind die Bitnamen in
den entsprechenden Registern, die diesen I/O-Pin kontrollieren.
Den Rest kannst du dir jetzt hoffentlich trotz Karneval selber erklären.
Oliver
Es ist auch bei anderen MC-Serien gängig, daß es mehrere Symbole mit dem
gleichen Wert gibt.
Die Gründe sind vielfältig. Z.B. daß man sich nicht gleich auf eine
Schreibweise einigen konnte. Oder daß ein neuer die Abteilung übernommen
hat und meinte, seine Duftmarke hinterlassen zu müssen.
Manchmal kriegen dann ältere Symbole den Kommentar "deprecated".
Nervig ist es auch, wenn die gleichen Symbole bei verschiedenen
Derivaten anders heißen. Z.B. bei der AVR-UART ist das besonders kraß
und bei den Interruptvektoren. Wechselt man das Derivat, kriegt man
unnötig Fehlermeldungen und Warnungen. Ignoriert man die Warnungen,
werden die Interrupts einfach nicht mehr ausgeführt.
Rainer V. schrieb:> Sind also 2 Konstante mit 2> Namen, die aber dasselbe Bit in der Realität beschreiben?
Schau in die Header Dateien, dann siehst du dass es sogar mehr als 2
sind.
Rainer V. schrieb:> dann könnte ich also auch PIND0 mit dem Wert 0 und PD0 mit dem Wert> 1 belegen?
Nein. PIND0 ist eine Konstante definition, die kannst du mit nichts
"belegen". Wenn schon, schreibst du Werte in die Register PORTD oder
DDRD.
Wenn du das PIND Register beschreibst, passiert je nach AVR Modell gar
nicht oder du löst damit die Spezialfunktion "toggle pin" aus.
Es ist möglich, konstante Definitionen für den darunter folgenden Code
zu überschreiben, z.B. durch
#define PD0 3.14159
Aber wer so etwas tut, der gehört geteert und gefedert.
Stefan ⛄ F. schrieb:> Es ist möglich, konstante Definitionen für den darunter folgenden Code> zu überschreiben, z.B. durch>> #define PD0 3.14159
Das gibt aber ne Warnung.
Wennschon, dann aber:
Lampion schrieb:> Ich habe insgesamt sieben Taster an meinem INT0 angeschlossen. Je> nachdem welcher gedrückt wird, soll etwas anderes passieren
(Prellende) Taster kommen nie an Interrupteingänge.
Programmiere deinen ATmega16 so, dass er alle 10ms aufwacht und die 8
Taster die jeweils an 8 eigenen Eingängen (mit pull up) angeschlossen
sind, eingelesen und ausgewertet werden.
Fertig, und fertig entprellt.
Stefan ⛄ F. schrieb:> Schau in die Header Dateien, dann siehst du dass es sogar mehr als 2> sind.
Ja, danke...ich wollte jetzt auch nicht groß stören...und ich bin kein
"Header Dateien" sprich Hochsprachentyp :-)
Gruß Rainer
>(Prellende) Taster kommen nie an Interrupteingänge.
Warum? Wenn man den Interrupt überhaupt nicht enabled, außer zu dem
Zweck (und nur dazu), dass der Taster den Controller so aus dem
Power-Down-Sleepmode aufwecken kann, den Taster ansonsten aber pollt, wo
soll dann das Problem sein?
Rainer V. schrieb:> ich bin kein "Header Dateien" sprich Hochsprachentyp
Das verstehe ich nicht. Auch in Assembler benutzt man üblicherweise
definitionen (*def.inc Dateien) für Register und Bits. Du nicht?
MaWin schrieb:> (Prellende) Taster kommen nie an Interrupteingänge.
Also, meine Super-Fernbedienung macht das auch, wenn auch mit Pinchange
IRQ:
Beitrag "Re: Quick&dirty - schnelle Problemlösungen selbst gebaut"
Sobald der MC erweckt ist, scannt er die Tasten ohne ISR, sendet, was er
findet und legt sich wieder schlafen. Das funktioniert nun schon seit
mehr als 4 Jahren - ohne Fehlauslösung und ohne den Akku zu laden.
Musste sie nur einmal neu programmieren, weil ich den SAT Empfänger
gewechselt habe.
LostInMusic schrieb:>> (Prellende) Taster kommen nie an Interrupteingänge.>> Warumhttp://www.ganssle.com/debouncing.htm
Weil Flankenwechsel bei prellenden Tastern sehr kurz nacheinander
kommen, teils in weniger als Mikrosekunden Abstand, und damit der
nächste Interrupt schon kommt, bevor der vorherige abgearbeitet wurde.
Je nach Programmierung und uC-Hardware geht der Impuls verloren,
blockiert der Impuls die Eingangsschaltung weil er gesetzt aber nicht
mehr rückgesetzt wird, löst er direkt nach der Abarbeitung des
vorherigen Impulses den nächsten Interrupt aus so dass das Hauptprogramm
in der Prellzeit gar nicht mehr dran kommt oder führt Interrupt in
Interrupt zum Stacküberlauf mit crash des uC.
MaWin schrieb:> Weil Flankenwechsel bei prellenden Tastern sehr kurz nacheinander> kommen, teils in weniger als Mikrosekunden Abstand, und damit der> nächste Interrupt schon kommt, bevor der vorherige abgearbeitet wurde.
Natürlich sperrt die ISR sich selber, sobald sie aufgerufen wurde, das
sollte aber sowieso klar sein. Es geht ja nur um den Flankenwechsel zum
Erwecken.
@MaWin: Genau so, wie Matthias es sagt: Man disabled den Interrupt
unmittelbar nach dem Aufwecken, indem man den entsprechenden Code in
seine eigene ISR schreibt. Dann bleibt es bei dieser einen Triggerung
und die von Dir angesprochenen Probleme tauchen nirgendwo auf. Man muss
natürlich alles penibel berücksichtigen (Control-Bits, Flags, Timer auf
Null setzen, irgendwelche FSMs resetten etc.), aber dann funktioniert
das einwandfrei.
Einem Taster die Fähigkeit zu verleihen, den Controller aus dem
Power-Down rauszuholen, ist schließlich einer der Einsatzzwecke des
externen Interrupts überhaupt. Für Fernbedienungen, wo das alle und
viele Tasten können müssen, hat man dann den PCINT erfunden, um nicht zu
jedem Taster noch eine Diode auf die Platine löten zu müssen.