Problem mit Variablen bei C Uhr

Gast #4091593
Lesenswert?

Hallo zusammen,

ich versuche gerade eine einfache Uhr in C zu programmieren.
Das ganze läuft über den Timer eines Mikrocontrollers. Mit dem 
TimerInterruptOverflow zähle ich eine Variable hoch.
Diese wiederum zählt dann meine Schleifen hoch
if(sek==59){
sek=0;
min++;
usw.

funktioniert auch soweit und auch die Ausgabe auf das LCD.
Als Variablen benutzte ich uint8_t.
Das Problem ist das nach einer gewissen Zeit meine Zeilen auf dem 
Display mit irgendeinem Kram überschrieben werden. Es scheint mir so als 
ob die Variablen irgendwann überfüllt sind.
Das verstehe ich nicht, da ich ja immer wieder bei 59 auf 0 setze usw.

Hat jemand einen Tipp?
Ich programmiere mit AVR-Studio 4
Gast #4091605
Lesenswert?

>Das Problem ist das nach einer gewissen Zeit meine Zeilen auf dem
>Display mit irgendeinem Kram überschrieben werden. Es scheint mir so als
>ob die Variablen irgendwann überfüllt sind.

Nö, ich denke das die Ausgabe auf das Display Müll ist.

>Das verstehe ich nicht, da ich ja immer wieder bei 59 auf 0 setze usw.

Wie gibst du die Zahlen aus?

Mal ein einfaches Beispiel:

Deine Minute war 59. Danach wird 0 ausgegeben.
59 -> 09. Sieht das ungefähr so aus?
Gast #4091616
Lesenswert?

also wie gesagt das flag wird in der Iterrupt Routine gezählt.
Ja das Problem das beim umspringen von 59 auf 1 -> 19 steht hab ich auch 
noch ;-)
1
static uint8_t sek=0;
2
static uint8_t min=0;
3
static uint8_t std=0;
4

5
if(flag1>=61){
6
  sekunde++;
7
  flag1=0;
8
  lcd_set_cursor(7,1);
9
  lcd_print_itoa(sekunde);
10

11
if(sekunde>=59){
12
  sekunde=0;
13
  minute++;
14
  lcd_set_cursor(4,1);
15
  lcd_print_itoa(minute);
16
if(minute>=59){
17
  minute=0;
18
  stunde++;
19
  lcd_set_cursor(1,1);
20
  lcd_print_itoa(stunde);
21
if(stunde>=23){
22
  stunde=0;
23
  }
24
  }
25
  }
26
  }
Gast #4091631
Lesenswert?

die Funktion habe ich aus der vorhandenen lib und sieht so aus:
1
   The function itoa() converts the integer value from \c val into an
2
   ASCII representation that will be stored under \c s.  The caller
3
   is responsible for providing sufficient storage in \c s.
4

5
   \note The minimal size of the buffer \c s depends on the choice of
6
   radix. For example, if the radix is 2 (binary), you need to supply a buffer
7
   with a minimal length of 8 * sizeof (int) + 1 characters, i.e. one
8
   character for each bit plus one for the string terminator. Using a larger
9
   radix will require a smaller minimal buffer size.
10

11
   \warning If the buffer is too small, you risk a buffer overflow.
12

13
   Conversion is done using the \c radix as base, which may be a
14
   number between 2 (binary conversion) and up to 36.  If \c radix
15
   is greater than 10, the next digit after \c '9' will be the letter
16
   \c 'a'.
17
    
18
    If radix is 10 and val is negative, a minus sign will be prepended.
19

20
   The itoa() function returns the pointer passed as \c s.
21
*/
22
extern char *itoa(int __val, char *__s, int __radix);


Die Uhr springt ja jeweils durch rücksetzen sekunde=0; auf Null oder 
muss ich das anderst realisieren?
Gast #4091662
Lesenswert?

Ok ich verstehe schon was ihr meint.
Ich versuche mal eine Lösung zu finden bzw. eine andere Funktion für die 
itoa Variante.
Wie kann ich die Printfunktion beeinflussen damit immer 2-stellig 
geschrieben wird?

Das Problem, dass mir irgendwann alles überschrieben wird habe ich aber 
immer noch nicht verstanden. Irgendeine Idee woher das kommen könnte?
#4091665
Lesenswert?

Anfänger schrieb:
> also wie gesagt das flag wird in der Iterrupt Routine gezählt.

Das ewige und meist auch sinnvolle Dogma mit der möglichst kurzen ISR 
besagt nicht, dass man darin gar nichts machen darf. Zähl deine Uhr in 
der ISR hoch. Soviel Zeit muss sein. Und die ist auch vorhanden. Dann 
tritt auch das Problem, dass ein Inkrement verschluckt wird, gar nicht 
erst auf. Du zählst einfach bis 60 bzw. 24 und setzt dann auf 0.

