Forum: Mikrocontroller und Digitale Elektronik MSP430F2012 usigned long Timertakte Zaehlen


von Sebastian (sepp1985)


Lesenswert?

Hallo zusammen,

ich bin gerade dabei ein Relais in eimen zyklisch Zeitabstand zu 
schalten.
Hierzu zähle ich Timerinterruptimpulse. Als Zählvariable verwende ich 
eine unsigned Long Variable. Hierbei gibt es aber Probleme.
Wenn ich zwischen 5m-30m Zähle gibt es keine Probleme (Abweichung 
<100ms).
Bei 4h funktioniert es nicht. Hier schaltet das Relais erst nach 8h.
Den Code habe ich etwas gekürzt, damit es nicht so überfrachtet ist.
rest_spuelzeit wird über einen Timerinterrupt alle 100ms decrementiert.
zeit_nicht_gespuelt wird über einen Timerinterrupt alle 100m 
incrementiert.

Wenn ich die Zeiten 3m-30m einstelle, dann funktioniert dies.
max_Zwangsspuelzeit=18000L;
min_Zwangsspuelzeit=1800L;

Bei 25m-250m klappt es mit 25m aber die 250m funktionieren nicht
max_Zwangsspuelzeit=150000L;
min_Zwangsspuelzeit=15000L;

Hierbei verhält es sich, als wäre die Zähler Variable irgendwann 
negativ.
Wenn ich das Poti nach 4h auf 0 drehe, dann bleibt das Relais trotzem 
aus.
Gibt es bei Code Composer Studio irgendwelche Bugs, die dieses erklären 
würden?


Festlegung des Intervalls: P2 wird über ein Poti verstellt. Ist getestet 
und liefert Werte zwischen 0-1023.
1
intervall_zwangsspuelung=(((max_Zwangsspuelzeit-min_Zwangsspuelzeit) * P2value)/1023L)+min_Zwangsspuelzeit;

Abfrage ob die Zeit wo nicht gespült wurde, größer als der Intervall 
ist.
1
if(zeit_nicht_gespuelt>intervall_zwangsspuelung)
2
{
3
   rest_spuelzeit = 300L;
4
}

Wenn Spuelzeit großer 0, dann soll der Ausgang geschaltet werden.
1
if (rest_spuelzeit>0)
2
          {
3
            P2OUT |= 0x40;
4
            zeit_nicht_gespuelt=0L;
5
          }
6
          else
7
          {
8
            P2OUT &= ~0x40;
9
            rest_spuelzeit=0L;
10
          }

Vielen Dank im voraus.
Sebastian

von Falk B. (falk)


Lesenswert?

Sebastian R. schrieb:
> Hallo zusammen,
>
> ich bin gerade dabei ein Relais in eimen zyklisch Zeitabstand zu
> schalten.
> Hierzu zähle ich Timerinterruptimpulse. Als Zählvariable verwende ich
> eine unsigned Long Variable. Hierbei gibt es aber Probleme.

Hast du das Thema volatile und atomar beachtet? Siehe Interrutpt.

> Bei 4h funktioniert es nicht. Hier schaltet das Relais erst nach 8h.
> Den Code habe ich etwas gekürzt, damit es nicht so überfrachtet ist.

Irrtum! Deine Fragmente sind nichtssagend, der Fehler steckt oft nicht 
im gezeigten Ausschnitt.

Zeige uns deinen GESAMTEN Quelltext als Anhang.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Sebastian R. schrieb:
> Den Code habe ich etwas gekürzt, damit es nicht so überfrachtet ist.
Du solltest einen Code posten, der den Fehler zeigt. Dazu solltest du 
den Code im Idealsfall auf einen "Dreizeiler" zusammenkürzen, also den 
kürzestmöglichen Code, der den Fehler noch zeigt.

Der Witz dabei: ganz oft findet man den Fehler bei deratigem Vorgehen 
schon selber.

> Hierzu zähle ich Timerinterruptimpulse.
Womit? Was ist die Zählervariable?

