Forum: Mikrocontroller und Digitale Elektronik ATMega16 mehrere Taster an INT0


von Lampion (Gast)


Lesenswert?

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 :)

von Oliver S. (oliverso)


Lesenswert?

Lampion schrieb:
> Die Taster sind mit Dioden angeschlossen und mechanisch entprellt.

Zeig mal einen Schaltplan.

Oliver

von Sebastian R. (sebastian_r569)


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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?

: Bearbeitet durch Moderator
von LostInMusic (Gast)


Lesenswert?

>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.

von Lampion (Gast)


Angehängte Dateien:

Lesenswert?

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 ^^'

von Oliver S. (oliverso)


Lesenswert?

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

von Spess53 (Gast)


Lesenswert?

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

von Ingo Less (Gast)


Lesenswert?

Taster fragt man zyklisch in nem Timerinterrupt ab (polling) und 
entprellt sie auch gleich dort in Software...

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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
define MYTASTER = 0b01111111; // es sind nur 7 Taster, D7 ist frei
2
// Taste 0 gedrückt 
3
if ((PIND & MYTASTER) == ((~(1 << D0)) & MYTASTER) 
4
    {
5
    // mache Taste 0
6
    }
Allerdings solltest du dir auf jeden Fall mal die Timermethode 
anschauen:
https://www.mikrocontroller.net/articles/Entprellung

von HildeK (Gast)


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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?

: Bearbeitet durch Moderator
von c-hater (Gast)


Lesenswert?

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.

von Lampion (Gast)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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.

: Bearbeitet durch User
von Äxel (Gast)


Lesenswert?

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"

von Jan (Gast)


Lesenswert?

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.

von LostInMusic (Gast)


Lesenswert?

>und aktiver Zeitmessung

Bist Du ganz sicher, dass passive Zeitmessung hier nicht ausreichend 
wäre?

von EAF (Gast)


Lesenswert?

HildeK schrieb:
> Hoffentlich nicht 😀.
> Deine Entprell-Hardware wird so nichts bewirken.
> R und C sind ja dauerhaft kurzgeschlossen.

Das ist die sogenannte Borg-Schaltung.
https://robotfreak.de/elab-wiki/index.php?title=Datei:Widerstand-ist-zwecklos.jpg
(Gilt natürlich auch in der Kombination mit Kondensator)

von HildeK (Gast)


Lesenswert?

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 😉.

von Mario M. (thelonging)


Lesenswert?

Lampion schrieb:
> Ich habe insgesamt sieben Taster an meinem INT0 angeschlossen.

Nimm Pedas Code, spare 21 Bauteile und Gewinne neben einer sicheren 
Entprellung den Komfort einer Flankenerkennung.

https://www.mikrocontroller.net/articles/Entprellung#Timer-Verfahren_.28nach_Peter_Dannegger.29

von Jan (Gast)


Lesenswert?

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.

von LostInMusic (Gast)


Lesenswert?

>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?

von Jan (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

Hier mal eine Version Entprellen mit Sleep:

Beitrag "AVR Sleep Mode / Knight Rider"

von LostInMusic (Gast)


Lesenswert?

@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.

von Stefan F. (Gast)


Lesenswert?

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?

von HildeK (Gast)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

HildeK schrieb:
> Wenn auch nur verwirrend, wenn man
> es durcheinander würfeln würde.

Eben, das würde kein normaler Mensch machen.

von HildeK (Gast)


Lesenswert?

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?

von c-hater (Gast)


Lesenswert?

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.

von c-hater (Gast)


Lesenswert?

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.

von Oliver S. (oliverso)


Lesenswert?

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

von HildeK (Gast)


Lesenswert?

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
1
#define    PB7       7
2
#define    PB6       6
3
.
4
.
Das existiert ja auch.

von HildeK (Gast)


Lesenswert?

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!

von c-hater (Gast)


Lesenswert?

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.

von HildeK (Gast)


Lesenswert?

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:
1
 PORTB |= (1<<DDB0);
das ja trotzdem den Pin PortB0 setzt.

von Oliver S. (oliverso)


Lesenswert?

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

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

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 haben

Stefan ⛄ 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.

von Rainer V. (a_zip)


Lesenswert?

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

von HildeK (Gast)


Lesenswert?

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)

von Rainer V. (a_zip)


Lesenswert?

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

von Oliver S. (oliverso)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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:
1
#undef PD0
2
#define PD0 3.14159

von Stefan F. (Gast)


Lesenswert?

Peter D. schrieb:
> Wennschon, dann aber:
> #undef PD0
> #define PD0 3.14159

Würde ich nicht machen, denn damit unterdrückt man die wertvolle 
Warnung.

von MaWin (Gast)


Lesenswert?

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.

von Rainer V. (a_zip)


Lesenswert?

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

von LostInMusic (Gast)


Lesenswert?

>(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?

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

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?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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.

: Bearbeitet durch User
von MaWin (Gast)


Lesenswert?

LostInMusic schrieb:
>> (Prellende) Taster kommen nie an Interrupteingänge.
>
> Warum

http://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.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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.

von LostInMusic (Gast)


Lesenswert?

@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.

von Rainer V. (a_zip)


Lesenswert?

Stefan ⛄ F. schrieb:
> Das verstehe ich nicht

 muß du auch nicht...hatte einen "schwachen" Augenblick und möchte nicht 
mehr dran denken :-)
Gruß Rainer

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
Noch kein Account? Hier anmelden.