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


von Oliver K. (Firma: TGM) (oliver1990)


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

1
include <util/delay.h>  
2
#define F_CPU 16000000UL   //Frequenz
3
#include <avr/io.h>     //Deklaration
4
#include <util/delay.h>
5
#include<avr/signal.h>    //fuer Interrupt
6
#include<avr/interrupt.h>
7
8
static int DURCHLAUFE=100; //sonst 255
9
static int DURCHLAUFEG=100; // = Frequenz nach dem Teiler / gewnschte Frequenz
10
static char SCHRITT=1;
11
static char enablex=0;
12
static char enabley=0;
13
static int SCHRITTG=50;    // entspricht ca. 1 cm bei unserem Tisch
14
static char richtungx;
15
static char richtungy;
16
static char flag=0;
17
18
ISR(SIG_OVERFLOW0)    //Timer fr die Motorsteuerung
19
{    
20
    if(richtungx==1) {PORTB = PORTB |(1 << PB1);}    //Richtungsabfrage x
21
    else  {PORTB = PORTB &~ (1 << PB1);}
22
    if(richtungy==1) {PORTB = PORTB | (1 << PB4);}    //Richtungsabfrage y
23
    else  {PORTB = PORTB &~ (1 << PB4);}
24
    if(enablex==1)  {PORTB = PORTB | (1 << PB2);}    //Enableabfrage x
25
    else  {PORTB = PORTB & ~( 1 << PB2 );}
26
    if(enabley==1)  {PORTB = PORTB | (1 << PB5);}    //Enableabfrage y
27
    else  {PORTB = PORTB &~ (1 << PB5);}
28
    
29
    
30
    PORTB ^= (1 << PB0) ;      //Toggeln fuer Takt
31
    PORTB ^= (1 << PB3) ;      //Toggeln fuer Takt
32
33
    TCNT0= 256 - DURCHLAUFE;     //Startwert von Timer0; ft=fp/DURCHLAUFE(=(256-Startwert))
34
35
    SCHRITT=SCHRITT + 1;      //Zählt einen Schritt dazu, fuer die Abfrage der getätigten Schritte
36
}
37
38
void delayms(int ms) 
39
{
40
  int id;
41
  for(id=0; id<=ms; id++)
42
    _delay_ms(1);
43
}
44
45
46
void zeilenscan(int laengex, int laengey)    //Steuert die zwei Motoren in einem Zeilenscannverfahren. Zeilen sind durch ez und iz vernderbar
47
{  
48
  int x;  
49
  int d;
50
  int y;
51
52
  for(y=1; y<=laengey; y++)      //Schleife für die Bewegung in der Y-Ebene (positive Richtung)
53
  {
54
  for(x=1; x<=laengex; x++)      //Schleife für die Bewegung in der X-Ebene (positive Richtung)
55
  {
56
    richtungx=1;
57
    enablex=1;
58
    SCHRITT=1;
59
    while(SCHRITT<=SCHRITTG)
60
    {
61
    }
62
    enablex=0;
63
    if(flag>0) return;
64
    for(d=1; d<=1000; d++)
65
    {
66
    _delay_ms(1);
67
    }
68
  }
69
  richtungy=1;
70
  enabley=1;
71
  enablex=1;
72
  SCHRITT=1;
73
  while(SCHRITT<=SCHRITTG)
74
  {
75
  }
76
  enabley=0;
77
  enablex=0;
78
  for(d=1; d<=1000; d++)
79
  {
80
  _delay_ms(1);
81
  }
82
  for(x=1; x<=laengex; x++)      //Schleife für die Bewegung in der X-Ebene (negative Richtung)
83
  {
84
    richtungx=0;
85
    enablex=1;
86
    SCHRITT=1;
87
    while(SCHRITT<=SCHRITTG)
88
    {
89
    }
90
    enablex=0;
91
    if(flag>0) return;
92
    for(d=1; d<=1000; d++)
93
    {
94
    _delay_ms(1);
95
    }
96
  }
97
  richtungy=1;
98
  richtungx=1;
99
  enablex=1;
100
  enabley=1;
101
  SCHRITT=1;
102
  while(SCHRITT<=SCHRITTG)
103
  {
104
  }
105
  enablex=0;
106
  enabley=0;
107
  for(d=1; d<=1000; d++)
108
  {
109
  _delay_ms(1);
110
  }
111
  if(flag>0) return;
112
  }
113
}
114
115
116
117
118
int main(void)
119
{
120
  TCCR0 = (/*0<<CS00)|(1<<CS01)|(*/1<<CS02) ; // (Teiler) Register richtig setzen fuer den Timer0, dzt. Frequenz = f/128
121
  TIFR = (1<<TOV0);             // Timer Interrupt Flag Register --> enable
122
  TIMSK = (1<<TOIE0);
123
  TCNT0= 256 - DURCHLAUFE;         //Startwert von Timer0; ft=fp/DURCHLAUFE(=(256-Startwert))
124
sei();  //Interrupts aktivieren
125
126
  DDRB=0xFF;
127
  DDRD=0x00;
128
129
  while (1)
130
  {
131
    zeilenscan(10,5);
132
  }  
133
}

von Stefan B. (stefan) Benutzerseite


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.

von ... .. (docean) Benutzerseite


Lesenswert?

1
include <util/delay.h>  
2
#define F_CPU 16000000UL   //Frequenz
3
#include <avr/io.h>     //Deklaration
4
#include <util/delay.h>
5
#include<avr/signal.h>    //fuer Interrupt
6
#include<avr/interrupt.h>

besser
1
#infndef F_CPU
2
   #warning F_CPU definiere F_CPU neu
3
   #define F_CPU 16000000UL   //Frequenz
4
#endif
5
6
#include <avr/io.h>     //Deklaration
7
#include <util/delay.h>
8
#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....

von Peter (Gast)


Lesenswert?

1.)
Alle Variabeln die Du innerhalb und auch ausserhalb einer ISR verwendest 
musst Du volatile deklarieren:
1
static volatile int DURCHLAUFE=100; //sonst 255
2
static int DURCHLAUFEG=100; 
3
static volatile char SCHRITT=1;
4
static volatile char enablex=0;
5
static volatile char enabley=0;
6
static volatile int SCHRITTG=50;
7
static volatile char richtungx;
8
static volatile char richtungy;
9
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)

von Oliver (Gast)


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

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.