Warum nachst du es nicht so wie die Arduinos beim millis() Zähler? Denn 
die zeigen, wie Zeitvergleiche auch mit einem Zählerüberlauf zuverlässig 
funktionieren: der millis-Zähler läuft dauernd hoch, die zugehörigen 
Vergleichswerte sind Zeitstempel dieses millis-Zählers und die Differenz 
zwischen beiden ist die inzwischen abgelaufene Zeit. Und der Überlauf 
des millis-Zählers wird durch eine gechickte Berechnung im Vergleich 
elegant abgefangen:
- https://electric-junkie.de/2020/08/arduino-millis-anstatt-von-delay

: Bearbeitet durch Moderator
von Sebastian (sepp1985)


Lesenswert?

Ich hab gerade paar Sachen rausgelöscht.
ADC ist uninteressant hier habe ich einfach den vollausschlag von 1023 
eingegeben.
Ich habe volatile beachtet, aber nicht atomar. Dieses sollte aber 
eigentlich keinen effekt haben oder?

Die Bedingung sollte ja normalerweise, wenn P2value auf 0 gedreht wird.

zeit_nicht_gespuelt>intervall_zwangsspuelung
1
#include <msp430.h>
2
#include <msp430f2012.h>
3
void io_init(void);
4
5
volatile unsigned long rest_spuelzeit;
6
volatile unsigned long zeit_nicht_gespuelt;
7
8
unsigned int P2value = 0;
9
10
int main(void)
11
{
12
    int jumper_Spuelzeit;
13
   
14
    volatile unsigned long intervall_zwangsspuelung;
15
    volatile unsigned long max_spuelzeit;
16
    volatile unsigned long min_Zwangsspuelzeit;
17
    volatile unsigned long max_Zwangsspuelzeit;
18
19
    WDTCTL = WDTPW + WDTHOLD;               
20
    //IO initialisieren
21
    io_init();
22
23
    //Variablen initialisieren
24
    rest_spuelzeit=0L;
25
    zeit_nicht_gespuelt=0L;
26
    intervall_zwangsspuelung=150000L;
27
    P2value=1023;
28
29
  __enable_interrupt();                    
30
  TACCR0 = 12500;                            
31
  TACCTL0 |= CCIE;                          
32
  TACTL = TASSEL_2 | MC_1 | ID_3;          
33
34
  _BIS_SR(GIE);                 // Global interrupt enable
35
36
  while (1)
37
      {
38
          //Eingaenge Einlesen und mappen
39
          jumper_Zwangsspuelen = ((0xC0 & (~P1IN))>>6);
40
41
          if(jumper_Zwangsspuelen != 0x03)
42
              {
43
                  max_Zwangsspuelzeit=150000L;
44
                  min_Zwangsspuelzeit=15000L;                        
45
                  intervall_zwangsspuelung=(((max_Zwangsspuelzeit-min_Zwangsspuelzeit) * P2value)/1023L)+min_Zwangsspuelzeit;
46
              }
47
          else
48
          {
49
              zeit_nicht_gespuelt = 0L;
50
              intervall_zwangsspuelung = 0L;
51
          }
52
 
53
          if (zeit_nicht_gespuelt>intervall_zwangsspuelung)
54
                   {
55
                     if (rest_spuelzeit==0L)
56
                     {                   
57
                       rest_spuelzeit=300L;
58
                     }
59
                   }
60
61
          if (rest_spuelzeit>0L)
62
          {
63
            P2OUT |= 0x40;
64
            zeit_nicht_gespuelt=0L;
65
          }
66
          else
67
          {
68
            P2OUT &= ~0x40;
69
            rest_spuelzeit=0L;
70
          }
71
      }
72
}
73
74
void io_init(void)
75
{
76
    P2SEL &= ~0x40;
77
    P2DIR |= 0x40;                           
78
    P2OUT &= ~0x40;                           
79
80
    P1SEL |= 0x03;                            
81
    P1DIR &= ~0xEB;   //E8                        
82
    P1REN |= 0xE8;                           
83
    P1OUT |= 0xE8;                            
84
}
85
86
87
#pragma vector=TIMER0_A0_VECTOR
88
__interrupt void ta0_isr(void)
89
{
90
  //Restspuelzeit reduzieren
91
  if (rest_spuelzeit>0L)
92
      {
93
          rest_spuelzeit-=1L;
94
      }
95
  zeit_nicht_gespuelt +=1L;
96
}

von Peter D. (peda)


Lesenswert?

Sebastian R. schrieb:
> Ich habe volatile beachtet, aber nicht atomar. Dieses sollte aber
> eigentlich keinen effekt haben oder?

Nun 32Bit dürfte auf nem 16Bitter wohl 2 Zugriffe benötigen, wo 
natürlich ein Interrupt zwischen grätschen kann.
Auch lustiges mehrfaches Lesen und Setzen im Main ist zutiefst 
unbestimmt. Die komplette Sequenz von ersten bis zum letzten Zugriff 
müßte dann atomar sein.

Ich setze mir daher im Interrupt nur ein 100ms Flag, was dann an 
kontrollierter Stelle im Main die Variablen ändert.

von Sebastian (sepp1985)


Lesenswert?

Peter D. schrieb:
> Sebastian R. schrieb:
>> Ich habe volatile beachtet, aber nicht atomar. Dieses sollte aber
>> eigentlich keinen effekt haben oder?
>
> Nun 32Bit dürfte auf nem 16Bitter wohl 2 Zugriffe benötigen, wo
> natürlich ein Interrupt zwischen grätschen kann.
> Auch lustiges mehrfaches Lesen und Setzen im Main ist zutiefst
> unbestimmt. Die komplette Sequenz von ersten bis zum letzten Zugriff
> müßte dann atomar sein.
>
> Ich setze mir daher im Interrupt nur ein 100ms Flag, was dann an
> kontrollierter Stelle im Main die Variablen ändert.

Also das der Interrupt zwischen der Bearbeitung des 32Bit Wertes 
aufgerufen wird, kann ich glauben.
Das es für einen Zyklus dann ggf. falsche Werte hat auch, aber 
spätestens bei der nächsten Abarbeitung müsste der Zähler wieder 
synchron sein.
Es ist ja nur ein lesender Zugriff an der Stelle. Der Schreibzugriff 
findet ja nicht statt.

Ich werde mein Programm kurz abändern und ein Flag benutzen um die Werte 
zu bearbeiten. Das Programm ist ja schnell genug und wird nicht länger 
als 100ms brauchen. Dementsprechen wird es zu keinem doppelten Aufruf 
kommen.

von Falk B. (falk)


Lesenswert?

Sebastian R. schrieb:
> Ich hab gerade paar Sachen rausgelöscht.

Ob das so gut ist?

> ADC ist uninteressant hier habe ich einfach den vollausschlag von 1023
> eingegeben.

Ist der Effekt noch da?

> Ich habe volatile beachtet, aber nicht atomar. Dieses sollte aber
> eigentlich keinen effekt haben oder?

Oder.

Einfach will alles volatile zu deklarieren ist Unsinn. Nur Variablen, 
welche sowohl in einer ISR als auch im Hauptprogramm verwendet werden.

> Die Bedingung sollte ja normalerweise, wenn P2value auf 0 gedreht wird.
>
> zeit_nicht_gespuelt>intervall_zwangsspuelung
> #include <msp430.h>
> #include <msp430f2012.h>
> void io_init(void);
> volatile unsigned long rest_spuelzeit;
> volatile unsigned long zeit_nicht_gespuelt;
> unsigned int P2value = 0;
> int main(void)
> {
>     int jumper_Spuelzeit;
>
>     volatile unsigned long intervall_zwangsspuelung;
>     volatile unsigned long max_spuelzeit;
>     volatile unsigned long min_Zwangsspuelzeit;
>     volatile unsigned long max_Zwangsspuelzeit;

Die volatile sind hier Unsinn, auch wenn sie nicht schaden.

Du greifst auf rest_spuelzeit und zeit_nicht_gespuelt mehrfach in deinem 
Hauptprgramm zu, außerdem in der ISR. Deine Hauptprogramm rast wie ein 
Wahnsinniger ohne Bremse im Kreis und wird schätzungsweise 10.000mal und 
mehr pro Sekunde ausgeführt. Die Chance, einen nichtatomaren 
Zugriffskonflikt zu erzeugen ist sehr hoch, um nicht zu sagen sicher.
Sowas macht man nicht.
Peter hat das deutlich bessere Konzept genannt. Der Timer aktiviert alle 
x ms ein Flag, welches in der Hauptschleife abgefragt und ausgewertet 
wird. Dann wird deine Funktion EINMAL aufgerufen. Dann kann sie CPU 
sonstwas machen oder wieder schlafen gehen. Damit vermeidet man u.a., 
daß in der ISR große Variablen verändert werden müssen. Dein Programm 
ist soooo langsam, daß das nicht nötig ist.

Alternativ muss der Durchlauf deines Programmabschnitts atomar gemacht 
werden, dann ist es sicher. Siehe Interrupt, jetzt mit korrekter 
Schreibweise ;-)

von Falk B. (falk)


Lesenswert?

Die Einrückungen deines Programm sind sehr schlecht, vermutlich TABs, 
welche hier in der Forumssoftware vermurkst wurden. Formatiere die 
Einrückungen sauber mit Leerzeichen.

          if (rest_spuelzeit>0L)
          {
            P2OUT |= 0x40;
            zeit_nicht_gespuelt=0L;
          }
          else
          {
            P2OUT &= ~0x40;
            rest_spuelzeit=0L;
          }

Sowas ist Unsinn. Im else Zweig ist rest_spuelzeit == 0, denn das wurde 
in der Bedingung geprüft. Das nochmal zuzuweisen ist Unsinn und 
irreführend.

von Loco M. (loco)


Lesenswert?

Was ich irreführend finde, dass überall im Program 'signed long' Werte 
benutzt werden um 'unsigned long' Variablen zu initialisieren.
Z.B. 'rest_spuelzeit=300L' anstelle von 'rest_spuelzeit=300UL'.

Hast du dir die Compiler Warnings mal genauer angeschaut?

: Bearbeitet durch User
von Sebastian (sepp1985)


Lesenswert?

Loco M. schrieb:
> Was ich irreführend finde, dass überall im Program 'signed long' Werte
> benutzt werden um 'unsigned long' Variablen zu initialisieren.
> Z.B. 'rest_spuelzeit=300L' anstelle von 'rest_spuelzeit=300UL'.
>
> Hast du dir die Compiler Warnings mal genauer angeschaut?

Ich habe den Code übernommen und dort waren die schon mit einem L 
initialisiert. Es gibt keine Warnung, sonst hätte ich diese schon 
geschrieben.

Mein Fehler war definitiv, dass ich keinen Atomaren Datenzugriff 
verwendet habe.
Ich verwende jetzt ein Timepulse Flag und ich schalte Global die 
Interrupts aus, wenn ich auf Daten worauf die Interupts schreiben.
Test lasse ich gerade laufen.

Die Unordnung im Programm ist ein wenig der Versuche geschuldet.
Ich hatte mit dem Volatile schon gelesen gehabt und habe irgendwann 
gesagt, driss drauf lieber vor allem als irgendwo was zu vergessen.

Das gleiche gilt dem "L".

Kann man beim Code Composer Studio die Einrückungen Global auf 
Leerzeilen stellen?

Obwohl ich mit Code Composer Studio absolut nicht zufrieden bin.
Könnt ihr einen anderen IDE bzw. Compiler empfehlen?
Ich würde sonst schauen ob ich nicht auf Eclispe gehe.

Macht es Sinn die stdint.h zuverwenden und mit den int32_t generell zu 
arbeiten? Prinzipiell ist es ja nichts anderes als meine declarationen.

von Falk B. (falk)


Lesenswert?

Sebastian R. schrieb:
> Mein Fehler war definitiv, dass ich keinen Atomaren Datenzugriff
> verwendet habe.
> Ich verwende jetzt ein Timepulse Flag und ich schalte Global die
> Interrupts aus, wenn ich auf Daten worauf die Interupts schreiben.
> Test lasse ich gerade laufen.

Zeig mal deinen Quelltext.

von Falk B. (falk)


Lesenswert?

Sebastian R. schrieb:
> Macht es Sinn die stdint.h zuverwenden und mit den int32_t generell zu
> arbeiten?

Ja sicher, die gibt es seit 25 Jahren in C99!

> Prinzipiell ist es ja nichts anderes als meine declarationen.

Ja, nur allgemeingültiger, kürzer und eindeutiger.

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

