Forum: Compiler & IDEs Uhrzeit stellen


von Jochen (Gast)


Lesenswert?

Hallo,

ich bin Jochen und versuche mich gerade an einem kleinen Projekt.
Ich habe das Buch von Herrn Günter Spanner.
"AVR-Mikrokontroller in C programmieren"

Darin sind einige Beispielprojekte, an welchen ich mich so nach und nach 
versuche.

Ich bin gerade dabei eine Tischuhr zu bauen.
Die Uhr gibt nur Stunden Minuten und Sekunden aus.

Der Programmcode, mit welchem meine Uhr soweit schon läuft sieht wie 
folgt aus.
1
#define XTAL  8e6                 // Taktangabe
2
#define F_CPU  XTAL                // Taktangabe
3
#include <avr/io.h>
4
#include <stdlib.h>
5
#include <util/delay.h>             // verzögerung_delay_ms(). _delay_us()
6
#include <avr/interrupt.h>
7
#include <lcd/lcd-routines-portd.h> // greift auf LCD-routine zu
8
#include <lcd/lcd-routines.c>       // greift auf LCD-routine zu
9
#include <stdio.h>
10
11
#define   TASTER1       PB0
12
#define   TASTER2       PB1
13
#define   TASTER3       PB2
14
#define   TASTER4       PD7         // eventuell umlöten auf PB3-->(ISP)!
15
16
17
volatile int tc;
18
char hr=20, min=0, sec=0;
19
char str[2];
20
21
22
ISR(TIMER1_OVF_vect)                //1 second clock
23
{  
24
   TCNT1 = 34286; tc++;
25
}
26
27
int main(void)
28
{
29
30
    TIMSK |= _BV(TOIE1);   // aktivate overflow interrupt of timer1 
31
  TCCR1B |= (1<<CS12);  // prescaler = 256
32
  TCNT1 = 0xFFFF;         // FFFF for start 
33
    lcd_init();
34
  lcd_clear();
35
  lcd_setcursor(1,1);
36
  lcd_string("00:00:00");
37
    sei();
38
39
//*************UHR****************
40
41
                sec=tc;
42
    if(sec==60)
43
    {
44
       tc=0;
45
       sec=0;
46
       min++;
47
       if(min==60)
48
       {
49
          min=0;
50
        hr++;
51
        if(hr==24)
52
        {
53
           hr=0;
54
           }
55
       }
56
       sprintf(str,"%02d",min);
57
       lcd_setcursor (4, 1);
58
       lcd_string(str);
59
60
       sprintf(str,"%02d",hr);
61
       lcd_setcursor (1, 1);
62
       lcd_string(str);
63
     }
64
     sprintf(str,"%02d",sec);
65
     lcd_setcursor (7, 1);
66
     lcd_string(str);
67
//********************************
68
69
70
}
71
  return 0;
72
}

Dieser Code stammt auch aus dem Buch.
Eine weitere Aufgabe, welche man sich stellen soll ist die Verwendung 
von Tastern, mit welchen man die Uhr stellen soll.

Ich habe nun schon etliche Versuche gestartet nur leider bekomme ich es 
irgendwie nicht hin.

Kurze Frage:
Mit sei(); wird ja ein Interrupt aufgerufen. Warum steht am Ende dann 
nicht cli(); ? Das Hauptprogramm läuft doch pausenlos durch.

Nun ja, ich habe 4 Taster definiert:
[c]
#define   TASTER1       PB0
#define   TASTER2       PB1
#define   TASTER3       PB2
#define   TASTER4       PD7
[c/]

Mit Taster1 möchte ich die Stunden hochzählen und mit Taster2 die 
Minuten.
Mit Taster3 oder 4 soll das ganze bestätigt werden.

Ich hoffe ihr könnt mir etwas helfen, für Ideen und Vorschläge wäre ich 
sehr Dankbar

schöne Grüße Jochen

von MaWin (Gast)


Lesenswert?

> Mit sei(); wird ja ein Interrupt aufgerufen.

Nein. Freigegeben.

von Jochen (Gast)


Lesenswert?

MaWin schrieb:
> Nein. Freigegeben.

Gut, aber was macht den unterschied ob ich cli(); am Ende setze oder 
nicht.
Ich hab es ja schon ausprobiert, jedoch läuft die Uhr dann nur einmal 
und bleibt bei 00:00:01 stehen.

Hm, warum stelle ich die Frage eigentlich erklärt sich ja von selbst ;)
sei();
cli();
wird beim ersten Durchlauf Freigegeben und danach geschlossen.

nur sei();
wird bei jedem Durchlauf des Hauptprogrammes Freigegeben.

von Krapao (Gast)


Lesenswert?

