Moin, ich habe das problem, das mein atmega bei einem interruptz den pin
kurz high schaltet und danach auch wieder sofort low. also quasi geht er
beide schritte durch, obwohl ich dort ne if unterscheidung mache, auch
mit einer switch case anweisung klappt es nicht.
wisst ihr weiter?
Hallo,
Du musst festlegen ob der Interrupt bei einer fallenden oder steigenden
Flanke ausgelöst wird.
Des Weiteren sollte man keine Wartezeit in der Interrupt-Routine machen.
Wo wird eigentlich die Variable state gesetzt.
Hi,
"int state" muss "volatile" sein.
Ansonsten solltest du ein Flag setzten, und die Arbeit im
"Hauptprogramm" machen.
Den Interrupt brauchst du auch nicht ausschalten, die sind in einem
Interrupt-Aufruf automatisch gesperrt.
Marcus P. schrieb:> Hi,> "int state" muss "volatile" sein.
habe ich getestet, ohne veränderungen
> Ansonsten solltest du ein Flag setzten, und die Arbeit im> "Hauptprogramm" machen.
hm, das wäre mir nun neu, wie kann ich das machen?
> Den Interrupt brauchst du auch nicht ausschalten, die sind in einem> Interrupt-Aufruf automatisch gesperrt.
ok, da war ich mir nicht sicher, ich hatte in meinen anfängen, als ich
in "arduino " programmiert habe immer das problem, das er, weil der
taster nicht hardware seitig entprellt war, ständig neu in den isr
gegangen ist und dabei irgendwann abgeschmiert ist.
anbei mal meinen test code:
1
#define F_CPU 16000000UL // 16 MHz
2
3
#include<avr/io.h>
4
#include<avr/interrupt.h>
5
#include<util/delay.h>
6
7
volatileintstate;
8
9
intmain(void)
10
{
11
//state = 0;
12
DDRD&=~(1<<DDD2);// Clear the PD2 pin
13
// PD2 (PCINT0 pin) is now an input
14
15
PORTD|=(1<<PORTD2);// turn On the Pull-up
16
// PD2 is now an input with pull-up enabled
17
18
DDRB&=~((1<<DDB0)|(1<<DDB2));
19
20
21
EICRA|=(1<<ISC00);// set INT0 to trigger on ANY logic change
test schrieb:> Was hängt an dem Pin für "INT0", ein Taster? Wenn ja, vielleicht> prellt> Der und der Interrupt wird mehrmals hintereinander ausgeführt.
arbeite mit einem dev board, welches eigentlich mal für pic controller
war. wegen dem nachprellen, hatte ich ja an das delay gedacht, aber auch
wenn ich quasi eine 5V leitung nehme und ganz kurz an den pin halte,
habe ich das problem.
Eine Taste an INT0 ist nicht gut, da das Prellen immer mehrere ISR
auslöst.
Da du auch noch auf ANY logic change gestellt hast, wird eine ISR beim
drücken und eine beim loslassen der Taste ausgeführt. Abschalten nützt
nichts da die letzte Anforderung gespeichert wird auch wenn die ISR
gesperrt ist.
Also eine Taste am Besten pollen, oder auf rising edge stellen.
K.M. Henkler schrieb:> aber auch wenn ich quasi eine 5V leitung nehme und ganz kurz an den pin> halte, habe ich das problem.
Auch die prellt. Dein Delay ist keine adäquate Entprellung. Der
Interrupt wird durch das Prellen nochmal ausgelöst und das
Interrupt-Flag gesetzt. Sobald deine ISR fertig ausgeführt ist, wird sie
gleich wieder ausgeführt.
Mach die Entprellung richtig, dann funktioniert das auch.
K.M. Henkler schrieb:>> Ansonsten solltest du ein Flag setzten, und die Arbeit im>> "Hauptprogramm" machen.>> hm, das wäre mir nun neu, wie kann ich das machen?
ISRs sollten immer möglichst schnell abgearbeitet sein, weil während
ihrer Laufzeit der Prozessor blockiert ist und nichts anderes tun kann.
Aber gerade die Vermeidung von solchen Blockaden ist die Idee hinter dem
Konzept von Interrupts. Deshalb sind Delays in der ISR ein no-go. Bei so
einem kleinen Programm mag das noch nicht so wichtig sein, aber besser
gar nicht erst angewöhnen, denn das führt nur zu Problemen.
Dieter F. schrieb:> Das sieht mir nach einem ATMega16 oder ATMega32 aus - oder?>> Müsstest Du dann nicht mit MCUCR und GICR arbeiten (und nicht mit EICRA> und EIMSK)?
ne ist der 328P
Hubert G. schrieb:> Eine Taste an INT0 ist nicht gut, da das Prellen immer mehrere ISR> auslöst.> Da du auch noch auf ANY logic change gestellt hast, wird eine ISR beim> drücken und eine beim loslassen der Taste ausgeführt. Abschalten nützt> nichts da die letzte Anforderung gespeichert wird auch wenn die ISR> gesperrt ist.> Also eine Taste am Besten pollen, oder auf rising edge stellen.
jo stimmt, jetzt hat es "klick" gemacht, ja klar so hat er ja immer 2
veränderungen, ohmann ;)
Rolf M. schrieb:> K.M. Henkler schrieb:>> aber auch wenn ich quasi eine 5V leitung nehme und ganz kurz an den pin>> halte, habe ich das problem.>> Auch die prellt. Dein Delay ist keine adäquate Entprellung. Der> Interrupt wird durch das Prellen nochmal ausgelöst und das> Interrupt-Flag gesetzt. Sobald deine ISR fertig ausgeführt ist, wird sie> gleich wieder ausgeführt.> Mach die Entprellung richtig, dann funktioniert das auch.>> K.M. Henkler schrieb:>>> Ansonsten solltest du ein Flag setzten, und die Arbeit im>>> "Hauptprogramm" machen.>>>> hm, das wäre mir nun neu, wie kann ich das machen?>> ISRs sollten immer möglichst schnell abgearbeitet sein, weil während> ihrer Laufzeit der Prozessor blockiert ist und nichts anderes tun kann.> Aber gerade die Vermeidung von solchen Blockaden ist die Idee hinter dem> Konzept von Interrupts. Deshalb sind Delays in der ISR ein no-go. Bei so> einem kleinen Programm mag das noch nicht so wichtig sein, aber besser> gar nicht erst angewöhnen, denn das führt nur zu Problemen.
ja ich werde das delay wieder raus nehmen, war ja nur ein test, ob sich
so was ändert. das eigentliche programm ist auch länger, nur ich habe
bisher nie was mit interruppts gemacht und hab gedacht, ich schreibe
besser erstmal nen test programm. auf polling wollte ich verzichten.
deswegen möchte ich ja interrupts benutzen.
Wollte nochmal Fragen, wie das mit dem Flag gemeint ist. Soll ich quasi
nur die variable ändern und das pin umschalten zb. dann unter main()
machen?
K.M. Henkler schrieb:> Wollte nochmal Fragen, wie das mit dem Flag gemeint ist. Soll ich quasi> nur die variable ändern und das pin umschalten zb. dann unter main()> machen?
Genau so macht man das. Das Problem mit Tastenprellen wirst du aber so
nur schwer in den Griff bekommen. Du musst dir im main erst wieder eine
Abfrage einbauen die eine ISR innerhalb eines kurzen Zeitraums
ignoriert.
K.M. Henkler schrieb:> auf polling wollte ich verzichten.> deswegen möchte ich ja interrupts benutzen.
eine ganz schlechte Idee wenn man mechanische Taster einlesen will.
Entweder du glaubst das, oder du verstehst das oder du muss deine
eigenen Erfahrungen machen
K.M. Henkler schrieb:> auf polling wollte ich verzichten.> deswegen möchte ich ja interrupts benutzen.
Mit PeDa's Routinen nutzt Du Interrupts (zum pollen :-) )
Ansonsten musst Du halt per Hardware entprellen - Möglichkeiten stehen
auch im Link.
https://sites.google.com/site/qeewiki/books/avr-guide/external-interrupts-on-the-atmega328
Hab die Seite als Hilfestellung benutzt. Auch wegen den Timern ist die
Top. Gerade wenn man noch lernen muss Datenblätter zu lesen und zu
verstehen.
Hab den Mode "The falling edge of INTx generates an interrupt request"
eingefügt. Nun läuft es so wie ich es mir gedacht habe. Das mit dem
internen Interrupt werde ich mit dem Polling dann auch mal testen. Danke
euch für die fixe hilfe, ich stand ja voll auf dem schlauch mit dem mode
des Interrupts.
Man sollte nicht immer nur kopieren sondern auch verstehen was dort
wirklich gemacht wird ;)
K.M. Henkler schrieb:> Hab den Mode "The falling edge of INTx generates an interrupt request"> eingefügt. Nun läuft es so wie ich es mir gedacht habe.
Das ist ja spannend - kannst Du den entsprechenden Code bitte hier
einstellen? Ich wusste nicht, dass eine Umstellung auf "falling edge"
die Prellerei eliminiert. Das wäre ja wirklich prima :-)
Dieter F. schrieb:> K.M. Henkler schrieb:>> Hab den Mode "The falling edge of INTx generates an interrupt request">> eingefügt. Nun läuft es so wie ich es mir gedacht habe.>> Das ist ja spannend - kannst Du den entsprechenden Code bitte hier> einstellen? Ich wusste nicht, dass eine Umstellung auf "falling edge"> die Prellerei eliminiert. Das wäre ja wirklich prima :-)
ich habe mal mit meinem oszi gemessen, ein prellen bzw nachschwingen
kann ich nicht festtellen, wundert mich ja selber, denke das es
irgendwie schon entstört ist, da es ein dev board ist. bei meiner
platine die ich später entwerfen will, werde ich auch hardware seitig
entprellen, macht vieles software seitig einfacher.
hier noch der code, obwohl ich ja denke das es von dir Ironie war :P
1
#define F_CPU 16000000UL // 16 MHz
2
3
#include<avr/io.h>
4
#include<avr/interrupt.h>
5
#include<util/delay.h>
6
7
volatileintstate;
8
9
intmain(void)
10
{
11
//state = 0;
12
DDRD&=~(1<<DDD2);// Clear the PD2 pin
13
// PD2 (PCINT0 pin) is now an input
14
15
PORTD|=(1<<PORTD2);// turn On the Pull-up
16
// PD2 is now an input with pull-up enabled
17
18
DDRB&=~((1<<DDB0)|(1<<DDB2));
19
20
21
EICRA|=(1<<ISC01);// set INT0 to trigger on ANY logic change