Forum: Mikrocontroller und Digitale Elektronik Atmega8 und Interrupts


von Jochen K. (jokunz)


Angehängte Dateien:

Lesenswert?

Hallo,

Mit meinem kleinen Beispielcode im Anhang stehe ich vor einem Rätsel.
Ich möchte u.A. drei Analogwerte einlesen und einen davon über die RS232 
weitersenden, dies zyklisch per Timerinterrupt gesteuert, also ständig 
einlesen, rumrechnen und ca alle Sekunde einmal den Analogwert senden.

Lese ich in der Interruptroutine den AD-Wert zum Senden ein, habe ich 
kein Problem.
Aber sobal ich in der main-loop die Werte einlese und im 
Interrupthandler versenden möchte, geht es nicht.
Es sieht fuer mich so aus, als ob der main "nicht abgearbeitet" wird, 
irgendwie ein irq-vektor/reset  das Programm wieder neu startet.
Ich sehe den Denkfehler aber nicht.

liebe Grüße
jochen

von Stefan E. (sternst)


Lesenswert?

Ich habe mir den Code jetzt nicht im Detail angesehen, aber ein CTRL-F 
fördert kein "volatile" zu Tage. Das wird das Problem sein.
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Datenaustausch_mit_Interrupt-Routinen

von STK500-Besitzer (Gast)


Lesenswert?

>cli();      // Interrupts nicht zulassen

Sinnfrei innerhalb einer ISR, da dort sowieso keine anderen Interrupts 
zugelassen werden.
1
SIGNAL (SIG_OVERFLOW0)
2
{
3
  cli();      // Interrupts nicht zulassen << sinnfrei
4
5
    takt--;
6
7
  if (takt == 0) {
8
    takt = TIMERVALUE;
9
      ucSend = 1;
10
11
Wie lange dauert der ganze Spaß hier?   
12
    UARTPutChar(0x01);
13
    // UARTPutChar(readAnalogValues(0));  // vor Rechen
14
    UARTPutChar(readAnalogValues(1));  // hinter Rechen
15
//    UARTPutChar(ucAnalogValues[1]);
16
    UARTPutChar(PIND & 0xfc);
17
    // UARTPutChar(readAnalogValues(2));  // Einsteller
18
    UARTPutChar(0xff);
19
20
    }
21
  sei();        << wenn das Sperren schon sinnfrei ist, braucht man sich um das Freigeben auch nicht mehr kümmern...
22
23
}


Ich würde sagen, dass deine ISR viel zu langsam ist.

Weiterhin sollte man den ADC nur ein Mal initialisieren und den ersten 
Messwert verwerfen. Die darauffolgenden Messwerte sind dann auch erste 
richtig gültig.

von STK500-Besitzer (Gast)


Lesenswert?

"takt" sollte wirklich noch volatile deklariert werden!

von Stefan E. (sternst)


Lesenswert?

Warum? "takt" wird ausschließlich im Interruptcode verwendet.
"ucAnalogValues" muss aber volatile sein.

von Maddin (Gast)


Lesenswert?

In der main-loop belädst Du das Array:
>ucAnalogValues[i]= readAnalogValues(i);
Der Inhalt des Arrays wird aber nirgendwo verwendet...

Dafür wartet die ISR
>SIGNAL (SIG_OVERFLOW0)
aktiv auf ADC-Ergebnisse (4x in readAnalogValues(unsigned char ucMux)):
1
for (i=0;i<4;i++) {
2
    ADCSRA |= (1<<ADSC);
3
  while (ADCSRA&(1<<ADSC)) {}

Aktives Warten auf ADC-Ergebnisse innerhalb einer Timer-ISR finde ich...
...unkonventionell.

von Stefan E. (sternst)


Lesenswert?

Maddin wrote:
> In der main-loop belädst Du das Array:
>>ucAnalogValues[i]= readAnalogValues(i);
> Der Inhalt des Arrays wird aber nirgendwo verwendet...

Doch:
//    UARTPutChar(ucAnalogValues[1]);
Die auskommentierte Zeile gehört zu dem "funktioniert nicht"-Fall.

von Maddin (Gast)


Lesenswert?

>Die auskommentierte Zeile gehört zu dem "funktioniert nicht"-Fall.
OK, sorry...
Noch eine Bemerkung zum Datenaustausch:
Wenn das Array auf "Tasklevel" (main loop) gegeschrieben und auf 
Interrupt-Level gelesen wird, muß der Schreibzugriff in "main" geschützt 
werden (d.h. unter Interruptsperre), damit im Interrupt keine halb 
geschriebenen Daten an die UART gesendet werden...

von Stefan E. (sternst)


Lesenswert?

Sorry, aber ich denke nicht, dass das hier zwingend nötig ist.
Wie kann denn ein einzelnes unsigned char "halb geschrieben" sein?

von Maddin (Gast)


Lesenswert?

Ahh, ich glaube, es ist Zeit fürs Bett.
Ich bin von 10bit-Werten ausgegangen, obwohl die Fkt. ja nur 8bit vom 
ADC verwendet und
1
unsigned char
 zurückgibt.

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.