PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme mit Taster zum Auslösen des externen Interrupts



Jaccaranda
05.03.2010, 18:02
Hallo!

Ich habe ein RN-Minicontrol Board (mit Atmega168) und ein RN-Speak, das über I2C mit dem Controller verbunden ist. Am Controllerboard hängt auch ein Ultraschallsensor. Ab einer bestimmten Entfernung werden die Abstandswerte als Sprachnachrichten über das RNSpeak ausgegeben. Programmiert ist das ganze unter BASCOM.

Das hat bisher super funktioniert.

Jetzt möchte ich, dass die Messung und Ausgabe nur dann durchgeführt wird, wenn ich einen Taster betätige, der an JP1 angeschlossen ist. Und ab jetzt funktioniert gar nichts mehr. Prinzipiell ist mein Programm folgendermaßen aufgebaut:
.
.
.
config pind.2=input
config int0=rising
enable interrupts
enable int0
on int0 ausgabe
portd.2=0

do
NOP
loop
end

Ausgabe:

...
return


meinen drucktaster habe ich zwischen 5V und Signalpin an JP1 geschalten. der interrupt wird scheinbar total willkürlich ausgelöst auch wenn ich den taster nicht drücke und wenn ich den taster drücke wird er auch manchmal nicht ausgelöst. manchmal gibt rn-speak auch einfach die letzte message aus, was so im programm gar nicht auftaucht. außerdem wird das Programm zwischendurch einfach hin und wieder neu gestartet. Einen Kurzschluss habe ich aber sicher nirgendwo.
Ich bin mir nicht sicher ob es sich um ein Hardware- oder Softwareproblem handelt. Kann es am Taster liegen? Oder an den Kabeln? Oder muss ich für den externen Interrupt noch zusätzliche Einstellungen machen? In der BASCOM Hilfe habe ich gelesen dass ich beim atmega168 das r23 sichern muss??


Hilfe!! Ich bin wirklich verzweifelt. Hat jemad eine Idee?

Kampi
05.03.2010, 18:18
Entprell mal den Taster im Programm also einfach schreiben:

If Pin(Taster) = 0 then ....
Waitms100
If Pin(Taster) = 0 then....

und schalt den Taster mal nicht gegen 5V sondern gegen Ground. Also 5V mit einem 10k Ohm Widerstand an Interrupt dazu parallel den Taster gegen Ground, soass wenn der TAster gedrückt wird eine Verbindung von Vcc und GND besteht. So haste nämlich zwei fest definierte Pegel. EInmal die 5V und einmal 0V

reinhars
08.03.2010, 07:16
Mit Interrupts kann man viel Spaß haben - vorallem wenn man mehrere hat und diese nur zu bestimmten Zeiten aktiviert oder deaktiviert :-)

Als Tip habe ich noch für dich:
-In der Interruptroutine nur ein Bit setzen und dann in der Hauptschleife dieses Bit auswerten und rücksetzen. Das vermeidet viele Probleme weil wenn gerade ein Interrupt ausgeführt wird kein anderer Interrupt greifen kann bzw. nur ein Interrupt mit höherer Priorität greifen kann.
-Ein debouncen des Tasters kannst du dir Sparen, wenn du nach der Auswertung in der Hauptschleife den Interrupt ausschaltest und nach Abarbeitung wieder einschaltest.


do
If Bit = 1 then
Disable Int 0
Auswertung......

.... Auswertung ende
Reset Bit
Enable Int 0
end if
loop
end

interrupt:
set bit
return

Als Grundregel gilt: Interrupts so kurz wie möglich.

Grüße Stefan

Richard
08.03.2010, 11:53
Entweder an JP.1 den internen Pull up einschalten oder
einen externen 10k gegen vcc anschließen. Den Taster
dann von JP.1 nach GND schalten UND config int0=rising
ändern auf = falling. Man kann noch parallel zum Taster
einen 100 nF setzen.

Gruß Richard

for_ro
08.03.2010, 13:18
Hallo Stefan,
in deiner Antwort sind einige Ungenauigkeiten, die so nicht stehen bleiben sollten.

