UPDATE:
ich hab mich noch ein wenig gespielt und versucht wenigstens ein Programm zu schreiben, dass zwei Interrupts auslöst:
Das Progrmm funktioniert soweit auch. Immer wenn die Inkrementalgeberscheibe auf Schwarz steht wird ein Interrupt ausgelö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); } }
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?







Zitieren

Lesezeichen