www.mikrocontroller.net

Forum: GCC Fehler mit Interrupt?


Important announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Koloblix (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
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

Autor: Peter S. (psavr)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
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...

Autor: Stefan Ernst (sternst)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
  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.

Autor: Peter S. (psavr)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
>>  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))

Autor: koloblix (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
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);

Autor: Stefan Ernst (sternst)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
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.

Autor: Koloblix (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Aha, ok das klärt einiges. THX

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel




Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder GIF-Format hochladen.
Siehe Bildformate
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net