Forum: Mikrocontroller und Digitale Elektronik atmega- Programm läuft nicht immer richtig


von Kalle K. (kalledk)


Lesenswert?

Hi,

habe ein Programm für einen Atmega32 geschrieben, was eigentlich nur 
zwei LEDs in drei unterschiedlichen Modi(Timer2) zum Blinken bringen 
soll. Diese Modi sollen dann über drei Schalter, die an PortA 
angeschlossen sind eingestellt werden. Komisch ist nur, dass alles 
korrekt funktioniert, solange ich die Zeilen für den LCD Display nicht 
auskommentiere, wenn diese auskommentiert sind blinken die LEDs nur im 
ersten Modus und lassen sich nicht mehr umstellen. Die Taster werden 
aber immer noch erkannt da die LED an PA7 aufleuchtet. Es scheinen nur 
Veränderungen innerhalb der Timer nicht mehr zu funktionieren.

Weiß vielleicht einer von euch, wo der Fehler liegen könnte?

Ich programmiere mit dem Programmers Notepad von WinAVR und übertrage 
den Code mit PonyProg.

Vielen Dank schonmal

Mein C-Code:
1
 
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include "lcd.h"
5
#include <util/delay.h>
6
#include <stdint.h> 
7
8
int i=1;
9
int max=100;
10
int on=100;
11
int state=1;
12
13
int time=0;
14
15
int t1=0;
16
int wait=0;
17
int wait1=0;
18
int mode=0;
19
20
char buffer[7];
21
 
22
int main(void)
23
{
24
25
 // lcd_init(LCD_DISP_ON);
26
 // lcd_clrscr();
27
28
  DDRA=0xF0;
29
  PORTA=0x0F;
30
31
  TCCR0 = (1<<CS00);
32
  TCCR2 = (1<<CS22) | (1<<CS20);
33
34
35
  TIMSK |= (1<<TOIE0) | (1<<TOIE2);
36
 
37
38
  sei();
39
40
 
41
  while(1)
42
  {
43
 
44
  // lcd_home();
45
    // itoa(mode ,buffer, 10);
46
  // lcd_puts("Mode: ");
47
    // lcd_puts(buffer);
48
   
49
   if(!(PINA & ( 1 << PA1 )))
50
  {
51
  mode=0;
52
  PORTA |= (1 << PA7);
53
  }
54
55
  else if(!(PINA & ( 1 << PA2 )))
56
  {
57
  mode=1;
58
  PORTA |= (1 << PA7);
59
  }
60
  
61
  else if(!(PINA & ( 1 << PA3 )))
62
  {
63
  mode=2;
64
  PORTA |= (1 << PA7);
65
  }
66
  else
67
  {
68
   PORTA &= ~(1 << PA7);
69
  }
70
   
71
  }
72
}
73
 
74
 
