Attiny2313 INTF1 nicht gesetzt
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
Liste der Anhänge anzeigen (Anzahl: 1)
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.