Nur Ausgabe auf das Display machst du natürlich nicht in der ISR. Sowas 
ist meist tödlich.

mfg.
(Firma: DB1FW) Persönliche Seite #4091684
Lesenswert?

Wenn das C ist, dann ist lcd_print_itoa eine Funktion. Die macht 
anscheinend irgendwas  mit itoa und gibt was auf das LCD aus.
Ob sie das mit/ohne 0 oder Leerzeichen macht, das wissen wir nicht.

Wahrscheinlich/anscheinend nicht - aber wenn uns der TO nicht sagt
welche Libraries er verwendet, dann ist alles nur geraten und stochern 
im Nebel.

P.s. Die LCD Funktion solle nicht aus dem Interrupt sondern in der 
Hauptprogrammschleife aufgerufen werden.
Aber das ist das 2.te Problem.
Gast #4091704
Lesenswert?

1
void lcd_data(unsigned char temp1)
2
{
3
   unsigned char temp2 = temp1;
4
 
5
   LCD_PORT |= (1<<LCD_RS);        // RS auf 1 setzen
6
 
7
   temp1 = temp1 >> 4;
8
   temp1 = temp1 & 0x0F;
9
   LCD_PORT &= 0xF0;
10
   LCD_PORT |= temp1;               // setzen
11
   lcd_enable();
12
 
13
   temp2 = temp2 & 0x0F;
14
   LCD_PORT &= 0xF0;
15
   LCD_PORT |= temp2;               // setzen
16
   lcd_enable();
17
   
18
   _delay_us(42);
19
}
20

21
void lcd_string(char *data)
22
{
23
    while(*data) {
24
        lcd_data(*data);
25
        data++;
26
    }
27
}
28

29
void lcd_print_itoa(unsigned int zahl) {
30
char buffer [1000];
31

32
    itoa(zahl, buffer, 10); 
33
    lcd_string(buffer);
34
  }
Gast #4091711
Lesenswert?

>Eine führende Null für eine eistellige Zahl könnte man so einbauen:
>
>    itoa(zahl, buffer, 10);
>    if(buffer[1] == 0x00)
>      lcd_data('0');

OMG.

  if(zahl < 10) lcd_data('0');

Danach das andere Geraffel.
Gast #4091713
Lesenswert?

Du benutzt :     lcd_print_itoa();
Du erklärst :    itoa();
Du Antwortest :  lcd_print ist nur die Funktion um etwas an das LCD zu 
senden

Jetzt haben wir schon 3 unterschiedliche Funktionen im Spiel.

Wenn das C ist, dann sind das 3 unterschiedliche Dinge.

Aus lcd_print wird nicht plötzlich lcd_print_itoa nur weil man _itoa 
and den Namen dranhängt.

Ich bin fast Sicher die Lösung wäre was in der Richtung
1
if(flag1>=61){
2
  sekunde++;
3
  flag1=0;
4
   
5
  lcd_set_cursor(7,1);
6
  if ( sekunde < 10 )
7
    lcd_print("0");
8
  lcd_print_itoa(sekunde);
9

10
  if(sekunde>60){
11
    sekunde=0;
12
    minute++;
13
    lcd_set_cursor(4,1);
14
    if ( minute < 10 )
15
      lcd_print("0");
16
    lcd_print_itoa(minute);
17
    if(minute>=59){
18
      minute=0;
19
      stunde++;
20
      lcd_set_cursor(1,1);
21
      if ( stunde < 10 )
22
        lcd_print("0");
23
      lcd_print_itoa(stunde);
24
      if(stunde > 23){
25
        stunde=0;
26
      }
27
    }
28
  }
29
}
Und das im Hautprogramm aufgerufen.


Aber halt nur geraten.
Gast #4091738
Lesenswert?

ok, erstmal vielen Dank für die ganzen Hilfestellungen.
@Frank, deine Idee bringt mir aufjedenfall die führenden Nullen aber ich 
überschreibe mir tortzdem bei der Ausgabe auf dem LCD irgendwann meine 
weiteren Zeilen und Spalten mit irgendwelchen Zahlen.

Was mich wundert, dass das manchmal sofort, manchmal erst nach 3 Minuten 
passiert.
Gast #4091845
Lesenswert?

Ich inkrementiere jetzt nur noch das Flag über den Interrup, der Rest 
läuft im Hauptprogramm. Es scheint jetzt zu funktionieren, keine 
komischen Zeichen mehr und nichts wird überschrieben. Hauptproblem war 
dann wohl meine Strukturierung.

Vielen Dank für die ganzen Hilfen!!!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren