Forum: Mikrocontroller und Digitale Elektronik Variablenänderung erkennen


von Patrick R. (pat711)


Lesenswert?

Hallo zusammen,
ich haebe derzeit das Problem, dass ich möglichst exakt an dem Punkt, an 
welchem eine Variable ihren Wert ändert einen ADC - Wert aufnehmen muss.
Diese Variable hat außerdem noch einen Einfluss auf einen Ausgabepin und 
hat nur die Zustände eins und Null.
Die Variable wird durch eine Interruptroutine eines Timers geändert.
Mein bisheriger Ansatz ist folgender:
1
sens[0] = 0;
2
sens[1] = 0;
3
sens[2] = 0;
4
5
if (freq == 1)
6
{
7
  while(freq == 1)
8
  {}
9
}
10
while (freq == 0)
11
{}
12
for (counter = 0; counter < 3; counter ++)
13
{
14
  abfragen(counter);
15
  sens[counter] = result;
16
}
17
min[0] = sens[0];
18
min[1] = sens[1];
19
min[2] = sens[2];
20
    
21
while (freq == 1)
22
{}
23
for (counter = 0; counter < 3; counter ++)
24
{
25
  abfragen(counter);
26
  sens[counter] = result;
27
}
28
max[0] = sens[0];
29
max[1] = sens[1];
30
max[2] = sens[2];
31
32
...
33
34
set_cursor(0,2);
35
lcd_string("                ");
36
    
37
set_cursor(10,2);
38
lcd_string("    ");
39
char Buffer[20];
40
itoa(delta[0], Buffer, 10);
41
set_cursor(1,2);
42
lcd_string( Buffer );
43
44
itoa(max[0], Buffer, 10);
45
set_cursor(6,2);
46
lcd_string( Buffer );
47
48
itoa(min[0], Buffer, 10);
49
set_cursor(10,2);
50
lcd_string( Buffer );
51
abfragen(0);
52
long_delay(200);

Der Teil den ich durch ... erstezt habe funktioniert einwandfrei und die 
LCD - Ausgabe unten auch, das habe ich mit älteren Versionen getestet, 
welche noch nicht diesen Wechsel benötigten.

Das Problem ist nun, dass der Controller irgendwo hängen bleibt, er 
arbeitet das Programm mindestens bis zu der ersten beschriebenen Zeile 
ab kommt aber nie bei der LCD - Ausgabe an. Der Takt wird auch an dem 
Pin ausgegeben, es kann also nicht an der Variablen liegen.

Controller: ATmega8
Verw. Timer: 2
Takt: 16MHz


Mfg Pat

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Es macht keinen Spaß, das zu debuggen, weil es 1. Spagetticode und 2. 
ein Codefetzen ohne Anfang und Ende ist. Deshalb lasse ich das.

Ich würde eine kleine Hauptschleife bauen und darin die betreffende 
Variable abfragen.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
volatile uint8_t beobachtete_variable;
5
6
void arbeitsroutine(void)
7
{
8
  // Portpin schalten
9
10
  // ADC-Messung ausführen
11
12
  // LCD-Ausgabe machen
13
}
14
15
int main(void)
16
{
17
  ddr_einstellen();
18
  timer2_initialisieren();
19
  sei();
20
21
  while(1)
22
  {
23
    if ( beobachtete_variable == 1 )
24
    {
25
      arbeitsroutine();
26
      beobachtete_variable = 0; // Alles abgearbeitet
27
    }
28
  }
29
}

Dabei ist darauf zu achten, dass die arbeitsroutine() beendet sein muss, 
wenn die nächste Änderung der beobachteten_variable passiert. Das kann 
je nach Frequenz deines Timer2 und der Änderungsfrequenz der 
beobachteten_variable sehr kritisch sein oder man kann es entspannt 
angehen.

Um herauszufinden ob man sich Sorgen machen muss, kann man in der Timer2 
ISR seinerseits die beobachtete_variable prüfen. Wenn in der Timer2 ISR 
eine Änderung notwendig wird, aber die beobachtete_variable vom 
vorherigen Aufruf noch auf 1 steht, dann ist ein Zeitkonflikt 
aufgetreten, Das kann man zählen und entsprechend die arbeitsroutine() 
optimieren.

Optimierungspotential sehe ich bei:

* der ADC-Messung. Die ADC-Messung selbst braucht eine gewisse Zeit. 
Wenn Mittelwerte gebildet werden, umso länger.

Man kann diese Zeit verkürzen, wenn die ADC-Initialisierung einmalig 
vorab gemacht wird und die Referenz etc. nicht umgeschaltet wird. Auch 
kann man sich überlegen die ADC Messung bereits in der Timer2 ISR zu 
starten und in der Arbeitsroutine nur noch kurz Ergebnis warten zu 
müssen.

* die LCD-Ausgabe.

Man kann diese Zeit verkürzen, indem man einen Teil der Ausgabe bereits 
macht, wenn die beobachtete_variable noch nicht geändert ist. Wenn die 
Änderung kommt, setzt man nur noch den eigentlichen Wert in die mit 
vorbereitete LCD Anzeige ein.

* dem Schalten des Portpins.

Das kann man ebenfalls in der Timer2 ISR erledigen, wenn man den Inhalt 
der beobachtete_variable ändert. Wenn die Änderung des Portpins 
besonders wichtig ist, könnte man den auch ändern, wenn die 
arbeitsroutine() unterbrochen wurde.

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.