PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Attiny2313 INTF1 nicht gesetzt



X-917
23.12.2009, 21:40
Hallo zusammen

Ich habe ein Problem mit meinem "Programm".
Wenn ich an meinem Attiny2313 den INT1 triggere, wird
das INTF1-flag nicht gesetzt, obwohl die Interrupt-routine ausgeführt wird.
Sie wird sogar etwa 3mal hintereinander ausgeführt, das Ganze is ziemlich dubios und unvorhersehbar. Könntet ihr mal meinen Code anschauen? Bin noch Anfänger und auch für andere Verbesserungsvorschläge offen. Wenn es hilft, könnte ich auch noch ein Schaltplan liefern, da die Taster ungewöhnlich verdrahtet wurden, um Eingänge zu sparen.

<code>

#include <avr/io.h>
#include <avr/pgmspace.h>
#include "lcd.h"
#include <avr/interrupt.h>
#include <inttypes.h>
#include <stdint.h>
#include <util/delay.h>

#ifndef F_CPU
#define F_CPU 10700000UL //clock = 10,7Mhz (external)
#endif

volatile uint8_t button_state = 0; //button status
volatile uint8_t button_pressed = 0; //set if button pressed


int main()
{

DDRD = 0x33; //a,b,c & beeper = out
PORTD = 0x17; //a,b,c = 1, beeper = 0

lcd_init(LCD_DISP_ON); //initialize display
lcd_clrscr(); //clear display and cursor home
DDRB |= (1<<PB7); //LED-light = output
PORTB |= (1<<PB7); //LED-light on
lcd_puts_P("XX XX.XX.XXXX XX:XX\n"); //send string to display (ROM)
lcd_puts_P("Next Alarm:"); //send string to display (ROM)

MCUCR = 0x0E; //INT0 = falling, INT1 = rising, sleep mode = idle
GIMSK = 0xC0; //INT1 & INT0 = enabled, PCIE = disabled
sei(); //set global interrup enable flag


while(1 == 1) //forever
{

if(button_pressed == 1) //any button pressed (read flag)
{

if(button_state == 1) //button value == 1
{
lcd_clrscr(); //clear display and cursor home
lcd_puts_P("<-"); //send string to display (ROM)
}

else if(button_state == 2)
{
lcd_clrscr();
lcd_puts_P("->");
}

else if(button_state == 3)
{
lcd_clrscr();
lcd_puts_P("+");
}

else if(button_state == 16)
{
lcd_clrscr();
lcd_puts_P("-");
}

else if(button_state == 17)
{
lcd_clrscr();
lcd_puts_P("MENU");
}

else if(button_state == 18)
{
lcd_clrscr();
lcd_puts_P("should not be seen");
}

button_pressed = 0; //reset flag

}


}

}


ISR(INT1_vect)
{
DDRD &=~ (1<<PD0) | (1<<PD1) | (1<<PD4); //set a,b,c to input
DDRD |= (1<<PD3); //set INT1 to output
button_state =~ (PIND | 0xEC); //button != abc
button_pressed =1; //set button_pressed-flag
DDRD |= (1<<PD0) | (1<<PD1) | (1<<PD4); //set a,b,c to output
DDRD &=~ (1<<PD3); //set INT1 to input
}

</code>

Vielen Dank!

Marco

markusj
23.12.2009, 22:31
Hallo Marco,

Punkt 1: Ich sehe nicht, wo du auf das Flag INTF1 zugreifst.
Punkt 2: Wenn du einen Taster angeschlossen hast, ist der Versuch, den Taster mit Interrupts auszuwerten von vornherein zum Scheitern verurteilt. Taster "prellen" beim Betätigen, es gibt kein sauberes Signal sondern abhängig vom Taster sowohl in der Menge als auch in der Stärke unterschiedlich ausgeprägte Störungen.
Du solltest dich diesbezüglich Mal über das Thema "Debouncing" Informieren.

mfG
Markus

Edit: Bezüglich einer "ungewöhnlichen" Tasterverdrahtung - hast du mehr gemacht als die normale "ein-Pin-je-Taster"-Lösung? Matrixverschaltungen o.ä.? Das sollte aber eigentlich nicht direkt am Fehler beteiligt sein.

X-917
23.12.2009, 23:07
Hallo Markus

Ich greife auch nicht im code auf das flag zu. Im Datenblatt steht, es sollte vor dem Sprung in den betreffenden Interruptvektor gesetzt werden. Beim debuggen habe ich jedoch gesehen, dass es nicht gesetzt wurde.
Könnte es sein, dass der Interrupt deshalb mehrmals abgearbeitet wird, weil mehrere Impulse vom Taster kommen? Wäre mir neu, dass der AVR Interrupts "speichert". Aber auch das würde immer noch nicht erkären, wieso das INTF1-flag nicht gesetzt wird.
Ja, ich habe eine kleine Eigenkreation angehängt. Dies sollte jedoch kein Problem sein, die Tastendrücke wurden alle erkannt.
Die Funktion dieser Schaltung ist wie folgt: zuerst sind A, B und C auf 1. Ein Tastendruck bewirkt nun einen Interrupt an INT1. In der Interrupt-routine wird nun INT1 auf Ausgang und 0 geschaltet und A, B und C als Eingänge mit Pull-ups. Der code der gedrückten Tasten liegt nun in negativer Logik an A, B und C an. Es müssen nur noch die anderen Ports von PORTD mit einer Maske ausgefiltert werden und schon hat man einen schönen Wert.