>  lcd_string("00:00:00");
>    sei();
>
>//*************UHR****************
>
>                sec=tc;
>    if(sec==60)
>    {

Nach dem sei() und vor dem sec=tc fehlt mindestens eine Zeile!

Nämlich die Anweisung, dass eine Endlosschleife beginnen soll, also ein 
while(1){ oder ein for(;;){

Das Abfragen von Tastern ist im AVR-GCC-Tutorial erklärt und man muss 
den Artikel Entprellung beachten.

von Ralf G. (ralg)


Lesenswert?

Vergiss erstmal die Uhr. Wichtiger ist eine ordentliche Programmstruktur 
(funktionell + 'ästhetisch'). Wenn ich bei den bunt durcheinander 
gewürfelten Klammern nicht wieder eine übersehen habe: der Code geht 
nicht mal durch den Compiler.

Jochen schrieb:
> Ich hab es ja schon ausprobiert, jedoch läuft die Uhr dann nur einmal
> und bleibt bei 00:00:01 stehen.

Das hast du auch so programmiert! Ein Funktionsaufruf (hier zuuufällig 
'main') und dann Schluss.

von Jochen (Gast)


Lesenswert?

Krapao schrieb:
> Nach dem sei() und vor dem sec=tc fehlt mindestens eine Zeile!

Hi Krapao,
ja klar die while(1) hatte ich vergessen, da ich den Code aus meinem 
"Versuchscode" rauskopiert habe. die while(1) ist aber vorhanden.

Die Entprellung habe ich auch aus dem vorgeschlagenem Artikel.
Habe ihn auf meinen Taster zurecht geschnitten, jedoch noch nicht 
getestet.
Habe ich damit grundlegend was falsch gemacht?
Er steht im Code genau vor der "main" Funktion.
Ich bin mir aber unsicher, ob es sich um den Code nur um die Flanken 
handelt, oder ob die Prellung damit gleichzeitig "weg ist"
1
#define   TASTER1       PB0
2
3
char taster(void) 
4
{
5
    static unsigned char zustand;
6
    char rw = 0;
7
 
8
    if(zustand == 0 && !(PINB & (1<<TASTER1)))   //Taster wird gedrueckt (steigende Flanke)
9
    {
10
        zustand = 1;
11
        rw = 1;
12
    }
13
    else if (zustand == 1 && !(PINB & (1<<TASTER1)))   //Taster wird gehalten
14
    {
15
         zustand = 2;
16
         rw = 0;
17
    }
18
    else if (zustand == 2 && (PINB & (1<<TASTER1)))   //Taster wird losgelassen (fallende Flanke)
19
    {
20
        zustand = 3;
21
        rw = 0;
22
    }
23
    else if (zustand == 3 && (PINB & (1<<TASTER1)))   //Taster losgelassen
24
    {
25
        zustand = 0;
26
        rw = 0;
27
    }
28
 
29
    return rw;
30
}
31
32
33
-->main

von Krapao (Gast)


Lesenswert?

Schreib ein kleines Zählerprogramm. Dann siehst du, ob die Entprellung 
funktioniert. Jeder Tastendruck muss sauber einen Zählschritt machen.

Teile des Zählerprogramms kannst du später für das Stellen der Uhrzeit 
rezyklieren. Das Stellen von Stunde/Minute ist auch nix anders als ein
Hochzählen von 0-23 bzw. 0-59.

von Jochen (Gast)


Lesenswert?

Hier mal mein Code für das Zählprogramm.

Er ist sicher Klobig und Grob in euren Augen, jedoch bekomme ich so das 
Zählen hin.
Das Problem ist dabei nur, dass der Taster ab und an nicht richtig 
funktioniert und man muss 3x dücken, bevor sich was tut.

Was mich interessiert ist, ob ich den "Entprellcode" und die "Flanken" 
richtig eingefügt habe?

Verbesserungsvorschläge sind natürlich gerne gesehen ;)
1
#define XTAL  8e6                 // Taktangabe
2
#define F_CPU  XTAL                // Taktangabe
3
#include <avr/io.h>
4
#include <stdlib.h>
5
#include <util/delay.h>             // verzögerung_delay_ms(). _delay_us()
6
#include <avr/interrupt.h>
7
#include <lcd/lcd-routines-portd.h> // greift auf LCD-routine zu
8
#include <lcd/lcd-routines.c>       // greift auf LCD-routine zu
9
#include <stdio.h>
10
11
#define   TASTER1       PB0
12
        
13
14
15
16
//Flanken
17
char taster(void) 
18
{
19
    static unsigned char zustand;
20
    char rw = 0;
21
 
22
    if(zustand == 0 && !(PINB & (1<<PB0)))   //Taster wird gedrueckt (steigende Flanke)
23
    {
24
        zustand = 1;
25
        rw = 1;
26
    }
27
    else if (zustand == 1 && !(PINB & (1<<PB0)))   //Taster wird gehalten
28
    {
29
         zustand = 2;
30
         rw = 0;
31
    }
32
    else if (zustand == 2 && (PINB & (1<<PB0)))   //Taster wird losgelassen (fallende Flanke)
33
    {
34
        zustand = 3;
35
        rw = 0;
36
    }
37
    else if (zustand == 3 && (PINB & (1<<PB0)))   //Taster losgelassen
38
    {
39
        zustand = 0;
40
        rw = 0;
41
    }
42
    return rw;
43
}
44
45
//Entprellcode
46
void entprellung( volatile uint8_t *port, uint8_t maske ) 
47
{
48
  uint8_t   port_puffer;
49
  uint8_t   entprellungs_puffer;
50
 
51
  for( entprellungs_puffer=0 ; entprellungs_puffer!=0xff ; ) 
52
  {
53
    entprellungs_puffer<<=1;
54
    port_puffer = *port;
55
    _delay_us(150);
56
    if( (*port & maske) == (port_puffer & maske) )
57
    entprellungs_puffer |= 0x01;
58
  }
59
}
60
61
int main(void)
62
{
63
64
     lcd_init();
65
   lcd_setcursor(1,1);
66
   lcd_string( "Hallo" ); 
67
   char counter;
68
     char str[2];
69
   counter = 255;
70
     counter = 0;
71
72
73
while(1)
74
{
75
   while(PINB & (1<<PB0))
76
   {
77
        entprellung( &PINB, (1<<PB0) ); // ggf. Prellen abwarten 
78
     if( PINB & (1<<PB0) )              // dann stabilen Wert einlesen
79
     {
80
       // mach was
81
       lcd_setcursor(1,2);
82
        lcd_string( "Taster aus" ); 
83
     }
84
     else
85
     {
86
       // mach was anderes
87
     lcd_setcursor(1,2);
88
     lcd_string( "Taster ein" );
89
     counter++;
90
     if(counter==25)
91
       {
92
        counter=0;
93
     } 
94
95
     }
96
97
   sprintf(str,"%02d",counter);
98
   lcd_setcursor (12, 2);
99
   lcd_string(str);
100
101
   }
102
103
}
104
  return 0;
105
}

von Krapao (Gast)


Lesenswert?

Du hast ein Mischmasch aus zwei Versionen :-(

1) char taster(void)

Das ist nur Beiwerk im Programm. Toter Code der nirgends aufgerufen 
wird.

2) Sieht gut aus:
   entprellung( &PINB, (1<<PB0) );
   if( PINB & (1<<PB0) )

3) while(PINB & (1<<PB0))

"So lange wie eine Taste gedrückt ist, mache..." macht mir 
programmlogisch keinen Sinn, wenn pro Tastendruck ein Zähler hochzählen 
soll. Diese Funktionalität hast du bereits durch das while(1) in 
Verbindung mit dem Konstrukt aus 2) weil die entprellung() dort nicht 
auf das Loslassen der Taste besteht.

Du musst auch beachten, dass dein Programm durch zu viele LCD Ausgaben 
träge reagiert. Mache die Ausgaben nur, wenn sich tatsächlich etwas 
geändert hat.
1
#include <avr/io.h>
2
#include <stdlib.h>
3
#include <stdio.h>
4
#include <util/delay.h>             // verzögerung_delay_ms(). _delay_us()
5
#include <lcd/lcd-routines-portd.h> // greift auf LCD-routine zu
6
7
// Besser: Als eigenständiges C-File ins Projekt einbinden
8
#include <lcd/lcd-routines.c>       // greift auf LCD-routine zu
9
10
#define AN 1
11
#define AUS 0
12
#define UNDEFINIERT -1
13
14
// Entprellcode
15
void entprellung( volatile uint8_t *port, uint8_t maske ) 
16
{
17
  uint8_t   port_puffer;
18
  uint8_t   entprellungs_puffer;
19
 
20
  for( entprellungs_puffer=0 ; entprellungs_puffer!=0xff ; ) 
21
  {
22
    entprellungs_puffer<<=1;
23
    port_puffer = *port;
24
    _delay_us(150);
25
    if( (*port & maske) == (port_puffer & maske) )
26
    entprellungs_puffer |= 0x01;
27
  }
28
}
29
30
int main(void)
31
{
32
  char str[2+1]; // <=== War vorher zu klein für zwei Dezimalstellen!
33
  char counter = 0;
34
  char zustand = UNDEFINIERT;
35
36
  lcd_init();
37
  lcd_setcursor(1,1);
38
  lcd_string( "Hallo" ); 
39
  sprintf(str,"%02d", counter);
40
  lcd_setcursor (12, 2);
41
  lcd_string(str);
42
43
  while(1)
44
  {
45
    entprellung( &PINB, (1<<PB0) ); // ggf. Prellen abwarten 
46
    if( PINB & (1<<PB0) )           // dann stabilen Wert einlesen
47
    {
48
      if ( zustand != AUS )
49
      {
50
        lcd_setcursor(1,2);
51
        lcd_string( "Taster aus" ); 
52
        zustand = AUS;
53
      }
54
    }
55
    else
56
    {
57
      if ( zustand != AN )
58
      {
59
        lcd_setcursor(1,2);
60
        lcd_string( "Taster ein" );
61
        zustand = AN;
62
      }
63
      counter++;
64
      if( counter == 25 )
65
      {
66
        counter = 0;
67
      } 
68
      sprintf(str,"%02d", counter);
69
      lcd_setcursor (12, 2);
70
      lcd_string(str);
71
    }
72
  }
73
}

von Krapao (Gast)


Lesenswert?

Statt dem fettem

> sprintf(str,"%02d", counter);

geht auch das:
1
  str[0] = '0' + counter/10;
2
  str[1] = '0' + counter%10;
3
  str[2] = '\0';

von Peter D. (peda)


Lesenswert?

Jochen schrieb:
> entprellung( &PINB, (1<<PB0) ); // ggf. Prellen abwarten
>      if( PINB & (1<<PB0) )              // dann stabilen Wert einlesen

Das stimmt nicht.
Deine Entprellung macht es nur etwas warscheinlicher, daß der Zustand 
danach stabil ist, sie garantiert es aber nicht.
Er kann sich zufällig gerade danach ändern.
Deine Muskeln sind ja nicht mit dem CPU-Takt synchronisiert.

Es ist deshalb deutlich zuverlässiger, wenn die Entprellung selber den 
stabilen Zustand zurückgibt, denn genau dafür ist sie ja da und nur sie 
kann es auch feststellen.

Programme, die wild umher den Zustand von außen neu einlesen, können die 
wunderlichsten Überrraschungen erleben.
Außerdem ist das nur unnütz zusätzlicher Code.

Es gibt nur eine Instanz, die den Pin einlesen darf und das ist der 
Entpreller.
Alle anderen haben stricktes Verbot den Pin direkt einzulesen, sie 
dürfen nur den aufbereiteten Wert des Entprellers verwenden.


Peter

von Jochen (Gast)


Lesenswert?

Krapao schrieb:

> 3) while(PINB & (1<<PB0))
>
> "So lange wie eine Taste gedrückt ist, mache..." macht mir
> programmlogisch keinen Sinn, wenn pro Tastendruck ein Zähler hochzählen
> soll. Diese Funktionalität hast du bereits durch das while(1) in
> Verbindung mit dem Konstrukt aus 2) weil die entprellung() dort nicht
> auf das Loslassen der Taste besteht.
(siehe unten)


1
>   char str[2+1]; // <=== War vorher zu klein für zwei Dezimalstellen!
Hm..hat vorher aber auch funktioniert, jedenfalls die Ausgabe auf dem 
Display.


1
>   while(1)
2
>   {
3
>     entprellung( &PINB, (1<<PB0) ); // ggf. Prellen abwarten 
4
>     if( PINB & (1<<PB0) )           // dann stabilen Wert einlesen
5
>     {
6
>       if ( zustand != AUS )
7
>       {
8
>         lcd_setcursor(1,2);
9
>         lcd_string( "Taster aus" ); 
10
>         zustand = AUS;
11
>       }
12
>     }
13
>     else
14
>     {
15
>       if ( zustand != AN )
16
>       {
17
>         lcd_setcursor(1,2);
18
>         lcd_string( "Taster ein" );
19
>         zustand = AN;
20
>       }
21
>       counter++;
22
>       if( counter == 25 )
23
>       {
24
>         counter = 0;
25
>       } 
26
>       sprintf(str,"%02d", counter);
27
>       lcd_setcursor (12, 2);
28
>       lcd_string(str);
29
>     }

habe deinen Code einfach mal so übernommen und getestet;)
Ich weiß nun nicht ob es deine Absicht war ihn funktionsfähig zu 
machen..., jedoch laufen die Zahlen beim gedrückt halten ununterbrochen 
weiter.
Ist ja eigentlich logisch da while(1)... Die Schleife interessiert es ja 
nicht ob ich den Taster gedrückt halte oder nicht?

von Jochen (Gast)


Lesenswert?

natürlich...hab vergessen mich zu bedanken!
Vielen Dank für die Bemühungen ;)

von Jochen (Gast)


Lesenswert?

..und nochmal..tut mir leid^^
durch das einbringen von while(PINB & (1<<PB0)) in die while(1) deines 
Codes läuft das hochzählen nun tadellos!

Was spricht dagegen es nicht zu verwenden? Meine Erfahrung in Sachen C 
sind einfach, dass es immer einen Hacken gibt. Also raus mit der Sprache 
;)

von Peter D. (peda)


Lesenswert?

Jochen schrieb:
> Was spricht dagegen es nicht zu verwenden? Meine Erfahrung in Sachen C
> sind einfach, dass es immer einen Hacken gibt. Also raus mit der Sprache
> ;)

Probier mal folgendes zu programmieren:

1.
Nimm 2 LEDs und 2 Tasten, können aber auch mehr sein.
Beim Drücken einer Taste wechselt die dazu gehörende LED.
Beim gedrückt Halten, Loslassen oder ungedrückt passiert nichts.
Jede Taste arbeitet unabhängig. Also auch wärend die andere Taste 
gedrückt gehalten wird, funktioniert sie.

2.
Jetzt simulieren wir eine hohe CPU-Last und bauen 500ms Delay in die 
Mainloop ein.
Alles muß weiterhin funktionieren, ohne daß man 500ms lang drücken muß.
Lediglich die LEDs reagieren bis zu 500ms verzögert.

Eine gute Entprellroutine muß das können, keinen Tastendruck verlieren 
und keinen Preller durchlassen.


Es ist nunmal so, daß man im Web alles veröffentlichen kann, also auch 
Entprellroutinen, die deutliche Nachteile haben.
Es gibt keinen Oberlehrer, der dann diese Beiträge löscht.
Man muß also ganz genau lesen und auch die Erfahrungen anderer, was 
diese so benutzen.


Man sollte auch versuchen, daß die Geräte auch nach einem Jahr noch 
einwandfrei funktionieren, wenn die Federspannung nachläßt oder die 
Kontakte verschmutzen.
Eine Entprellroutine testet man am besten mit alten Tastern, die man aus 
Geräten ausgebaut hat, die lange (10 Jahre) und häufig benutzt wurden.
Mit fabrikneuen Tastern kann man die Qualität der Entprellsoftware nicht 
feststellen.


Peter

von Jochen (Gast)


Lesenswert?

Hallo Peter,

klar habe ich auch deinen Code gesehen.
Würde ihn auch gerne benutzen, jedoch nutzt er einen Takt, welchen meine 
"Uhr" nicht nutzt.

Der Quarz schwingt mit 8MHz, der Entprellcode von dir nutzt aber eine 
andere Frequenz, habe nun nicht mehr im Kopf welche.

Und genau deshalb habe ich einen Bogen um deinen Code gemacht, weil ich 
mich dort wieder in Gefilde begebe, von denen ich noch etwas weit 
entfernt bin ;)

Deinen Vorschlag mit den Tastern und den LED's werde ich versuchen 
morgen umzusetzen.

Dennoch ist mir in letzter Zeit aufgefallen, dass die Verwendung von 
Schleifen doch noch etwas Unklarheit bei mir hervorruft.

Ich habe mich natürlich auch belesen und weiß was eine Schleife macht, 
verwende sie ja nicht das erste mal. ....Dennoch müsste mein Programm 
doch laufen, doch dann tut sich doch nichts.

Ich beschreibe einfach einmal kurz wie ich die verschiedenen Schleifen 
definiere. Wenn es da Differenzen gibt, klärt mich auf!


while(1) Endlosschleife, läuft von oben nach unten und immer so weiter. 
Jede Schleife die danach kommt wird deshalb nicht erfasst.

while(Bedingung) Schleife läuft sobald die Bedingung erfüllt wird.
So lange die Bedingung erfüllt ist läuft sie weiter. Wenn die Bed. nicht 
erfüllt ist, wird die Schleife ignoriert.

do while(Bedingung) im Gegensatz zur while() Schleife ist diese 
Fußgesteuert. d.h. die Schleife läuft so lange durch, bis die Bedingung 
erfüllt wurde.

for(;;) z.B. for(int i=0 ; i<=10 ; i++){ cout << i;} i wird so lange 
gezählt, bis es den Wert 10 erreicht hat, dann geht die Schleife "zu".

von Krapao (Gast)


Lesenswert?

> durch das einbringen von while(PINB & (1<<PB0)) in die while(1) deines
> Codes läuft das hochzählen nun tadellos!
>
> Was spricht dagegen es nicht zu verwenden? Meine Erfahrung in Sachen C
> sind einfach, dass es immer einen Hacken gibt. Also raus mit der Sprache
> ;)

Die zweite while-Klammer bewirkt, dass der Taster losgelassen werden 
muss, damit der Anweisungsblock wieder betreten werden kann. Ich habe 
das im Beitrag "Re: Uhrzeit stellen" falsch 
gesehen.

Ohne das while hat der Taster also eine Autorepeat-Funktion, deren 
Geschwindigkeit man mit Delays tunen könnte; mit dem While muss jeder 
Zählschritt einzeln betätigt werden.

Das war zwar nicht meine Absicht beim Schreiben, kann man aber 
vielleicht brauchen. Mein Wecker aus dem Kaufhaus hat eine 
Autorepeatfunktion beim Uhrzeit stellen.

Beiss dich in die saubere Entprellung rein. Mit seinen Tipps hat Peter 
Recht. Das brauchst du immer mal für angenehm funktionierende Geräte.

von Jochen (Gast)


Lesenswert?

Hi Krapao,

wird gemacht, wie gesagt versuche ich mich morgen daran.

Kannst du mir noch etwas zu den Schleifen sagen, welche ich einen Post 
vorher gepostet habe?

von Jochen (Gast)


Lesenswert?

Hab nochmal was probiert und deinen Tip eingebaut.


so könnte man es auch machen, finde es sogar recht praktisch, so kann 
man den Taster betätigen und so lange gedrückt halten bis man auf der 
gewünschten Zeit ist...

Diese Funktion ist mir bekannt, aber selbst auf sowas zu kommen ist für 
mich wirklich schwer!
1
while(1)
2
 {
3
 
4
    entprellung( &PINB, (1<<PB0) ); // ggf. Prellen abwarten 
5
    if( PINB & (1<<PB0) )           // dann stabilen Wert einlesen
6
    {
7
      if ( zustand != AUS )
8
      {
9
        lcd_setcursor(1,2);
10
        lcd_string( "Taster aus" ); 
11
        zustand = AUS;
12
      }
13
    }
14
    else
15
    {
16
      if ( zustand != AN )
17
      {
18
        lcd_setcursor(1,2);
19
        lcd_string( "Taster ein" );
20
        zustand = AN;
21
      }
22
      counter++;
23
      if( counter == 24 )
24
      {
25
        counter = 0;
26
      } 
27
      _delay_ms(500);//                    <------<
28
      sprintf(str,"%02d", counter);
29
      lcd_setcursor (12, 2);
30
      lcd_string(str);
31
    }
32
  
33
  }

