PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Attiny13 mit Pinchange Interrupt boolvariable setzen



ExXeQtor
10.10.2010, 20:15
hallo forenuser,
folgendes problem dürfte für viele hier schnell durchschaut sein, ich finde den fehler nicht:

ich möchte durch einen pinchange interrupt eine boolvariable verändern, damit in meiner main-schleife je nach zustand der variablen in eine andere schleife gegangen wird.
Im Beispiel:
einmaliger Tastendruck -> variable = true -> in der mainschleife der if-zweig, der die led schneller blinken lässt.
erneuter tastedruck -> variable = false -> anderer (langsamer blinkender) zweig in der mainschleife.
bei erneutem druck wieder von vorne, usw usf.



#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#define F_CPU 9.6E6
#include <util/delay.h>


volatile bool onoff;

ISR(PCINT0_vect)
{
if (onoff)
{
onoff = false;

PORTB = 0b00000000; // LED OFF
_delay_ms(200);
}

if (!onoff)
{
onoff = true;

PORTB = 0b00000010; // LED ON
_delay_ms(200);
}
}

int main(void)
{

DDRB = 0b00000010;
PORTB = 0b00000000;

GIMSK |= (1<<PCIE);
PCMSK |= (1<<PCINT0); // TASTER auf PB0
sei();

while (1)
{
if (onoff)
{
for (int i=0; i<5; i++)
{
PORTB = 0b00000000; // LED OFF
_delay_ms(50);
PORTB = 0b00000010; // LED ON
_delay_ms(50);
}
}
else if (!onoff)
{
for (int i=0; i<5; i++)
{
PORTB = 0b00000000; // LED OFF
_delay_ms(200);
PORTB = 0b00000010; // LED ON
_delay_ms(200);
}
}
else
PORTB = 0b00000000; // LED OFF
}

return 0;
}


nun verhält sich mein controller mit dem folgenden code aber so, als würde der wert der variablen ständig derselbe bleiben. Kann mir da jemand helfen?

Slein
10.10.2010, 21:47
Mahlzeit!

Die Variable sollte sich schon ändern mit deinem code (wenn ich nichts übersehen hab...).
Probier doch mal so: halt den Taster mal unten und beobachte.

Pin *change* interrupt meint genau das was der Name sagt. Ein Int beim Übergang von high auf low und ein Int beim Übergang von low auf high. Wenn du jetzt auf den Taster drückst und loslässt hattest du 2 Ints und damit ist dein Bool wieder da wo es vorher war.

Dein Taster ist richtig angeschlossen?

ExXeQtor
10.10.2010, 22:01
...Wenn du jetzt auf den Taster drückst und loslässt hattest du 2 Ints und damit ist dein Bool wieder da wo es vorher war.

Dein Taster ist richtig angeschlossen?

hi! klingt logisch... ja der taster sollte richtig angeschlossen sein (druck gibt mir ein high am eingang) und ist mit einem 33k wiederstand und 0,33µF entprellt.

da ich auf dem gebiet sehr neu bin: wie könnte ich das verhindern? ich erinnere mich gelesen zu haben, dass man die flanke auswählen kann, die das interrupt auslöst (?)...
oder anders: wie könnte man mein problem anders lösen? externer (tastergesteuerter) interrupt, der eine boolvariable bei einmaligem drücken setzt um damit (was mein ziel ist) den µC in den sleep mode zu schicken bzw beim nächsten mal wieder aufzuwecken...

grüße

Slein
10.10.2010, 22:38
Du könntest z.B sowas in die int routine mit einbauen:

if (PINB & 0x01) {
....
}

Dann würdest du die .... nur ausführen, wenn sich am ausgesuchten (PCMSK) Pin was ändert und der Pin auf high ist. 0x01 für PB0, im Zweifel bei Wikipedia mal nach 'und' suchen.

Aber aufpassen, wenn du mehrere Pins an portb für Taster benutzt wirds Probleme geben wenn du mehrere Taster gleichzeitig drückst. Da müsste man sich dann die letzten Zustände merken.

Die Flanke/Level kann man afaik nicht bei pin change interrupts einstellen, dafür gibts dann Int0, Int1 usw. Ob der Tiny13 sowas hat musst du im Datenblatt nachsehen.

markusj
10.10.2010, 23:37
Die direkte Tasterauswertung in einer ISR ist eine eher schlechte Idee, lies dir Mal etwas Wissen zum Thema Entprellung an.

Linktipps: RN-Wissen (http://www.rn-wissen.de/index.php/Taster-Abfrage_in_C) und µC.net Wiki (http://www.mikrocontroller.net/articles/Entprellung)

mfG
Markus

ExXeQtor
11.10.2010, 00:54
hallo markus,
du meinst die hardwareentprellung, die ich oben erwähnt habe, ist ungeeignet?

oberallgeier
11.10.2010, 09:38
... Pin *change* interrupt meint genau das was der Name sagt. Ein Int beim Übergang von high auf low und ein Int beim Übergang von low auf high. Wenn du jetzt auf den Taster drückst und loslässt hattest du 2 Ints und damit ist dein Bool wieder da wo es vorher war ...Klar - die hübsche PCI-Funktion hat diesen Effekt. Leider bin ich im Programmieren nicht so erfahren, kann keine guten Ratschläge geben. Aber mein PCI-Code läuft prächtig.

Dabei gehts um eine ähnliche Sache wie bei ExXeQtor. Der µC wird in den sleep geschickt, (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=521530#521530) und soll bei Tastendruck aufwachen. Deshalb habe ich eine ziemlich kurze PCI-ISR: der vollständige Code in der Routine ist ein return. Damit kann ich z.B. den Aufruf im main :
schlaf_PI4 ();
in eine while-Schleife legen, die mir in Art eines Menues - je nach gedrücktem Pin - nach der Rückkehr aus dem SparSchlaf oder auch ohne diesen durch einen oder beliebig viele Tastendrücke auch auf verschiedene Tasten das erledigt, was ich will. Wieso "... nach beliebig vielen Tastendrücken ..."? Weil die ISR nur ein popeliges "return" ist - also im Programm selbst garnicht stört. Der einzige Zweck, der dabei erreicht wird, ist es, den µC mit einem Tastendruck aus dem Sleep zu holen >>wenn er da drin ist<<. Und ich kann >>irgendwann<< - wenn es mir beliebt - den µC wieder in den Sleep schicken. Sogar durch einen Druck auf die gleiche Taste (Anregung: if Taste gedrückt? dann prüfen Taste lose? wenn ja schlaf_PI4 (); - else zum ersten if: etwas ohne Tastendruck).

@ExXeQtor - vielleicht überlegst Du Dir diese Vorgehensweise? Obwohl ich nicht weiß, ob das ein gutes Verfahren ist. Aber es läuft in meinem pacer seit "Ewigkeiten" problemlos.

markusj
11.10.2010, 12:19
hallo markus,
du meinst die hardwareentprellung, die ich oben erwähnt habe, ist ungeeignet?

Das ist keine Hardwareentprellung, es ist überhaupt keine Entprellung.
Noch während du in der ISR bist kann durch das Prellen der PCINT-Flag erneut gesetzt werden -> Nach verlassen der ISR wird diese gleich wieder ausgelöst.

Und sleep() in einer ISR ist eine sehr schlechte Idee ...

mfG
Markus

oberallgeier
11.10.2010, 13:42
... Und sleep() in einer ISR ...Wo taucht die denn auf? Hab ich da etwas übersehen?

ExXeQtor
11.10.2010, 13:43
Das ist keine Hardwareentprellung, es ist überhaupt keine Entprellung.
Noch während du in der ISR bist kann durch das Prellen [...]


prellen tut der aufbau soweit nicht (merkbar)... insofern würde ich die hardwareentprellung schon eine nennen...



Und sleep() in einer ISR ist eine sehr schlechte Idee ...


die sleep sollte nicht in die ISR, ich wollte in der ISR ja nur ein(ige) bool(s) setzen, die in meiner mainschleife dann bestimmen, ob sleep oder nicht...

markusj
11.10.2010, 14:10
Pardon oberallgeier, ersetze sleep() durch _delay_ms



ISR(PCINT0_vect)
{
if (onoff)
{
_delay_ms(200); // hier
}

if (!onoff)
{
_delay_ms(200); // und heir
}
}
(Für den Hinweis unnötiger Code wurde von mir gelöscht)

@ExXeQtor:
Das ist keine Hardware-Entprellung - Oder hast du irgendwelche Hardware zwischen Taster und Pin geschaltet, die die Entprellung übernimmt? Dann hast du nichts davon geschrieben ... Und nein, das oben ist KEINE Hardware-Entprellung.


prellen tut der aufbau soweit nicht (merkbar)
Nein, er tut nur nicht was er soll ... Also alles bestens?

Wie wäre es wenn du jetzt Mal Nägel mit Köpfen machst, dir das notwendige Wissen anliest und aufhörst irgendwelche sonderbare Konstrukte mit dem PCINT zu schrauben ohne dessen "Seiteneffekte" zu beachten.

mfG
Markus

ExXeQtor
12.10.2010, 08:22
Nein, er tut nur nicht was er soll ... Also alles bestens?


Stimmt, allerdings lag das (zumindest unter anderem) an dem Effekt, den Slein im 2. Post in diesem thread bemerkt hat - berücksichtigt man das, wird die ISR zumindest aufgerufen und das nur EINMAL (wo wir bei entprellen sind, weshalb ich davon ausging der parallele widerstand und kondensator zu ground seien "hardwareentprellung" - vielleicht ist das ja der falsche begriff - wie nennt man es?)



Wie wäre es wenn du jetzt Mal Nägel mit Köpfen machst, dir das notwendige Wissen anliest und aufhörst irgendwelche sonderbare Konstrukte mit dem PCINT zu schrauben ohne dessen "Seiteneffekte" zu beachten.


Ich bin dabei, auch deshalb bin ich in diesem forum! ;)
"Anlesen" ist immer gut gesagt, wenn man mit einem Gebiet anfängt - da gehört zum verständnis schon auch praxis dazu.

Grüße

markusj
12.10.2010, 15:01
(wo wir bei entprellen sind, weshalb ich davon ausging der parallele widerstand und kondensator zu ground seien "hardwareentprellung" - vielleicht ist das ja der falsche begriff - wie nennt man es?)

DAS ist Hardwareentprellung, wie effektiv sie ist ist eine andere Frage. (Ebenso die Tatsache, dass du erst nach elf Antworten von diesem Aufbau geschrieben hast.)

Ich habe weiter oben nicht umsonst die beiden Wiki-Einträge verlinkt, dort steht alles drin was du zum Thema Entprellung wissen musst.

Kurzzusammenfassung: Die zuverlässigeren Routinen basieren typischerweise darauf dass sie die Eingänge mit einer gewissen Frequenz abtasten dann anhand mehrerer zurückliegender Werte stabile Zustände erkennen.

mfG
Markus

ExXeQtor
12.10.2010, 15:25
Ich zitiere mich mal selber (es war exakt der dritte post) ;)



...Wenn du jetzt auf den Taster drückst und loslässt hattest du 2 Ints und damit ist dein Bool wieder da wo es vorher war.

Dein Taster ist richtig angeschlossen?

hi! klingt logisch... ja der taster sollte richtig angeschlossen sein (druck gibt mir ein high am eingang) und ist mit einem 33k wiederstand und 0,33µF entprellt. [...]

genug davon, danke für die hilfe. eventuell löse ich das ganze jetzt doch mechanisch.

markusj
12.10.2010, 17:01
Ouch, Treffer versenkt. Sorry, den Satz hatte ich überlesen.
Dann ziehe ich meine Aussage zurück und behaupte das Gegenteil ;)

mfG
Markus

PS: Wie willst du Entprellung mechanisch lösen? Das Phänomen wird doch durch die mechanische Realität verursacht ...

ExXeQtor
12.10.2010, 19:20
ich werde wohl die gesamte schaltung mit einem miniaturschalter von der batterie trennen anstatt den µC per interrupt in und aus dem sleep zu holen... die entscheidung dazu war eine platzfrage aber ich habe VIELLEICHT gestern ein Gehäuse gefunden, das nur unwesentlich größer ist und schon einen mikro on off schalter integriert hat...