Datum:
Nabend Community Hab ein kleines Problem mit einem Interrupt. Nutze den Interrupt zusammen mit dem 16Bit Timers des ATTiny24 als Zeitsicherung, falls der normalerweise auslösende Taster versagen sollte. Wenn ich den Interrupt global deaktiviere läuft die Steuerung normal, bzw. so wie sie sollte, nur halt ohne diese Sicherungsfunktion. Schalte ich den Interrupt global ein, dann funktioniert der erste Durchlauf normal, ab dem 2. hört man zwar, dass das FET an Port B2 kurz geschaltet wird, aber direkt wieder ausgeschaltet wird. habe jetzt 2 Stunden mit AVR-Simulator versucht diesen Fehler zu reproduzieren, allerdings erfolglos. Da ich den Fehler einfach nicht finden kann, poste ich einfach mal den Code, vl. sieht ja jemand den Fehler.
#include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #define timer1_prescaler (1 << CS11) | (1 << CS10) #define timer1_aus ~((1 << CS11) | (1 << CS10)) #define timer1_compare_value 0x61A //******************************Variablen****************************** unsigned short int ammunition=1; uint16_t erg; unsigned short int fehler=0; volatile unsigned short int error=0; //**********Instellungsfariablen******************** //Munitionserkennung unsigned short int ammo=0; //Magazinerkennung unsigned short int mag=0; void initPortA() { /******************Initalisierung PortA**************************** PortA wird nur für Sensoren genutzt! PINA0 = Trigger PINA1 = Cutoff PINA2 = Magazinerkennung PINA3 = Boltcatch PINA4 = Charginghandle PORTA auf Eingabe mit Pullup-Wiederständen */ DDRA = 0x00; PORTA = 0b11011111; } void initPortB() { /*****************Initalisierung PortB****************************** PortB wird nur zur Motorsteuerung genutzt! PINB0 = Motorbremse geschaltet bei PORTB &= ~(1<<PB0); PINB2 = Treibendes FET geschaltet bei PORTB |= (1<<PB2); !Beim alten layout ohne PWM ist es PB1!!!! Der WErt wird erst gesetzt und dann den Pins die Ausgangsrichtung gesetzt um beim einschalten zu verhindern, dass Ausgangspins falsch stehen. */ PORTB = 0b00000001; DDRB = (1 << DDB0) | (1 << DDB2); } void initADC() { /******************Iniialisierung ADC*******************************/ if (ammo != 0) { if (!(PINA & (1<<PINA4))) //Munitionserkennung Brücke { ADCSRA = (1<<ADPS2) /*| (1<<ADPS0)*/ | (1<<ADATE); //Vorteiler = 8 ADATE = Free Running ADMUX = (1<<MUX2) | (1<<MUX0); //Kanal 5 (PA5) ADCSRA |= (1<<ADEN); } } } void initTimer() { /*****************Initialisierung Timer1****************************/ TIMSK1 |= (1 << OCIE1A); OCR1A = 0x1388; } void loading() { while(PINA & (1<<PINA2)); while(!(PINA &(1<<PINA2))) { _delay_ms(20); } ammunition=1; } void magazine() { if (mag !=0) { while (!(PINA & (1<<PINA2))); } } void WaitForTrigger() { while (PINA & (1 << PINA0)); if (ammunition == 0 && ammo != 0) { loading(); } } void mbreak() { ADCSRA |= !(1<<ADSC); PORTB &= ~(1<<PB2); _delay_ms(1); PORTB &= ~(1<<PB0); _delay_ms(100); PORTB |= (1<<PB0); while(!(PINA & (1<<PINA0))) { _delay_ms(10); } } void shoot() { ammunition = 0; ADCSRA |= (1<<ADSC); TCNT1 = 0; TIMSK1 |= (1 << OCIE1A); TCCR1B |= (1 << CS11) | (1 << CS10); PORTB |= (1<<PB2); if (!(PINA & (1<<PINA1))) //mit Hallsensor muss die bedingung andersherum sein! ohne "!" { while (!(PINA & (1<<PINA1))); //mit Hallsensor muss die bedingung andersherum sein! ohne "!" } while ((PINA & (1<<PINA1)) && (error!=1)) //mit Hallsensor muss die bedingung andersherum sein! mit "!" { if (ammo != 0) { erg = ADCW; if (erg < 0x0C8) { ammunition = 1; } } } TIMSK1 &= ~(1 << OCIE1A); TCCR1B &= ~(1 << CS11) | ~(1 << CS10); error = 0; ADCSRA &= ~(1<<ADSC); mbreak(); } int main(void) { initPortA(); initPortB(); initADC(); initTimer(); //magazine(); _delay_ms(100); //WaitForTrigger(); //shoot(); sei(); while(1) { //magazine(); WaitForTrigger(); shoot(); } } ISR(TIM1_COMPA_vect) { TIMSK1 &= ~(1 << OCIE1A); TCCR1B &= ~((1 << CS11) | (1 << CS10)); error=1; } |
Hoffe der Code ist verständlich. Ich danke euch schon mal für eure Hilfe. Kolo
Datum:
Ein erster Tipp: statt "unsigned short int" (=16 Bit) könntest Du überall auch 8 Bit Variabeln verwenden, => "uint8_t" Hilft vermutlich nicht weiter, aber macht den Code auf einer 8-Bit CPU deutlich effizienter...
Datum:
TCCR1B &= ~(1 << CS11) | ~(1 << CS10); |
Das soll wohl den Timer stoppen, aber in Wirklichkeit wird mit dieser Zeile kein einziges Bit in TCCR1B verändert.
Datum:
>> TCCR1B &= ~(1 << CS11) | ~(1 << CS10); > >Das soll wohl den Timer stoppen, aber in Wirklichkeit wird mit dieser >Zeile kein einziges Bit in TCCR1B verändert. Hehehe, dabei hat er's weiter oben sooooo schööööööön definiert: #define timer1_aus ~((1 << CS11) | (1 << CS10))
Datum:
Ja, daher ja die unabhängige Meinung. Hab das nicht gesehen :D Werd das nachher mal ändern. Aber an sich dürfte das dich nicht so viel ausmachen da das Compare Interrupt Flag auch auf null gesetzt wird.
TIMSK1 &= ~(1 << OCIE1A); |
Datum:
koloblix schrieb: > Aber an sich dürfte das dich nicht so viel ausmachen > da das Compare Interrupt Flag auch auf null gesetzt wird. Das ist nicht das Flag, sondern das Enable-Bit. Und das verhindert nicht, dass beim nächsten Erreichen des Compare-Wertes das entsprechende Flag gesetzt wird. Und wenn dann das Enable-Bit wieder gesetzt wird, kommt sofort der Interrupt, weil ja das dazugehörige Flag dann schon gesetzt ist.