Forum: Compiler & IDEs Programm springt falsch


von ibot (Gast)


Lesenswert?

Hallo zusammen,

ich bin gerade mit der AVR Programmierung angefangen und versuche ein 
Markisen Steuerung zu programmieren.

Quelltext:

// Port Definition
// PC0 -> Eingang -> rein / raus umschalter & motor bewegen
// PC1 -> Eingang -> Wind blockieren
// PC2 -> Eingang -> blockieren nicht möglich
// PC3 -> Ausgang -> durch Winde blockiert
// PC4 -> Ausgang -> rein / raus
// PC5 -> Ausgang -> Motor ein

#define F_CPU 1000000UL
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>



struct
{
   unsigned wind:1; // 1 Bit für bStatus_1
   unsigned manuellbetrieb:1; // 1 Bit für bStatus_2
   unsigned motor_bewegung:1; // Und hier noch mal ein Bit
   unsigned richtung_raus:1;    // Dieses Feld ist 2 Bits breit
   // All das hat in einer einzigen Byte-Variable Platz.
   // die 3 verbleibenden Bits bleiben ungenutzt
} status;

int motor_ein()
{
  status.motor_bewegung = 1;
  PORTC |= (1<<PC5);

  return 0;
};

int motor_aus(void)
{
  PORTC &= ~(1<<PC5);
  status.motor_bewegung = 0;

  return 0;
};

volatile unsigned int Counter;
ISR( TIMER0_OVF_vect )
{
  Counter++;

  if(Counter == 2)
  {
    Counter = 0;
  TCCR0 &= ~((1<<CS00)|(1<<CS01)|(1<<CS02));  //Timer deaktivieren

  cli();
  motor_aus();
  }
};



int bewegungsrichtung_change()
{
  //Richtung invertieren
  PORTC = PINC ^ ( 1 << PC4 );

  return 0;
};

int markise_fahren()
{
  bewegungsrichtung_change();
  motor_ein();

  TCCR0 = ( 1 << CS02 ) | ( 1 << CS00 ); // Teiler: 1024
  TIMSK = ( 1 << TOIE0 );         // Overflow Interrupt einschalten
  sei();                          // Interrupt generell zulassen

  return 0;
};


int markise_ein_fahren()
{
  //Bewegungsrichtung rein
  PORTC &= ~(1<<PC4);
  motor_ein();

  TCCR0 = ( 1 << CS02 ) | ( 1 << CS00 ); // Teiler: 1024
  TIMSK = ( 1 << TOIE0 );         // Overflow Interrupt einschalten

  return 0;
};


int init()
{
  //Datenrichtung bestimmen
  DDRC = 0b00111000;  //Ausgänge & Eingänge setzen


  status.wind = 0;
  status.manuellbetrieb = 1;
  status.motor_bewegung = 0;
  status.richtung_raus = 1;


  //Markiese einfahren
  markise_ein_fahren();

  return 0;
};

int main (void) {

  init();

  //markise_fahren();




  while(1)
  {
    if ( PINC & (1<<PINC0) )
    {
      markise_fahren();
    }

  }
  return 0;
};



Mein Problem ist, dass das Programm erst in die main() springt, dann in 
die init(). Soweit ist auch alles ok. Aber in der init() ruft er 
markise_ein_fahren(). Von dort führt er auch alles aus aber springt dann 
irgendwann in bewegungsrichtung_change() und anschließend in 
markise_fahren(). Aber warum?

Gruß,
Tobi

von Daniel G. (motello)


Lesenswert?

Springt er nicht vielleicht von markise_fahren() nach 
bewegungsrichtung_change() und führt anschließend den restlichen code 
von markise_fahren() aus?

Es ist wohl deine if-abfrage "if ( PINC & (1<<PINC0) )" falsch, dass er 
immer reinspringt?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Da fehen wohl ein paar volatiles.

Ausserdem kannst du nicht im Programm die IRQs aktivieren und in einer 
ISR deaktivieren. Beim Beenden der ISR wird der vorherige Programmstatus 
-- also auch das I-Flag -- wieder hergestellt.

Johann

von ibot (Gast)


Lesenswert?

Hallo,

was schlägst du vor, wie ich den Timer starte und anschließend wieder 
stoppe?

Oder soll der Timer einfach die ganze Zeit laufen?

Gruß,
Tobi

von Wolfgang Horn (Gast)


Lesenswert?

Hi, ibot,

"TIMSK = ( 1 << TOIE0 );         // Overflow Interrupt einschalten
  sei();                          // Interrupt generell zulassen"

Hier gibt Du Interrupts frei.
Bei jedem Überlauf springt der Programmzähler auf die Adresse, wo er den 
Sprungvektor für die Interrupt-Routine ISR(SIG_OVERFLOW0) (oder so 
ähnlich) erwartet - und dort rastet er aus.

Schau in das Datenblatt, welche ISR genau benötigt wird, füge sie hinzu, 
und schon ist dieser Fehler behoben - und der nächste taucht auf....;-(


Ciao
Wolfgang Horn

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.