von Krapao (Gast)


Lesenswert?

Jo, so steht's beim while und for in jedem C-Lehrbuch drin :-)

Bei deinem for-Beispiel ist das cout << i; kein C sondern C++
Wenn du das for-Beispiel in ein while-Beispiel umformen willst:
1
for(int i=0 ; i<=10 ; i++)
2
{
3
  ...Anweisungen...
4
}

wird daraus
1
{
2
  int i = 0;
3
  while( i <= 10 )
4
  {
5
    ...Anweisungen...
6
    i++;
7
  }
8
}

> do while(Bedingung) im Gegensatz zur while() Schleife ist diese
> Fußgesteuert. d.h. die Schleife läuft so lange durch, bis die Bedingung
> erfüllt wurde.

Nicht ganz. Der Anweisungsblock wird durchlaufen, dann wird die 
Schleifenbedingung geprüft. Wenn die Schleifenbedingung wahr ist, wird 
der Anweisungsblock wieder durchlaufen. Ist die Schleifenbedingung 
falsch, wird die do/while Schleife verlassen. Also nicht "Mache ... bis 
Bedingung wahr ist" sondern "Mache ... solange Bedingung wahr ist"

von Jochen (Gast)


Lesenswert?

Jupp alles klar und es ist auch richtig, dass wenn z.B.


main()
{
while(1) Endlosschleife läuft unendlich
{
xxxxx
}

for(xx) Da while eine Endlosschleife, wird diese völlig ignoriert
{
xxxxx
}
}

von Peter D. (peda)


Lesenswert?

Jochen schrieb:
> klar habe ich auch deinen Code gesehen.
> Würde ihn auch gerne benutzen, jedoch nutzt er einen Takt, welchen meine
> "Uhr" nicht nutzt.

Und wo ist dabei das Problem?

Dein unbekannter AVR hat bestimmt mehrere Timer und diese wiederum 
jeweils mehrere Compare-Interrupts.
Du kannst also haufenweise verschiedene Timerintervalle erzeugen.

Aber auch mit nur einem Timer geht das. Das kürzere Intervall legt man 
einfach so, daß das längere durch ein Vielfaches erzeugt werden kann (= 
Zählvariable). Und die Entprellzeit benötigt ja keinen exakten Wert, 
irgendwas im Bereich 5..50ms ist ok.


Jochen schrieb:
> ISR(TIMER1_OVF_vect)                //1 second clock
> {
>    TCNT1 = 34286; tc++;
> }

Das solltest Du besser schnell wieder vergessen, denn jedes Programm 
benötigt Ausführungszeit, auch ein Interrupt.
Zusätzlich können Interrupts durch andere Interrupts oder atomare 
Codesequenzen verzögert werden.
Diese Zeiten werden hier nicht berücksichtigt.
Wird Dein Programm größer, d.h. hat mehr zu tun, kann Deine Uhr 
nachgehen.
Wie kommst Du überhaupt auf diese komischen 34286?
8e6 / 256 = 31250


Peter

von Jochen (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Wie kommst Du überhaupt auf diese komischen 34286?
> 8e6 / 256 = 31250

Hallo Peter,

wie gesagt ist die Uhr aus einem Buch komplett herauskopiert worden.

Benutzt wird ein ATmega8.

Hier mal der komplette Uhrencode.
1
// LCD Clock
2
3
#define XTAL  8e6
4
#define F_CPU  XTAL
5
6
#include <stdlib.h> 
7
#include <stdio.h>
8
#include <avr/interrupt.h>
9
#include <util/delay.h>
10
11
#include "..\..\includes\BitUtilities.h"
12
#include "..\..\includes\LCD_display_free_int_pins.h"
13
14
volatile int tc;
15
char hr=20, min=0, sec=0;
16
char str[2];
17
18
ISR(TIMER1_OVF_vect)
19
{  TCNT1 = 34286; tc++;
20
}
21
22
int main(void)
23
{  TIMSK |= _BV(TOIE1);   // aktivate overflow interrupt of timer1 
24
  TCCR1B |= (1<<CS12);  // prescaler = 256
25
  TCNT1 = 0xFFFF;     // FFFF for start 
26
  sei();  
27
  
28
  lcd_init(); lcd_send(COMMAND, LCD_CLEAR);
29
  lcd_set_cursor (1, 4);lcd_write ("20:00:00");    
30
  
31
  while(1)
32
  {  sec=tc;
33
    if (sec==60)
34
    {  tc=0; sec=0; min++;
35
      if (min==60) {min=0; hr++; if (hr==24) hr=0;}
36
      sprintf(str,"%02d",min); lcd_set_cursor (1, 7); lcd_write (str);
37
      sprintf(str,"%02d",hr);  lcd_set_cursor (1, 4); lcd_write (str);
38
    }
39
    sprintf(str,"%02d",sec); lcd_set_cursor (1, 10); lcd_write (str);
40
    while(sec == tc);
41
  }    
42
  return(0);
43
}

Als Aufgabenstellung steht drüber:

-Erweiterungsvorschlag:
Spendieren Sie der Uhr einige Taster zum Einstellen der Uhrzeit und 
erweitern Sie so die Uhr zu einer vollwertigen Quarzuhr.


Im gesamten Buch mit ca. 30 Aufgaben und Beispielen wird in keinem der 
Projekte ein Taster verwendet....Ich als Leihe habe deshalb schon meine 
Schwierigkeiten dies zu realisieren.
Es ist natürlich nicht das erste mal, dass ich eine Schaltung realisiere 
und somit weiß ich auch wie man einen Taster active high/low anschlißen 
muss. Wenn man es jedoch auf das Buch beschränkt, ist diese Aussage von 
dem Autor jedoch etwas weit hergeholt;)

von Peter D. (peda)


Lesenswert?

Jochen schrieb:
> wie gesagt ist die Uhr aus einem Buch komplett herauskopiert worden.

Wenn dort die 34286 nicht erklärt wird, dann taugt das Buch nichts.

Aber hier mal die Lösung:
65536 - 8e6 / 256 = 34286

Jochen schrieb:
> Benutzt wird ein ATmega8.

Der hat 3 Timer und 3 Compare-Interrupts, damit kann man 3 völlig 
unabhängige zyklus-genaue Timings realisieren.

Die Overflow-Interrupts sind nur mit Einschränkungen benutzbar, wenn das 
Timing nicht genau sein muß, oder man abgeklärt hat, daß es aufgrund 
eines hohen Vorteilers nicht zu Ungenauigkeiten kommt.


Peter

von Jochen (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Aber hier mal die Lösung:
> 65536 - 8e6 / 256 = 34286

hm.. gut, würdest du das Programm mit deinen Änderungen denn verwenden?
Die Uhr lief bis jetzt sowieso nicht genau. Ein 8MHz Quarz ist 
angeschlossen, jedoch dauert eine Sekunde auf dem Display in 
Wirklichkeit 5 Sekunden.

Ich bin nun gerade dabei 
http://www.mikrocontroller.net/articles/Entprellung#Warteschleifen-Verfahren

für mein gelötetes Board zu übertragen, jedoch tut sich bis jetzt noch 
nichts.

Die Testapplication müsste doch eigentlich funktionieren.

Habe zwei Taster an PB0 und PB1.
Zwei LEDs sind an PC0 und PC1.
Alles was vor der Main steht habe ich unverändert eingefügt.
1
/*
2
   Testapplication
3
 */
4
int main(void)
5
{
6
  DDRB  &= ~(1<<PB0);
7
  PORTB |=   1<<PB0;
8
  DDRB  |=   1<<PC1;
9
  DDRB  &= ~(1<<PB1);
10
  PORTB |=   1<<PB1;
11
  DDRB  |=   1<<PC0;
12
  for(;;)
13
  {
14
    if( debounce( PINB, PB1 ) )
15
      PORTB ^= 1<<PC0;
16
17
    if( debounce( PINB, PB0 ) )
18
      PORTB ^= 1<<PC1;
19
  }
20
}

von Jochen (Gast)


Lesenswert?

Verwendet wurde auch deine Lösung

-Debounce-Makro von Peter Dannegger

von Krapao (Gast)


Lesenswert?

>  DDRB  &= ~(1<<PB0);
>  PORTB |=   1<<PB0;
>  DDRB  |=   1<<PC1;  <========== Copy&Paste FEhler? #1
>  DDRB  &= ~(1<<PB1); #3
>  PORTB |=   1<<PB1;
>  DDRB  |=   1<<PC0;  <========== Copy&Paste FEhler? #2

Schaltet Datenrichtung an PORTB.0 auf Ausgang.
Gleichzeitig ist der Pegel HIGH eingestellt,

Bei einem active-low Taster (schaltet gegen GND)
führt das Drücken des Tasters zum Kurzschluss

Bei #1 macht die Folgezeile #3 den Fehler rückgängig.
1
  // LEDs an PC0 und PC1 auf Ausgang
2
  DDRC |= (1<<PC1)|(1<<PC0);
3
  // active-low Taster an PB1 und PB0 auf Eingang
4
  DDRB &= ~((1<<PB1)|(1<<PB0));
5
  // Interne Pullups active-low Taster an PB1 und PB0 an
6
  PORTB |= (1<<PB1)|(1<<PB0);

von Jochen (Gast)


Lesenswert?

Hallo,

ja natürlich, habe vergessen DDRB auf DDRC um zu schreiben.

Krapao schrieb:
>>  DDRB  |=   1<<PC1;  <========== Copy&Paste FEhler? #1
>>  DDRB  |=   1<<PC0;  <========== Copy&Paste FEhler? #2

Danach ging eine von zwei LEDs und ich habe den Fehler im Programm 
gesucht...
Naja bis ich dann mal darauf gekommen bin, dass eine LED auf 
Sperrrichtung geschaltet war ist auch ein wenig Zeit vergangen.
1
/*
2
   Testapplication
3
 */
4
int main(void)
5
{
6
7
8
9
10
  DDRB  &= ~(1<<PB0);// active-low Taster an PB0 auf Eingang
11
  PORTB |=   1<<PB0;// Interne Pullups active-low Taster an PB0 an
12
  DDRC  |=   1<<PC1;// LEDs an PC1 auf Ausgang
13
  DDRB  &= ~(1<<PB1);// active-low Taster an PB1 auf Eingang
14
  PORTB |=   1<<PB1;// Interne Pullups active-low Taster an PB0 an
15
  DDRC  |=   1<<PC0;// LEDs an PC0 auf Ausgang
16
  
17
18
  for(;;)
19
  {
20
    if( debounce( PINB, PB0 ) )
21
  {    
22
      PORTC ^= 1<<PC0;    
23
  }
24
25
    if( debounce( PINB, PB1 ) )
26
  {    
27
      PORTC ^= 1<<PC1;
28
  }
29
  }
30
}

So funktioniert es jetzt. Beide LEDs schalten unabhängig voneinander.
Taster drücken => LED an...nochmals drücken LED aus.

Man merkt aber beim drücken eine deutliche Verzögerung, was auf dauer 
recht nervig sein kann ;D

Peter Dannegger schrieb:
> Nimm 2 LEDs und 2 Tasten, können aber auch mehr sein.
> Beim Drücken einer Taste wechselt die dazu gehörende LED.
> Beim gedrückt Halten, Loslassen oder ungedrückt passiert nichts.
> Jede Taste arbeitet unabhängig. Also auch wärend die andere Taste
> gedrückt gehalten wird, funktioniert sie.

Diese Aufgabe habe ich dann somit erstmal geschafft.

Danach habe ich mich nochmal ran gesetzt und das Zählen mit einbezogen.
Bei jedem Tastendruck wird nun gleichzeitig mit hochgezählt und das 
Ergebnis auf dem LCD ausgegeben.
Beide Taster arbeiten immer noch völlig unabhängig voneinander.
Dies ist für mich schon mal ein Fortschritt, da ich mit dieser 
Unabhängigkeit vorher einige Probleme hatte.
Was haltet ihr von meiner Lösung?
1
int main(void)
2
{
3
  lcd_init();
4
  lcd_clear();
5
  char str1[2+1];
6
  char str2[2+1];
7
  char counter1 = 0;
8
  char counter2 = 0;
9
10
11
  DDRB  &= ~(1<<PB0);// active-low Taster an PB0 auf Eingang
12
  PORTB |=   1<<PB0;// Interne Pullups active-low Taster an PB0 an
13
  DDRC  |=   1<<PC1;// LEDs an PC1 auf Ausgang
14
  DDRB  &= ~(1<<PB1);// active-low Taster an PB1 auf Eingang
15
  PORTB |=   1<<PB1;// Interne Pullups active-low Taster an PB0 an
16
  DDRC  |=   1<<PC0;// LEDs an PC0 auf Ausgang
17
  
18
19
  for(;;)
20
  {
21
    if( debounce( PINB, PB0 ) )
22
  {    
23
      PORTC ^= 1<<PC0;
24
    counter1++;
25
      if( counter1 == 24 )
26
      {
27
        counter1 = 0;
28
      } 
29
      str1[0] = '0' + counter1/10;
30
        str1[1] = '0' + counter1%10;
31
        str1[2] = '\0';
32
    lcd_setcursor (2, 1);
33
        lcd_string(str1);    
34
  }
35
36
    if( debounce( PINB, PB1 ) )
37
  {    
38
      PORTC ^= 1<<PC1;
39
    counter2++;
40
      if( counter2 == 60 )
41
      {
42
        counter2 = 0;
43
      } 
44
      str2[0] = '0' + counter2/10;
45
        str2[1] = '0' + counter2%10;
46
        str2[2] = '\0';
47
    lcd_setcursor (2, 2);
48
        lcd_string(str2);
49
  }
50
  }
51
}

von Krapao (Gast)


Lesenswert?

Sieht gut aus. Du kannst noch Platz einsparen.

Die str-Puffer werden temporär zur Vorbereitung der LCD-Ausgabe benutzt. 
Du brauchst deshalb nur einen.

Man kann sogar hingehen und sich eine Funktion z.B. lcd_zahlausgabe() 
für die Augabe einer zweistelligen Dezimalzahl mit führender Null aufs 
LCD schreiben, die man so aufruft:
1
  lcd_zahlausgabe(counter1, 2, 1);
2
  lcd_zahlausgabe(counter2, 2, 2);

und die diese doppelten Codeteile in main() ersetzt:
1
  char str1[2+1];
2
  char str2[2+1];
3
4
  str1[0] = '0' + counter1/10;
5
  str1[1] = '0' + counter1%10;
6
  str1[2] = '\0';
7
  lcd_setcursor (2, 1);
8
  lcd_string(str1);    
9
10
  str2[0] = '0' + counter2/10;
11
  str2[1] = '0' + counter2%10;
12
  str2[2] = '\0';
13
  lcd_setcursor (2, 2);
14
  lcd_string(str2);

von Jochen (Gast)


Lesenswert?

Hallo Krapao,

dein Vorschlag hört sich sehr gut an, das würde ich gerne umsetzen.
Hab auch schon ein bisschen herumgetürftelt, bin mir aber mit der
lcd_zahlausgabe() nicht ganz sicher, wie man diese Funktion beschreibt.
Wäre nett, wenn du es nochmal genauer erläutern könntest.

von Krapao (Gast)


Lesenswert?

Wie muss eine Funktion lcd_zahlausgabe geschrieben werden, damit die 
for-Schleife in main() später wie unten gezeigt aussieht, aber die 
gleiche Arbeitsweise (formatierte und positionierte LCD-Ausgabe) hat wie 
im Beitrag "Re: Uhrzeit stellen" vorhanden ist?

1
  for(;;)
2
  {
3
    if( debounce( PINB, PB0 ) )
4
    {    
5
      PORTC ^= 1<<PC0;
6
      counter1++;
7
      if( counter1 == 24 )
8
      {
9
        counter1 = 0;
10
      } 
11
      lcd_zahlausgabe(counter1, 2, 1);
12
    }
13
14
    if( debounce( PINB, PB1 ) )
15
    {    
16
      PORTC ^= 1<<PC1;
17
      counter2++;
18
      if( counter2 == 60 )
19
      {
20
        counter2 = 0;
21
      } 
22
      lcd_zahlausgabe(counter2, 2, 2);
23
    }
24
  }

von Peter D. (peda)


Lesenswert?

Jochen schrieb:
> Man merkt aber beim drücken eine deutliche Verzögerung, was auf dauer
> recht nervig sein kann ;D

Dann stimmt Deine F_CPU nicht mit der wirklichen Frequenz überein.
25ms merken vielleicht gerade mal Power-Gamer.


Peter

von Timo (Gast)


Lesenswert?

Jochen schrieb:
> Die Uhr lief bis jetzt sowieso nicht genau. Ein 8MHz Quarz ist
> angeschlossen, jedoch dauert eine Sekunde auf dem Display in
> Wirklichkeit 5 Sekunden.

Peter Dannegger schrieb:
> Dann stimmt Deine F_CPU nicht mit der wirklichen Frequenz überein.

So wird es wohl sein. Und 125 ms sind schon eher fühlbar.

Die  Quarzfrequenz von 8MHz muß als unsigned long angegeben werden, also
#define XTAL  8000000UL            // Taktangabe

von Jochen (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Dann stimmt Deine F_CPU nicht mit der wirklichen Frequenz überein.
> 25ms merken vielleicht gerade mal Power-Gamer.


Ja da habt ihr beiden recht. Habe bis Dato bei Fuses immer 1 MHz 
eingestellt.
Nun mal 8MHz Start up Time: 6CK +0ms. Benutze AVR Studio4.

Die Uhr läuft deutlich schneller und die Taster sind somit auch perfekt 
eingestellt.

Habe momentan nicht so viel Zeit, um die lcd_zahlausgabe werde ich mich 
erst heute Abend kümmern können.

von Jochen (Gast)


Lesenswert?

Krapao schrieb:
> Wie muss eine Funktion lcd_zahlausgabe geschrieben werden, damit die
> for-Schleife in main() später wie unten gezeigt aussieht, aber die
> gleiche Arbeitsweise (formatierte und positionierte LCD-Ausgabe) hat wie
> im Beitrag "Re: Uhrzeit stellen" vorhanden ist?


Hi Krapao, habe gerade 5min Zeit mich mal ranzusetzen. So weit wie von 
dir beschrieben war ich gestern auch schon.
hab trotzdem noch Gedankenlücken^^
Muss man evtl. mit Arrays arbeiten? Oder wird es auch anders gehen?

Gruß

von Jochen (Gast)


Lesenswert?

Krapao schrieb:
> Man kann sogar hingehen und sich eine Funktion z.B. lcd_zahlausgabe()
> für die Augabe einer zweistelligen Dezimalzahl mit führender Null aufs
> LCD schreiben

Hi, ich muss passen. Bekomme nur Murks raus. Ich denke ich mache einfach 
grundlegende Fehler beim erstellen der Funktion. Es wird ja sicher nicht 
damit getan sein einfach das zu schreiben

lcd_zahlausgabe();

und dann zwischen den Klammern einige Anweisungen zu geben was die 
Funktion tun soll. bei mir fängt es ja schon mit counter1 und counter2 
an. Wie erkläre ich der Funktion, dass es mehrere char counter1....2 
gibt?


Dies dient natürlich eher zur Verschönerung/Vereinfachung des 
Programmes.
Ich möchte auch noch versuchen meine Entprellten Taster mit der Uhr in 
Verbindung zu kriegen.

Die erste Frage die ich mir dabei wohl stellen muss ist, wie das mit den 
Timern meines Mega8 geregelt wird.

Die Entrpellung nutzt ja
1
#define F_CPU 9.6e6
Die Uhr nutzt aber
1
#define XTAL  8e6                 
2
#define F_CPU  XTAL

Ist es überhaupt wichtig XTAL anzugeben, oder spielt dies keine Rolle?
"Klar denke ich, dass bei dieser Variante der uC weiß, dass er den Takt 
von den XTAL Pins beziehen soll." Aber ob es relevant ist?!?!

Nungut, wie sage ich meinem uC, dass er jene Frequenz für die Uhr nutzen 
soll und die andere für die Entprellung?


Peter Dannegger schrieb:
> Dein unbekannter AVR hat bestimmt mehrere Timer und diese wiederum
> jeweils mehrere Compare-Interrupts.
> Du kannst also haufenweise verschiedene Timerintervalle erzeugen.
>
> Aber auch mit nur einem Timer geht das. Das kürzere Intervall legt man
> einfach so, daß das längere durch ein Vielfaches erzeugt werden kann (=
> Zählvariable). Und die Entprellzeit benötigt ja keinen exakten Wert,
> irgendwas im Bereich 5..50ms ist ok.


Ich würde es natürlich gerne über zwei verschiedene Timer versuchen, 
wenn dann soll es ja richtig gemacht werden.

Auf der anderen Seite müsste ich dann ja nur den Entprellcode an die 
8MHz anpassen richtig?




schöne Grüße und ein herzliches Dankeschön an alle die mich hier 
unterstützen, ist wirklich sehr sehr hilfreich!

von Jochen (Gast)


Lesenswert?

Hallo,

ich habe es mit der lcd_zahlausgabe zwar nicht hinbekommen, dennoch am 
Programm weiter gearbeitet.

Habe nun die Uhr und die Entprellung miteinander verschmolzen.

einen int uhrstellen habe ich auf Taster 3 gelegt. wenn dieser aktiviert 
wird, stellt er uhrstellen auf true und ich kann meine Uhr einstellen. 
Bei einer weiteren betätigung stelle ich diesen wieder auf false und die 
Uhr läuft mit den einstellungen die man mit Taster1 und 2 gemacht hat.

Hier mal der Code!
Bin mal auf eure Meinungen gespannt. Verbesserungsvorschläge sind wie 
immer willkommen ;)
1
int main(void)
2
{
3
  lcd_init();
4
  lcd_clear();
5
  char str[2+1];
6
7
  char hr = 0;
8
  char min = 0;
9
  int  uhrstellen=0;
10
11
12
  DDRB  &= ~(1<<PB0);// active-low Taster an PB0 auf Eingang
13
  PORTB |=   1<<PB0; // Interne Pullups active-low Taster an PB0 an
14
  DDRC  |=   1<<PC1; // LEDs an PC1 auf Ausgang
15
  DDRB  &= ~(1<<PB1);// active-low Taster an PB1 auf Eingang
16
  PORTB |=   1<<PB1; // Interne Pullups active-low Taster an PB0 an
17
  DDRC  |=   1<<PC0; // LEDs an PC0 auf Ausgang
18
19
  TIMSK |= _BV(TOIE1);   // aktivate overflow interrupt of timer1 
20
  TCCR1B |= (1<<CS12);  // prescaler = 256
21
  TCNT1 = 0xFFFF;     // FFFF for start 
22
  lcd_init();
23
  lcd_setcursor(1,1);
24
  lcd_string("00:00:00");
25
  sei();
26
27
28
29
30
  while(1)
31
  {
32
  if(debounce( PINB, PB2 )) //Taster3
33
  {
34
      uhrstellen = 1<<uhrstellen;
35
  }
36
  if(uhrstellen==1)
37
  {
38
39
//Uhrzeit stellen
40
    if( debounce( PINB, PB0 ) )//Taster1
41
    {    
42
      PORTC ^= 1<<PC0;
43
      hr++;
44
      if( hr == 24 )
45
      {
46
        hr = 0;
47
      } 
48
      str[0] = '0' + hr/10;
49
      str[1] = '0' + hr%10;
50
      str[2] = '\0';
51
      lcd_setcursor (1, 1);
52
      lcd_string(str);    
53
    }
54
    if( debounce( PINB, PB1 ) )//Taster2
55
    {    
56
      PORTC ^= 1<<PC1;
57
      min++;
58
      if( min == 60 )
59
      {
60
        min = 0;
61
      } 
62
      str[0] = '0' + min/10;
63
      str[1] = '0' + min%10;
64
      str[2] = '\0';
65
      lcd_setcursor (4, 1);
66
      lcd_string(str);
67
   
68
  }
69
  }
70
//Uhrzeit stellen ENDE
71
else
72
{
73
uhrstellen = 0;
74
75
//*************UHR****************
76
        sec=tc;
77
    if(sec==60)
78
    {
79
       tc=0;
80
       sec=0;
81
       min++;
82
       if(min==60)
83
       {
84
          min=0;
85
        hr++;
86
        if(hr==24)
87
        {
88
           hr=0;
89
           }
90
       }
91
       sprintf(str,"%02d",min);
92
       lcd_setcursor (4, 1);
93
       lcd_string(str);
94
95
       sprintf(str,"%02d",hr);
96
       lcd_setcursor (1, 1);
97
       lcd_string(str);
98
     }
99
     sprintf(str,"%02d",sec);
100
     lcd_setcursor (7, 1);
101
     lcd_string(str);
102
//********************************
103
104
  }
105
  }
106
107
108
}

von Jochen (Gast)


Lesenswert?

Hm.. interessiert sich wohl niemand mehr für^^ Naja aber ich denke ich 
habe das geschafft, was ich schaffen wollte. Natürlich mit eurer Hilfe!

Vielen dank nochmals und gehabt euch wohl :)

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.