-In der Interruptroutine nur ein Bit setzen und dann in der Hauptschleife dieses Bit auswerten und rücksetzen. Das vermeidet viele Probleme weil wenn gerade ein Interrupt ausgeführt wird kein anderer Interrupt greifen kann bzw. nur ein Interrupt mit höherer Priorität greifen kann.
Während ein Interrupt in seiner ISR behandelt wird, kann kein anderer Interrupt ausgeführt werden. Auch ein Interrupt mit höherer Priorität kann diesen nicht unterbrechen.
Prioritäten sind nur interessant, wenn zu einem Zeitpunkt gleich mehrere Interrupts zur Ausführung anliegen. Dann und nur dann wird tatsächlich nach der Reihenfolge abgearbeitet, die im Datenblatt angegeben ist. Ansonsten verwenden die AVRs keine Prioritäten.

-Ein debouncen des Tasters kannst du dir Sparen, wenn du nach der Auswertung in der Hauptschleife den Interrupt ausschaltest und nach Abarbeitung wieder einschaltest.
Das Disablen des Interrupts führt nur dazu, dass momentan keine ISR aufgerufen wird. Trotzdem ist der Interrupt intern vermerkt und führt nach Enable Interrupt sofort zu dessen Ausführung. Ein Prellen kannst du dadurch also nicht beseitigen.



Als Grundregel gilt: Interrupts so kurz wie möglich.

Das ist jedenfalls die richtige Vorgehensweise, führt aber nicht unbedingt zu problemloser Ausführung. Man muss die Möglichkeit der Unterbrechung des Ablaufs mit Verstand einsetzen und sich überlegen, wann sollen welche Code Teile ausgeführt werden und welche Teile möchte ich vor Unterbrechung schützen.
Es macht wenig Sinn, eine ISR auf das Setzen eines Flags zu beschränken um dann in der Hauptschleife sofort die Interrupts zu sperren. Dann lege ich die Befehle lieber gleich in die ISR.

oberallgeier
08.03.2010, 13:49
... Während ein Interrupt in seiner ISR behandelt wird, kann kein anderer Interrupt ausgeführt werden. Auch ein Interrupt mit höherer Priorität kann diesen nicht unterbrechen ...Falsch. Beispiel, gilt bei allen At mel die ich kenne:

... When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled. The user software can write logic one to the I-bit to enable nested interrupts. ...

for_ro
08.03.2010, 15:05
Guter Hinweis: Wenn man sie explizit in der ISR wieder freigibt, geht es mit allen Interrupts doch. Standardmäßig ist dieses Verhalten abgeschaltet.
Ist aber eher etwas für den absoluten Fachmann wie dich. Hier gilt noch mehr, das man genau wissen sollte, was man da tut.

Jaccaranda
08.03.2010, 21:30
vielen dank schonmal für die tips! wird durch den befehl portd.2=1 der pull up widerstand gesetzt? oder gibt es da einen anderen befehl unter bascom?

Jaccaranda
10.03.2010, 11:36
Hallo!
Also mit dem Taster auf GND funktioniert das Schalten jetzt einwandfrei, vielen Dank. Ich habe den Code auch nach dem Vorschlag von reinhars umgestaltet. allerdings wird das interrupt trotzdem bei etwas längerem drücken des Tasters zweimal ausgelöst. Habe schon versucht dies mit einer waitschleife mit bis zu 10 sekunden vor dem erneuten enable des interrupts zu vermeiden. jetzt kommt der zweite Interrupt nach dieser wartezeit!! sieht jemand den fehler?

Richard
10.03.2010, 12:24
Das ist kein Fehler, auch bei ausgeschaltete IRQ werden die
gespeichert und nach dem Freigeben in der gespeicherten
Reihenfolge abgearbeitet. Wenn das verhindert werden soll
muss man vor dem verlassen des IRQ das IRQ Flac löschen.

Ich habe es nicht genau im Kopf, aber ich glaube das dieses
Flac gelöscht wird wenn dort eine (1) gesetzt wird?

Gruß Richard

Jaccaranda
10.03.2010, 12:57
danke für den tip mit dem irq flag, daran wird es wohl liegen. der befehl lautet auch GIFR.INTF0 = 1 (laut diversen anderen foren).
allerdings spuckt bascom dabei eine fehlermeldung aus: invalid datatype
muss das register zuvor irgendwie konfiguriert werden?

kolisson
10.03.2010, 14:28
wie kommst du darauf ? GIFR.INTF0 = 1

ich sehe im datenblatt des 168 kein solches register

ich sehe stattdessen 11.2.3EIFR – External Interrupt Flag Register

•Bit 0 – INTF0: External Interrupt Flag 0

gruss