mikrocontroller.net

Forum: Compiler & IDEs Programm springt falsch


Autor: ibot (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Daniel G. (motello)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: ibot (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Wolfgang Horn (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

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
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
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 bestätigst du, die Nutzungsbedingungen anzuerkennen.