sternst
23.12.2009, 23:25
Im Datenblatt steht, es sollte vor dem Sprung in den betreffenden Interruptvektor gesetzt werdenDann ist das eine Fehlinterpretation des Datenblatts deinerseits. Es wird gesetzt bei dem entsprechenden Event (also z.B. Flanke an dem Pin). Beim Sprung zur ISR wird es dann wieder gelöscht.


Beim debuggen habe ich jedoch gesehen, dass es nicht gesetzt wurde. Wenn zum Zeitpunkt des Events gerade keine ISR ausgeführt wird (oder Interrupts anderweitig gesperrt sind), ist der Zeitraum, in dem das Flag gesetzt ist, auch extrem kurz. Du musst schon auf ASM-Level im Einzelschritt debuggen, um das gesetzte Flag zu Gesicht zu bekommen (wenn überhaupt).


Wäre mir neu, dass der AVR Interrupts "speichert".Ist aber so. Während die ISR bearbeitet wird, kann ein weiterer Event das Flag wieder setzen, so dass also ein Interrupt (pro Quelle) "gespeichert" wird.

X-917
24.12.2009, 09:02
Hallo Stefan

Ah, ok. Ich dachte das flag wird gelöscht, wenn die ISR verlassen wird.

Dann würde ich es also auch nicht sehen wenn ich ein JTAGICE mkII und die Funktion "step-into-next-statement" benutzen würde?

Ja klar kann das flag wieder gesetzt werden, aber es kann nicht sein, dass meine ISR 3mal oder mehr abgearbeitet wird, nur weil ein taster prellt. der AVR speichert eben maximal einen weiteren Interrupt derselben Quelle.
Klar kann es sein, dass durch das prellen der Interrupt immer wieder getriggert wird, doch ich denke nicht, dass das beim debuggen vorkommen würde. Die Ausführzeiten der ISR liegen dort ja weit über der Prellzeit der Taster.

MfG

Besserwessi
24.12.2009, 13:21
Wenn man ohne Debugger arbeitet, wird die Zeit zum Ausführen der ISR kürzer sein als die typische Prelzeit (ca. 1 ms), außer bei 32 kHz Takt. Vo daher kann die ISR Schon mehrfach ausgeführt werden.

Das Interrupt Flag wird schon beim Aufrufen der ISR gelöscht, nicht erst am Ende. Man sieht als in der ISR das Flag nicht mehr, da hift es auch nicht auf ASM Ebene zu debuggen. Nur wenn man ein sehr schnelles Prellen hat, könnte das Flag schon wieder ein 2tes mal gesetzt werden.

X-917
24.12.2009, 14:20
Hmm, aber die ISR wird WÄHREND DEM DEBUGGEN 3 mal ausgeführt...
Sie sollte aber, falls die Taster prellen, maximal 2 mal ausgeführt werden.
(1mal druck + 1 mal flag während der Abarbeitung der ISR durch prellen)

X-917
24.12.2009, 14:23
Achja, am Ende werde ich tatsächlich mit 32khz Takt arbeiten. Habe jedoch im Moment einen 10.7Mhz Quarz in Gebrauch, da der 32khz für debugwire zu langsam ist. Ich werde das Programm noch mit dem 32khz Quarz testen und dann berichten, ob das Problem immer noch vorhanden ist.

X-917
29.12.2009, 12:15
Ich kapiers nicht...

Es scheint, als würde der Interrupt getriggert, SOLANGE der Schalter gedrückt wird. Dabei habe ich doch auf "rising edge" konfiguriert...
Kann mir das mal jemand erklären? Unter Errata habe ich nichts gefunden was auf einen Designfehler des Controllers hindeutet, ich verzweifle langsam.

Ausserdem wird mein button_state bei folgender Zeile auf 0 gesetzt!!

if(button_pressed == 1) //any button pressed (read flag)

Weiss den niemand, was ich falsch mache?

X-917
29.12.2009, 17:10
Aaah!
Ich habe den Fehler gefunden. Hoch lebe das debuggen!
Wenn man sich die Zustände des INT1-Pin ansieht, fällt einem vielleicht etwas auf... Wenn ich nämlich den INT-pin auf 0 ziehe, um die Taster auszulesen, wird danach ein Interrupt ausgelöst, wenn ich ihn wieder auf Eingang schalte, da er dann wieder vom gedrückten Taster auf 1 gezogen wird. So entsteht bei jedem Interrupt ein neuer.