mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik At Mega 16 Problem mit dem Toggeln von Ports


Autor: Oliver Kra (Firma: TGM) (oliver1990)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Ich habe folgendes Problem, habe ein Probramm, dass einen Tisch in zwei 
Ebenen steuert und mit dem ATMega128 einwandfrei funktioniert.
Jetzt habe ich das Programm auf den AtMega16 überschrieben, natürlich 
mit den notwendigen Veränderungen, jedoch funktioniert die 
Richtungsänderung und der Enable nicht. Sprich er hupft in die 
for-Schleife von y in der Funktion zeilenscan gar nicht rein.

Könnt mir hier vl weiterhelfen?
Vielen dank schon im Voraus!

lg

include <util/delay.h>  
#define F_CPU 16000000UL   //Frequenz
#include <avr/io.h>     //Deklaration
#include <util/delay.h>
#include<avr/signal.h>    //fuer Interrupt
#include<avr/interrupt.h>

static int DURCHLAUFE=100; //sonst 255
static int DURCHLAUFEG=100; // = Frequenz nach dem Teiler / gewnschte Frequenz
static char SCHRITT=1;
static char enablex=0;
static char enabley=0;
static int SCHRITTG=50;    // entspricht ca. 1 cm bei unserem Tisch
static char richtungx;
static char richtungy;
static char flag=0;

ISR(SIG_OVERFLOW0)    //Timer fr die Motorsteuerung
{    
    if(richtungx==1) {PORTB = PORTB |(1 << PB1);}    //Richtungsabfrage x
    else  {PORTB = PORTB &~ (1 << PB1);}
    if(richtungy==1) {PORTB = PORTB | (1 << PB4);}    //Richtungsabfrage y
    else  {PORTB = PORTB &~ (1 << PB4);}
    if(enablex==1)  {PORTB = PORTB | (1 << PB2);}    //Enableabfrage x
    else  {PORTB = PORTB & ~( 1 << PB2 );}
    if(enabley==1)  {PORTB = PORTB | (1 << PB5);}    //Enableabfrage y
    else  {PORTB = PORTB &~ (1 << PB5);}
    
    
    PORTB ^= (1 << PB0) ;      //Toggeln fuer Takt
    PORTB ^= (1 << PB3) ;      //Toggeln fuer Takt

    TCNT0= 256 - DURCHLAUFE;     //Startwert von Timer0; ft=fp/DURCHLAUFE(=(256-Startwert))

    SCHRITT=SCHRITT + 1;      //Zählt einen Schritt dazu, fuer die Abfrage der getätigten Schritte
}

void delayms(int ms) 
{
  int id;
  for(id=0; id<=ms; id++)
    _delay_ms(1);
}


void zeilenscan(int laengex, int laengey)    //Steuert die zwei Motoren in einem Zeilenscannverfahren. Zeilen sind durch ez und iz vernderbar
{  
  int x;  
  int d;
  int y;

  for(y=1; y<=laengey; y++)      //Schleife für die Bewegung in der Y-Ebene (positive Richtung)
  {
  for(x=1; x<=laengex; x++)      //Schleife für die Bewegung in der X-Ebene (positive Richtung)
  {
    richtungx=1;
    enablex=1;
    SCHRITT=1;
    while(SCHRITT<=SCHRITTG)
    {
    }
    enablex=0;
    if(flag>0) return;
    for(d=1; d<=1000; d++)
    {
    _delay_ms(1);
    }
  }
  richtungy=1;
  enabley=1;
  enablex=1;
  SCHRITT=1;
  while(SCHRITT<=SCHRITTG)
  {
  }
  enabley=0;
  enablex=0;
  for(d=1; d<=1000; d++)
  {
  _delay_ms(1);
  }
  for(x=1; x<=laengex; x++)      //Schleife für die Bewegung in der X-Ebene (negative Richtung)
  {
    richtungx=0;
    enablex=1;
    SCHRITT=1;
    while(SCHRITT<=SCHRITTG)
    {
    }
    enablex=0;
    if(flag>0) return;
    for(d=1; d<=1000; d++)
    {
    _delay_ms(1);
    }
  }
  richtungy=1;
  richtungx=1;
  enablex=1;
  enabley=1;
  SCHRITT=1;
  while(SCHRITT<=SCHRITTG)
  {
  }
  enablex=0;
  enabley=0;
  for(d=1; d<=1000; d++)
  {
  _delay_ms(1);
  }
  if(flag>0) return;
  }
}




int main(void)
{
  TCCR0 = (/*0<<CS00)|(1<<CS01)|(*/1<<CS02) ; // (Teiler) Register richtig setzen fuer den Timer0, dzt. Frequenz = f/128
  TIFR = (1<<TOV0);             // Timer Interrupt Flag Register --> enable
  TIMSK = (1<<TOIE0);
  TCNT0= 256 - DURCHLAUFE;         //Startwert von Timer0; ft=fp/DURCHLAUFE(=(256-Startwert))
sei();  //Interrupts aktivieren

  DDRB=0xFF;
  DDRD=0x00;

  while (1)
  {
    zeilenscan(10,5);
  }  
}

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein paar volatile Kennzeichnungen fehlen z.B. bei SCHRITT
mehr siehe AVR-GCC-Tutorial Interrupts

> include <util/delay.h>
> #define F_CPU 16000000UL   //Frequenz
> #include <avr/io.h>     //Deklaration

Out of Order includes. delay muss F_CPU bereits kennen.

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
include <util/delay.h>  
#define F_CPU 16000000UL   //Frequenz
#include <avr/io.h>     //Deklaration
#include <util/delay.h>
#include<avr/signal.h>    //fuer Interrupt
#include<avr/interrupt.h>

besser
#infndef F_CPU
   #warning F_CPU definiere F_CPU neu
   #define F_CPU 16000000UL   //Frequenz
#endif

#include <avr/io.h>     //Deklaration
#include <util/delay.h>
#include<avr/interrupt.h>

So bekommst du eine Warnung wenn F_CPU schon irgendwo anders definiert 
ist z.B. im Makefile

signal.h sollte man nicht mit interrupt.h mischen....

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1.)
Alle Variabeln die Du innerhalb und auch ausserhalb einer ISR verwendest 
musst Du volatile deklarieren:
static volatile int DURCHLAUFE=100; //sonst 255
static int DURCHLAUFEG=100; 
static volatile char SCHRITT=1;
static volatile char enablex=0;
static volatile char enabley=0;
static volatile int SCHRITTG=50;
static volatile char richtungx;
static volatile char richtungy;
static char flag=0;

2.)
Alle Variabeln die Du innerhalb einer ISR änderst und auch ausserhalb 
der ISR verwendest und zudem grösser als 1 Byte sind (z.B. int) musst du 
ausserhalb der ISR atomic zugriffe sicherstellen (ISR gesperrt)

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... ... schrieb:
> So bekommst du eine Warnung wenn F_CPU schon irgendwo anders definiert
> ist z.B. im Makefile
>
> signal.h sollte man nicht mit interrupt.h mischen....

Die Warnung wirft der Compiler auch ohne das #define-Geraffel, und 
signal.h stört sich auch nicht an interrupt.h. Trotzdem wäre es 
natürlich gut, die ISR-Vektoren mal auf die aktuellen Namen zu ändern.

Das Programm dürfte in dieser Form mit einer eingermassen aktuellen 
Version von avr-gcc auf einem Mega128und auf einem Mega16 nur ohne 
Optimierung laufen. Wie schon gesagt wurde, fehlen da einige volatiles. 
Die älteren gcc-Versionen ( < 2003 ???) waren da toleranter, und 
signal.h lässt darauf schliessen, daß das alles schon älter ist.

Alle Variablen, die im Hauptprogramm UND in der ISR gelesen bzw. 
geschrieben werden, brauchen den volatile-Qualifier.

Oliver

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.