-         

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 12

Thema: Kleine Uhr

  1. #1

    Kleine Uhr

    Anzeige

    Hi zusammen,
    Ich wollte ne kleine Uhr programmieren, da ich mich mit den Strings in C nich wirklich auskenne und die nun bissel beherrschen lernen wollte...

    Ich hab jetzt folgenden Code:
    Code:
    #define preValue 57724
    
    int volatile gSeconds = 0;
    
    SIGNAL (SIG_OVERFLOW1) 
      {
    	gSeconds++;
        TCNT1 = preValue;
      }
      
      
    int main (void)
     {
     
    	lcd_init(LCD_DISP_ON);
    
        TCCR1B = (1<<CS12) | (1<<CS10);
        TIMSK |= (1<<TOIE1);
        TCNT1 = preValue;
        sei ();
    	
    	int seconds = 0;
    	int minutes = 0;
    	int hours   = 0;
    	
    	
    	char *sec  = "00";
    	char *min  = "00";
    	char *h    = "00";
    	
    	char *time = "00:00:00";
    	
    	lcd_puts("Time: ");
    	lcd_puts(time);
    	
    	
    	while (1)
    	 {
    		
    		if (seconds != gSeconds)
    		 {
    		   seconds = gSeconds;
    		   
    		   if (seconds == 60) 
    		    {
    			 seconds = 0;
    			 gSeconds = 0;
    			 minutes++;
    			}
    		   if (minutes == 60)
    		    {
    			 minutes = 0;
    			 hours++;
    			}
    		   if (hours == 24) hours = 0;
    		
    			time = "00:00:00";  // Problem hier s.u.
    	          //    01234567
    		   
    		   itoa(seconds, sec, 10);
    		  // itoa(minutes, min, 10);
    		   //itoa(hours,   h,   10);
    		   
    		   
    		   if (seconds < 10)
    		    {
    			 time[6] = "0";  // zweites Problem hier s.u.
    			 time[7] = sec[0];
    			}
    		   else
    		    {
    			 time[6] = sec[0];
    			 time[7] = sec[1];
    			}
    			
    		  /* if (minutes < 10)
    		    {
    			 time[4] = min[0];
    			}
    		   else
    		    {
    			 time[3] = min[0];
    			 time[4] = min[1];
    			}
    			
    		   if (hours < 10)
    		    {
    			 time[1] = h[0];
    			}
    		   else
    		    {
    			 time[0] = h[0];
    			 time[1] = h[1];
    			}*/
    		    
    		   lcd_gotoxy(6,0);
    		   lcd_puts(time);
    		   lcd_gotoxy(0,1);
    		   lcd_puts(sec);
    		 }
    	 }
     }
    Naja, das Problem ist, dass zwar der itoa der Seconds klappt, aber wenn ich die itoa's der Stunden und Minuten nicht auskommentiere, resetet der µC konstant




    Außerdem bringt folgende Zeile hier gar nix:

    Code:
    			time = "00:00:00";  // Problem hier s.u.
    Eigentlich sollte wenn die Seconds wieder bei 0 sind dadurch garantiert werden, dass in der Uhrzeit auch :00 anstatt :50 steht (Die 5 wäre noch aus den 50'er Sekunden geblieben). Ich hoffe ihr versteht was ich meine
    Trotz dieser Zeile, bleibt in den ersten 10 Sekunden jeder neuen Minute die 5 aus den 50'er Sekunden der vorherigen Minute stehen. So als ob die Variable gar nicht refresht wird...

    Time: 00:00:58
    Time: 00:00:59
    Time: 00:00:50
    Time: 00:00:51
    Time: 00:00:...
    Time: 00:00:59
    Time: 00:00:10

    Code:
    			 time[6] = "0";  // zweites Problem hier s.u.
    Ich dachte mir daher: Ach egal, packste halt die Null selber dahin.
    Seltsamerweise sieh die ausgabe dann so aus:
    Time: 00:00:s0
    Time: 00:00:s1
    Time: 00:00:...
    Time: 00:00:s9
    Ich hoffe, jmd hat ne Idee für mich...

    ThxInAdv
    Alex

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    25.09.2004
    Beiträge
    471
    in C kann man Strings nicht einfach durch = "text" zuweisen, sondern muss dies über die Funktion strcpy machen
    strcpy[stringvariable,"text"]
    stringvariable muss dabei ein array sein, dass mindestens um 1 länger als der maximal darin zu speichernde Text ist
    mfg churchi

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    01.06.2005
    Beiträge
    13
    Hi Alex,

    das Arbeiten mit Strings ist, wie churchi schon erläutert hat, für einen Anfänger in der C-Programmierung nicht so ganz einfach. So müsste es aber funktionieren:

    Code:
    #include <stdio.h>
    
    #define preValue 57724
    
    int volatile gSeconds = 0;
    
    SIGNAL (SIG_OVERFLOW1)
    {
      gSeconds++;
      TCNT1 = preValue;
    }
     
     
    int main (void)
    {
      int seconds = 0;
      int minutes = 0;
      int hours   = 0;
      char mytime[] = "00:00:00";
    
    
      lcd_init (LCD_DISP_ON);
    
      TCCR1B = (1<<CS12) | (1<<CS10);
      TIMSK |= (1<<TOIE1);
      TCNT1 = preValue;
      sei ();
       
      lcd_puts ("Time: ");
      lcd_puts (mytime);
       
      while (1)
      {
        if (seconds != gSeconds)
        {
          seconds = gSeconds;
             
          if (seconds == 60)
          {
            seconds = 0;
            gSeconds = 0;
            minutes++;
          }
          if (minutes == 60)
          {
            minutes = 0;
            hours++;
          }
          if (hours == 24)
            hours = 0;
    
          /* Uhrzeit formatieren */
          sprintf (mytime, "%02d:%02d:%02d", hours, minutes, seconds);         
    
          /* und auf dem Display ausgeben */
          lcd_gotoxy (6,0);
          lcd_puts (mytime);
        }
      }
    }
    Die Funktion sprintf() aus der Standard-C-Library wird hier dazu benutzt, den String für die gewünschte Ausgabe zu formatieren.

    Ich hoffe, das hilft Dir ein wenig.

    Gruß, M@nni

  4. #4
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    25.09.2004
    Beiträge
    471
    soweit ich weiß gibt es den sprintf Befehl nur in der avrgcc version und nicht in der winavr?
    bin mir da nicht ganz sicher
    mfg churchi

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    22.11.2003
    Beiträge
    991
    Zitat Zitat von churchi
    soweit ich weiß gibt es den sprintf Befehl nur in der avrgcc version und nicht in der winavr?
    Naja, so groß ist der unterschied zwischen den beiden nicht. WinAVR ist ja im Prinzip nur ein Programmpacket für Windows das avr-gcc benutzt.

    MfG Kjion

  6. #6
    Hi zusammen,
    Ich danke euch - klappt alles perfekt

    Bye
    Alex

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    02.03.2005
    Beiträge
    70
    Hallo,

    Ich habe mal eben das Programm übernommen. Allerdings treten bei mir 2 Fehler auf.

    1. Der Sekundenwert ändert sich bei mir immer erst nach genau 2 Sekunden. Er läuft also nur halb so schnell. Ich nehme mal an, das liegt an meinem externen 4Mhz Quarz. Wie kann ich den richtigen Wert dafür berechnen?

    2. Die Zeit läuft kurze Zeit richtig(bis auf das obige Problem). Danach bleibt der Wert stehen und es tut sich nichts mehr. Nach langem Warten (einige Minuten) bekomme ich wieder eine Anzeige. Die liegt dann irgendwo bei mehreren 100 Sekunden. Das heißt also, dass er anscheinend intern weiterzählt. Dachte erst, es hätte was mit dem Watchdog zu tun, dass kann dann aber eigentlich nicht sein.
    Ebenfalls zählt er die Minuten nicht hoch. if(seconds==60) wird nicht ausgeführt. Nehme mal an, dass liegt daran, dass er den Wert 60 überspringt.

    Kann mir einer vielleicht sagen, woran das liegen kann?

  8. #8
    Neuer Benutzer Öfters hier
    Registriert seit
    01.06.2005
    Beiträge
    13
    Hallo,

    offensichtlich benutzt der ursprüngliche Poster einen AVR, der mit 8 MHz betrieben wird, während Deiner mit 4 MHz läuft. Da der interne Takt zum Zählen benutzt wird, läuft Deine Uhr nur halb so schnell. Die Lösung wäre: ersetze im Programm die Zeile

    #define preValue 57724

    durch

    #define preValue 28862

    Das sollte dann funktionieren.

    Zu Deinem 2. Problem: Vielleicht hilft es, wenn Du den Teil des Programms, der in der Endlosschleife ausgeführt wird, etwas anders schreibst, etwa so:
    Code:
      while (1)
      {
        if (seconds != gSeconds)
        {
          seconds = gSeconds;
             
          if (seconds >= 60)
          {
            seconds -= 60;
            gSeconds = seconds;
            minutes++;
          }
          if (minutes >= 60)
          {
            minutes -= 60;
            hours++;
          }
          if (hours >= 24)
            hours -= 24;
    
          /* Uhrzeit formatieren */
          sprintf (mytime, "%02d:%02d:%02d", hours, minutes, seconds);         
    
          /* und auf dem Display ausgeben */
          lcd_gotoxy (6,0);
          lcd_puts (mytime);
        }
      }
    Sollte das Problem immer noch vorhanden sein, wäre es interessant zu wissen, welchen AVR Du einsetzt.

    Gruß, M@nni

  9. #9
    Benutzer Stammmitglied
    Registriert seit
    02.03.2005
    Beiträge
    70
    @ M@nni
    Danke für die Antwort.
    Wollte vor 2 Stunden deinen Vorschlag ausprobieren. Habe meine Kabel in mein Netzteil gesteckt, und siehe da, nichts funktionierte. Habe nämlich die Stecker vertauscht. Das hat mir anscheinend der 7805 für das Display übelgenommen. Der erzeugte danach um die 8 Volt. Habe mir gerade eine neue Spannungsversorgung zusammengelötet, jetzt allerdings mit Verpolungsschutz.

    Also nun zu obigen Problem. Wenn ich den Wert auf 28862 ändere, braucht er ca. 9s um den Wert zu erhöhen. Habe jetzt einfach mal 64000 eingegeben, dann ändert sich der Wert sehr viel schneller als 1s. Gibt es eigentlich eine Formel, mit der man das Berechnen kann? Ich benutze einen Mega163L mit 4MHz Quarz an einem STK500. Das 2.Problem hat sich soweit behoben. Er zählt bis 59 und addiert dann die Minute. Allerdings bricht das Programm immer noch einfach ab. Bei meinem letzten Test ist er bei den Werten (Zeit) 00:03:24 stehengeblieben.

    Vielen Dank schon mal

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    01.06.2005
    Beiträge
    13
    Hallo,

    oh, anscheinend ist der Zähler so konfiguriert, dass er vorwärts zählt und nicht rückwärts, so wie ich dachte. Habe im Moment leider kein lauffähiges AVR-System, sonst hätte ich das vorher ausprobiert.

    Es handelt sich um einen 16-Bit-Zähler, der von dem voreingestellten Wert (im Programm definiert durch "preValue") ausgehend vorwärts zählt. Wenn der Zähler den Maximalwert von 65535 überschreitet, erzeugt er einen Interrupt. In der Interrupt-Routine wird der Zähler dann wieder mit dem Wert "preValue" geladen.

    Das bedeutet, der Zähler zählt 65536 - preValue = 65536 - 57724 = 7812 Takte bei 8 MHz. In Deinem Fall müsste er bei 4 MHz nur halb so viele Takte, also 7812/2 = 3906 zählen. Du bekommst dann also einen Wert für preValue von 65536 - 3906 = 61630. Probier das mal aus, dann dürfte Deine Uhr in etwa richtig laufen.

    Es kann sein, dass die Uhr nach einiger Zeit etwas vor oder nachgeht. Dann kannst Du den Wert von preValue noch etwas tunen, also etwas erhöhen, wenn die Uhr zu langsam läuft und etwa verringern, wenn sie zu schnell läuft.

    Das mit dem Programmabbruch sollte eigentlich nicht sein, da die Software in einer Endlosschleife läuft. Bricht das Programm immer bei der gleichen Uhrzeit ab oder ist dies unterschiedlich? Evtl. könnte es sich um ein Hardware-Problem handeln, vielleicht das Netzteil.

    Gruß, M@nni

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •