UPDATE:
ich hab mich noch ein wenig gespielt und versucht wenigstens ein Programm zu schreiben, dass zwei Interrupts auslöst:
Code:
/*
Autor: Thomas
Datum: 18.4.2010
Vers.: 1.0
*/
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/delay.h>
#define BAUD 19200UL
#define F_CPU 7372800UL
#define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1)
//Globale Variablen
//*****************
int32_t durchSens_counter = 0; //Counter fuer Durchflusssensor
int8_t timer_counter = 0; //Counter fuer Timer_IRQ jede 1sec.
int impulse = 0;
int counter1 = 0;
int counter2 = 0;
static int
uart_putchar(char c, FILE *stream)
{
// ... warten bis der Sendepuffer leer ist ...
while ( !( UCSRA & (1<<UDRE)) )
;
UDR = c;
return 0;
}
void uart_init(void)
{
// Baudrate einstellen ( Normaler Modus )
UBRRH = (unsigned char) (UBRR_BAUD>>8);
UBRRL = (unsigned char) (UBRR_BAUD & 0x0ff);
// Aktivieren des Empfängers, des Senders und des "Daten empfangen"-Interrupts
UCSRB = (1<<RXEN)|(1<<TXEN);
// Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
void IRQ_init(void){
//IRQ initialisieren
//SREG = Status Register
//I (bit 7) = Global Interrupt Disable
//SREG |= (0<<7);
// alle Interrupts abschalten
cli();
//externen IRQ setzen
//===================
//GICR = General Interrupt Control Register
//External Interrupt Request Disable fuer INT2
GICR |= (0<<INT0)|(0<<INT1); //
//MCUCSR = MCU Control and Status Register
//ISC2 = Interrupt Sense Control 2: 0= falling edge; 1=rising edge auf PB2(INT2/AIN0)
MCUCSR |= (1<<ISC01)|(1<<ISC00)|(1<<ISC11)|(1<<ISC10);
//MCUCSR |= (1<<ISC2);
//GIFR = General Interrupt Flag Register
//INTF2 = External Interrupt Flag 2: Loeschen mit logischer 1
GIFR |= (1<<INTF0) | (1<<INTF1);
//External Interrupt Request Enable
GICR |= (1<<INT0) | (1<<INT1); //
//GICR |= (1<<INT1);
//Timer Overflow IRQ setzen
//=========================
//TIMSK |= (1<<TOIE0); //Timer Overflow Enable
//SREG = Status Register
//I = Global Interrupt Enable
//SREG |= (1<<7);
//alle Interrupts erlauben
sei();
}
//IRQ fuer Durchflussensor
ISR(INT0_vect){
PORTA &= ~ (1<<PA5);
PORTA |= (1<<PA7);
counter1++;
}
ISR(INT1_vect){
PORTC &= ~ (1<<PC5);
PORTC |= (1<<PC3);
counter2++;
}
void IO_init(void){
//DDRB = (0 << DDB2);
DDRD = (0<< PD3) | (0 <<PD2);
DDRA = (1<< PA5) | (1 <<PA7);
DDRC = (1<< PC5) | (1 <<PC3);
}
int main (void){
IRQ_init();
IO_init();
uart_init();
stdout = &mystdout;
while(1){
printf_P(PSTR("Der Wert 1 betraegt: %i Der Wert 2 betraegt %i \n"), counter1, counter2);
PORTA |= (1<<PA5);
PORTA &= ~ (1<<PA7);
PORTC |= (1<<PC5);
PORTC &= ~ (1<<PC3);
_delay_ms(1000);
}
}
Das Progrmm funktioniert soweit auch. Immer wenn die Inkrementalgeberscheibe auf Schwarz steht wird ein Interrupt ausgelöst.
Leider bleibt der dann aktiv solange bis ich weiter auf weis drehe. Ich möchte aber eigentlich dass der Interrupt nur einmal ausgelöst wird und erst beim nächsten Schwarzen Feld wieder. Er soll also nicht dauerhaft aktiv bleiben (der Zähler zählt dann munter weiter und weiter bis er überläuft und wieder von vorn anfängt, abgesehen davon reagiert der Controller dann nicht, da er sich in Interrupt Routine befindet).
Ich dachte eigentlich mit dem MCUCSR Bits den Interrupt auf steigende Flanke eingestellt zu haben.
Gerade hab ich die beiden Werte für High und Low mit dem Oszi untersucht und die Spannung sind in Ordnung, wakeln also bis auf 1mV nicht hin und her.
Es wird auch nicht daran liegen, dass die Gabellichtschranke nicht sauber wechselt von Low auf High, den dann würde es der Interrupt nicht weiter aktiv bleiben wenn die Scheibe auf schwarz steht.
Was ist da los?
Lesezeichen