Siehe Anhang, etwa so. Man muss nicht immer die Endung L hinschreiben. 
Das braucht man nur in bestimmten Situationen, wo man ein Formel 
hinschreibt und möchte, daß die mit 32 Bit gerechnet wird. Für einfache 
Zuweisungen braucht man das nicht.

von Sebastian (sepp1985)


Lesenswert?

Hallo Zusammen,
ich habe noch etwas weiter getestet. An dem Interrupt liegt es definitiv 
nicht, aber ich habe das trotzdem alles Atomar getrennt.
Wenn ich mit kleinen Zahlen arbeite funktioniert es, aber sobald ich 
z.B. 18000 als intervall verwende geht es nicht mehr.

Könnt ihr ein gutes Board inkl. Programmer fürs debuggen empfehlen?


Mit 1800UL klappt es:
1
intervall_zwangsspuelung = 1800UL;

Wenn ich das Poti direkt mit einbinde, dann kommt die passende Zeit.
1
intervall_zwangsspuelung = ((1800UL*(uint32_t)P2value/1023UL)+200UL);

Mit 18000UL klappt es nicht
1
intervall_zwangsspuelung = 18000UL;
1
if((uint32_t)zeit_nicht_gespuelt > (uint32_t)intervall_zwangsspuelung)
2
{
3
 if (rest_spuelzeit==0)
4
 {
5
  rest_spuelzeit=100UL; 
6
 }
7
}

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Sebastian R. schrieb:
> 1023UL
Das ist falsch. Richtig wären 1024.

> Aber ich habe das trotzdem alles Atomar getrennt.
>   rest_spuelzeit=100UL;
Das hier ist aber noch nicht atomar. Da kann irgendwas in die Zuweisung 
reinfunken.

> Mit 1800UL klappt es
>
> Mit 18000UL klappt es nicht
Mach mal eine sukzessive Approximation(**) an den Wert, der grade noch 
geht und den, mit dem es dann nicht mehr geht. Würde mich nicht arg 
wundern, wenn da 16383 und 16384 (oder irgendeine andere Zweierpotenz 
zwischen 1800 und 18000) herauskommen würden.

(**) nächster Test mit (18000+1800)/2 = 9900.
Wenn der Wert 9900 noch funktioniert, dann mit (18000+9900)/2 = 13950 
weiter.
Wenn der 9900 nicht funktioniert, dann mit (9900+1800)/2 = 5850 weiter.
Und dann immer weiter mit dem Mittelwert bis hin zum Übergang von "gut 
nach schlecht".

Sebastian R. schrieb:
> Aber ich habe das trotzdem alles Atomar getrennt.
>
>   rest_spuelzeit=100UL;
Das hier ist aber noch nicht atomar. Da kann irgendwas in die Zuweisung 
reinfunken.

: Bearbeitet durch Moderator
von Sebastian (sepp1985)


Lesenswert?

Lothar M. schrieb:
> Sebastian R. schrieb:
>> 1023UL
> Das ist falsch. Richtig wären 1024.
>
>> Aber ich habe das trotzdem alles Atomar getrennt.
>>   rest_spuelzeit=100UL;
> Das hier ist aber noch nicht atomar. Da kann irgendwas in die Zuweisung
> reinfunken.
>
>> Mit 1800UL klappt es
>>
>> Mit 18000UL klappt es nicht
> Mach mal eine sukzessive Approximation(**) an den Wert, der grade noch
> geht und den, mit dem es dann nicht mehr geht. Würde mich nicht arg
> wundern, wenn da 16383 und 16384 (oder irgendeine andere Zweierpotenz
> zwischen 1800 und 18000) herauskommen würden.
>
> (**) nächster Test mit (18000+1800)/2 = 9900.
> Wenn der Wert 9900 noch funktioniert, dann mit (18000+9900)/2 = 13950
> weiter.
> Wenn der 9900 nicht funktioniert, dann mit (9900+1800)/2 = 5850 weiter.
> Und dann immer weiter mit dem Mittelwert bis hin zum Übergang von "gut
> nach schlecht".
>
> Sebastian R. schrieb:
>> Aber ich habe das trotzdem alles Atomar getrennt.
>>
>>   rest_spuelzeit=100UL;
> Das hier ist aber noch nicht atomar. Da kann irgendwas in die Zuweisung
> reinfunken.

Mit dem Annähern bin ich schon dran.
hatte vorhin schon einmal mit 16382 getestet gehabt. Das hat noch 
funktioniert.

ich habe den Zugriff auf die Zähler Variablen nur noch im Main. Das 
sollte doch ausreichen sein.
Die TimerPulse Variable wird von der Interrupt Variable auf 1 gesetzt.
Wenn nur die Main Variable auf "zeit_nicht_gespuelt" zugreift, dann kann 
doch die Bearbeitung nicht manipuliert werden.
Oder kann es passieren, dass der Interrupt die Register in die die 
Variablen geladen wurde manipuliert und ich davon nichts mitbekomme?
1
if(TimerPulse >0)
2
 {
3
  TimerPulse =0;
4
  //Restspuelzeit reduzieren
5
  if (rest_spuelzeit>0)
6
   {
7
    rest_spuelzeit--;
8
   }
9
   zeit_nicht_gespuelt += 1UL;
10
  }

von Falk B. (falk)


Lesenswert?

Sebastian R. schrieb:
> Hallo Zusammen,
> ich habe noch etwas weiter getestet. An dem Interrupt liegt es definitiv
> nicht, aber ich habe das trotzdem alles Atomar getrennt.

Zeig uns deinen KOMPLETTEN, AKTUELLEN Quelltext!

von Harald K. (kirnbichler)


Lesenswert?