75
ISR (TIMER0_OVF_vect)
76
{
77
78
  if(i<=on)
79
  {
80
   PORTA |= (1 << PA4);
81
    
82
  }
83
  else if(i>on)
84
  {
85
   PORTA &= ~(1 << PA4);
86
  }
87
  
88
  if(i>=max)
89
  {
90
   i=0;
91
  }
92
  
93
  i++;
94
  
95
  
96
  if(time>=500)
97
  {
98
    if(on>0 && state==1)
99
    {
100
    on--;
101
    if(on<=0)
102
    {
103
    state=0;
104
    }
105
    }
106
  
107
    if(on<max && state==0)
108
    {
109
    on++;
110
    if(on>=max)
111
    {
112
    state=1;
113
    }
114
    }
115
   time=0; 
116
  }
117
  
118
 time++;  
119
 TCNT0=254;
120
121
122
 
123
}
124
125
ISR (TIMER2_OVF_vect)
126
{
127
  if(mode==2)
128
  {
129
 
130
  if(t1%2==0 && t1<4)
131
  {
132
    PORTA |= (1 << PA5);
133
    t1++;
134
  }
135
  else if(t1%2==1 && t1<4)
136
  {
137
    PORTA &= ~(1 << PA5);
138
    t1++;
139
  }
140
   
141
  if(t1%2==0 && t1>=4)
142
  {
143
    PORTA |= (1 << PA6);
144
    t1++;
145
  }
146
  else if(t1%2==1 && t1>=4)
147
  {
148
    PORTA &= ~(1 << PA6);
149
    t1++;
150
    if(t1>=8)
151
    {
152
    t1=0;
153
    }
154
  }
155
  }
156
157
  else if(mode==1)
158
  {
159
  
160
   if(wait >= 3)
161
    {
162
     wait=0;
163
    if(t1%2==0 && t1<4)
164
    {
165
      PORTA |= (1 << PA5);
166
      t1++;
167
    }
168
    else if(t1%2==1 && t1<4)
169
    {
170
      PORTA &= ~(1 << PA5);
171
      t1++;
172
    }
173
   
174
    else if(t1%2==0 && t1>=4)
175
    {
176
      PORTA |= (1 << PA6);
177
      t1++;
178
    }
179
    else if(t1%2==1 && t1>=4)
180
    {
181
      PORTA &= ~(1 << PA6);
182
      t1++;
183
      if(t1>=8)
184
      {
185
      t1=0;
186
      }
187
    }
188
    }
189
    wait++;
190
  }
191
  
192
  else if(mode==0)
193
  {
194
  
195
   if(wait >= 3)
196
    {
197
     wait=0;
198
     
199
     if(t1==0 && wait1 <=2)
200
    {
201
     wait1++;
202
    }
203
    
204
    else if(t1%2==0 && t1<4)
205
    {
206
      PORTA |= (1 << PA5);
207
      t1++;
208
    }
209
    else if(t1%2==1 && t1<4)
210
    {
211
      PORTA &= ~(1 << PA5);
212
      t1++;
213
      wait1=0;
214
    }
215
   
216
    else if(t1==4 && wait1 <=2)
217
    {
218
     wait1++;
219
    }
220
   
221
    else if(t1%2==0 && t1>=4)
222
    {
223
      PORTA |= (1 << PA6);
224
      t1++;
225
    }
226
    else if(t1%2==1 && t1>=4)
227
    {
228
      PORTA &= ~(1 << PA6);
229
      t1++;
230
      if(t1>=8)
231
      {
232
      t1=0;
233
      wait1=0;
234
      }
235
    }
236
    }
237
    wait++;
238
  }
239
  
240
  
241
  TCNT2=0;
242
}

von Peter II (Gast)


Lesenswert?


von Kalle K. (kalledk)


Lesenswert?

Vielen Dank für deine Antwort.

Sollte dann eigentlich alle Variablen, die in Timern genutzt werden 
volatile sein oder nur die, die Später extern verändert werden?

von Sandro (Gast)


Lesenswert?

Alle, die in Interruptserviceroutinen UND dem Hauptprogramm verwendet 
werden. Du vermeidest damit, dass die Variable vom Compiler wegoptimiert 
wird.

Allgemein solltest du Variablen mit einem Wertebereich von 0 bis 3 auch 
nicht als int deklarieren. Speicher ist wertvoll und ein char tut es an 
dieser Stelle auch. Wenn du Variablen, die größer sind als ein Byte, 
auch in einer ISR verwenden willst, solltest du im Hinterkopf haben, 
dass das Lesen und Schreiben einer solchen Variable nicht atomar ist. 
Das heisst dein 8-bit Prozessor bearbeitet zunächst das erste Byte und 
dann das Zweite, kann jedoch nach dem ersten Byte durch einen Interrupt 
unterbrochen werden. Wenn in der ISR genau diese Variable geändert wird, 
hast du möglicherweise nach dem Rücksprung ins Hauptprogramm dort einen 
falschen Wert gelesen, der sich aus einem alten ersten Byte und einem 
neuen zweiten Byte zusammensetzt. Man verhindert das durch kurzzeitiges 
deaktivieren der Interrupts.
Das ist in deiner Anwendung hier nicht weiter von Bedeutung, aber 
vielleicht in der Nächsten.

von Kalle K. (kalledk)


Lesenswert?

Das Programm läuft jetzt ohne Probleme auf einem Atmega32(mit der 
Änderung: volatile int mode=0;).

Ich wollte das gleiche Programm auf einen Atmega16 übertragen aber es 
funktioniert scheinbar nichts was innerhalb der Timer steht. Nur was 
innerhalb der While Schleife ist wird richtig ausgeführt, dass aber auch 
nur solange die Zeilen für den LCD Display auskommentiert sind.

Muss ich bei dem Atmega16 etwas anders machen als bei dem Atmega32?

von ... (Gast)


Lesenswert?

Hast du bei beiden die gleiche Einstellung der fuses beachtet?

von Kalle K. (kalledk)


Lesenswert?

Die Einstellungen sollte bei beiden gleich sein, da ich einfach nur den 
Atmega32 gegen einen Atmega16 auf dem Programmier Board ausgetauscht 
habe und das gleiche Programm dann mit PonyProg übertragen habe ohne 
etwas an den Fuses zu ändern.

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.