(Und zwar als Dateianhang mit der Dateinamenserweiterung *.c/*.h, damit 
das Forum die automatische Codeansicht anbieten kann)

von Sebastian (sepp1985)


Lesenswert?

Hab den letzten Fehler gefunden. In einem Beitrag hatte ich gelesen, 
dass man die Optimierungen abschalten sollte. Dieses hatte ich getestet, 
aber vergessen wieder einzuschalten.
Nachdem die Optimierung wieder eingeschaltet war, funktionierte auch der 
Rest vom Programm wieder.

geändert habe ich von der Ausgangssituation:
Interrupt Routine gekürzt. Hier wird nur noch ein Flag gesetzt was im 
Main ausgewertet wird.
ADC Interrupt setzt ebenfalls ein Flag und wird im Main umkopiert.
Volatile vor Variablen geschrieben die im Interrupt und im Main 
verwendet werden.

Vielen Dank für die Unterstützung.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Sebastian R. schrieb:
> Nachdem die Optimierung wieder eingeschaltet war, funktionierte auch der
> Rest vom Programm wieder.
(M)ein Programm muss mit und ohne Optimierung funktionieren.

Denn wenn die einen Unterschied macht, der sich nicht erklären lässt, 
dann hat man noch einen Fehler im Programm, der einen sicher wieder 
einholt.

Und wie schon gesagt: die Verwaltung von Zeiten wird viel einfacher, 
wenn man nicht zig Zähler verwalten muss, sondern nur 1 einzigen, der 
pünktlich und garantiert jede ms um 1 hochzählt. Wie das geht und sicher 
kein Überlaufproblem bringt, habe ich schon erwähnt.

: Bearbeitet durch Moderator
von Falk B. (falk)


Lesenswert?

Sebastian R. schrieb:
> Hab den letzten Fehler gefunden. In einem Beitrag hatte ich gelesen,
> dass man die Optimierungen abschalten sollte. Dieses hatte ich getestet,
> aber vergessen wieder einzuschalten.
> Nachdem die Optimierung wieder eingeschaltet war, funktionierte auch der
> Rest vom Programm wieder.

Das ist eine große Warnlampe! Wenn das Ein oder Ausschalten der 
Optimierung solche Änderung in der Reaktion eines Programms erzeugt, ist 
grundlegend was faul!

> geändert habe ich von der Ausgangssituation:
> Interrupt Routine gekürzt. Hier wird nur noch ein Flag gesetzt was im
> Main ausgewertet wird.
> ADC Interrupt setzt ebenfalls ein Flag und wird im Main umkopiert.
> Volatile vor Variablen geschrieben die im Interrupt und im Main
> verwendet werden.

Bla Bla Bla!

Bis du so ignorant oder was ist sonst mit dir los? Warum haben MEHRERE 
Leute geschrieben, daß du den aktuellen, VOLLSTÄNDIGEN Quelltext hier 
hochladen sollst?

Du hast weder das Problem verstanden noch gelöst, nur solange planlos 
rumgefummelt bis es SCHEINBAR funktioniert.

von Sebastian (sepp1985)


Lesenswert?

Lothar M. schrieb:
> Sebastian R. schrieb:
>> Nachdem die Optimierung wieder eingeschaltet war, funktionierte auch der
>> Rest vom Programm wieder.
> (M)ein Programm muss mit und ohne Optimierung funktionieren.
>
> Denn wenn die einen Unterschied macht, der sich nicht erklären lässt,
> dann hat man noch einen Fehler im Programm, der einen sicher wieder
> einholt.
>
> Und wie schon gesagt: die Verwaltung von Zeiten wird viel einfacher,
> wenn man nicht zig Zähler verwalten muss, sondern nur 1 einzigen, der
> pünktlich und garantiert jede ms um 1 hochzählt. Wie das geht und sicher
> kein Überlaufproblem bringt, habe ich schon erwähnt.

Wie schon erwähnt habe ich das schon so abgeändert.
Es gibt nur einen der per Flag aus dem Interrupt einmal im Main 
inkrementiert wird. Auch das Zurücksetzen findet nur einmal im Main 
statt.
Problem gab es mit der Berechnung der Zwangsspülzeit.

von Sebastian (sepp1985)


Lesenswert?

Falk B. schrieb:
> Sebastian R. schrieb:
>> Hab den letzten Fehler gefunden. In einem Beitrag hatte ich gelesen,
>> dass man die Optimierungen abschalten sollte. Dieses hatte ich getestet,
>> aber vergessen wieder einzuschalten.
>> Nachdem die Optimierung wieder eingeschaltet war, funktionierte auch der
>> Rest vom Programm wieder.
>
> Das ist eine große Warnlampe! Wenn das Ein oder Ausschalten der
> Optimierung solche Änderung in der Reaktion eines Programms erzeugt, ist
> grundlegend was faul!
>
>> geändert habe ich von der Ausgangssituation:
>> Interrupt Routine gekürzt. Hier wird nur noch ein Flag gesetzt was im
>> Main ausgewertet wird.
>> ADC Interrupt setzt ebenfalls ein Flag und wird im Main umkopiert.
>> Volatile vor Variablen geschrieben die im Interrupt und im Main
>> verwendet werden.
>
> Bla Bla Bla!
>
> Bis du so ignorant oder was ist sonst mit dir los? Warum haben MEHRERE
> Leute geschrieben, daß du den aktuellen, VOLLSTÄNDIGEN Quelltext hier
> hochladen sollst?
>
> Du hast weder das Problem verstanden noch gelöst, nur solange planlos
> rumgefummelt bis es SCHEINBAR funktioniert.

Daumen hoch für die Freundlichkeit.

Ich habe jetzt noch draus gelernt, dass wenn was nachher 
funktioniert/was gefunden hat, man am besten die Klappe hält.

Ich habe ein paar Fehler gefunden und behoben. Nur zur Korrektur, dass 
das Problem nicht verstanden wurde. Es waren leider mehrere Fehler.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Sebastian schrieb:
> Ich habe jetzt noch draus gelernt, dass wenn was nachher
> funktioniert/was gefunden hat, man am besten die Klappe hält.

Vielleicht hast du das falsche gelernt.

von Falk B. (falk)


Lesenswert?

Sebastian schrieb:
> Ich habe jetzt noch draus gelernt, dass wenn was nachher
> funktioniert/was gefunden hat, man am besten die Klappe hält.

Deine Wahrnehmung ist ziemlich verzerrt. Lies mal was über 
Netiquette.

https://www.mikrocontroller.net/articles/Netiquette#Happy_End

von Rainer W. (rawi)


Lesenswert?

Sebastian R. schrieb:
> Hierbei verhält es sich, als wäre die Zähler Variable irgendwann
> negativ.

Dann ist irgendetwas doch nicht unsigned.

von Harald K. (kirnbichler)


Lesenswert?

Wo bleibt eigentlich der Quelltext?

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.