Forum: Compiler & IDEs Timer1 Läuft nicht richtig


von Richard Brose (Gast)


Lesenswert?

Hallo Leute,

ich baue eine Uhr die Relativ genau gehen soll.
Mit dem Sourcecode ist eine Sekunde leider 16 Sekunden lang ;-(
Was mache ich falsch?
Benutze einen ATINY2313-20PU mit 16 Mhz extern Quarz.

Danke für die hilfe

Hier der Sourcecode:




#include <main.h>
#include <lcd.c>


 uint8_t second=0;
 uint8_t secled=0;
 uint8_t minute=0;
 uint8_t hour=0;

SIGNAL (SIG_OVERFLOW1)
{
   second ++;
   if(second == 60)
   {
      second = 0;
      minute ++;
   };
   if(minute == 60)
   {
      minute = 0;
      hour ++;
   };
   if(hour == 24)
   {
      hour = 0;
   };

};

//Hauptprogramm
int main (void)
{

  DDRD  = 0x00; /* alle Pins von Port D als Eingang */
  PORTD = 0xff; /* interne Pull-Ups an allen Port-Pins aktivieren */

  //Initzialisierung des LCD - Displays
  LCD_Init();
  LCD_Print(1,0,"Clock");

   OCR1AL = 0x09;
   OCR1AH = 0x3d;
   TCNT1L = 0xf7;
   TCNT1H = 0xc2;
   TCCR1B |= (1<<CS10)|(1<<CS12); //1024
   TIMSK |= (1 << TOIE1);
   sei();

  unsigned char count;
  //Hauptprogramm läuft ständig in einer schleife
  while (1)
    {
    /*       if ( !(PIND & (1<<PIND4)) ) {
           count++;
         {
         if ( !(PIND & (1<<PIND5)) ) {
           count--;
         { */
        LCD_Print(0,1,"Time: %i:%i:%i",hour,minute,second);
    }
return (1);
};

von Feadi (Gast)


Lesenswert?

Hast Du die Fuses richtig programmiert?
Wenn nicht könnte es sein das Dein Tiny mit dem internen 1MHz Oszi
läuft.

Feadi

von Kai (Gast)


Lesenswert?

Hast du den Prescaler richtig eingestellt? Versuch mal den Prescaler um
den Faktor 16 kleiner zu machen.

von Richard Brose (Gast)


Lesenswert?

@Feadi: Die Fuses sind richtig Programmiert.

@Kai: Wie meinst du es den Prescaler um den Faktor 16 kleiner machen?
Ich habe die Werte für OCR1AL,OCR1AH,TCNT1L,TCNT1H mit dem AvrCalc
berechnet von Jack Tidwell:
http://www.electronics-lab.com/downloads/mcu/002/index.html

von Feadi (Gast)


Lesenswert?

Ich denke es muss so aussehen:

volatile uint8_t second=0;

Du musst alle Variablen die in einem Interrupt geändert werden mit
"volatile" deklarieren.

Sonst fällt mir noch das ein:

SIGNAL (SIG_OVERFLOW1)
{
  // Am ende von dem Signal diesen code plazieren
  // timer = overflow - cpufreq / prescaler
  TCNT1    = 0        - F_CPU   / 1024;
}

Feadi

von Richard Brose (Gast)


Lesenswert?

Ich verstehe nicht warum bei mir 1 Sekunde 10 Sekunde dauert :-(

Wie kann ich nachprüfen mit wieviel Mhz der AVR läuft? Kann man das
irgendwie messen das man 100% sicher ist?

Hab das so gemacht:

#include <main.h>
#include <lcd.c>
//#include <avr/delay.h>


 volatile uint8_t second=0;
 volatile uint8_t minute=0;
 volatile uint8_t hour=0;

SIGNAL (SIG_OVERFLOW1)
{
   second ++;
   if(second == 60)
   {
      second = 0;
      minute ++;
   };
   if(minute == 60)
   {
      minute = 0;
      hour ++;
   };
   if(hour == 24)
   {
      hour = 0;
   };
   TCNT1    = 0        - F_CPU   / 1024;
};

//Hauptprogramm
int main (void)
{

  DDRD  = 0x00; /* alle Pins von Port D als Eingang */
  PORTD = 0xff; /* interne Pull-Ups an allen Port-Pins aktivieren */

  //Initzialisierung des LCD - Displays
  LCD_Init();
  LCD_Print(1,0,"Clock");

    OCR1AL = 0x09;
    OCR1AH = 0x3d;
    TCNT1L = 0xf7;
    TCNT1H = 0xc2;
    TCCR1B |= (1<<CS10)|(1<<CS12); //1024
    TIMSK |= (1 << TOIE1);
    sei();

  unsigned char count;
  //Hauptprogramm läuft ständig in einer schleife
  while (1)
    {
        LCD_Print(0,1,"Time: %i:%i:%i",hour,minute,second);
        //_delay_ms(100);
    }
return (1);
};





main.h


#ifndef MAIN_H
 #define MAIN_H

#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

#include "lcd.h"

#define SYSCLK  16000000  //Quarz Frequenz in Hz
#define F_CPU 16000000

extern int main (void);

#endif //_MAIN_H_

von Hubert.G (Gast)


Lesenswert?

Wieso beschreibst du das Timerregister TCNT1? Sollte das nicht bei 0
starten und bei erreichen des OCR1A einen ISR auslösen?

von Hubert.G (Gast)


Lesenswert?

Ausserdem wäre es besser in der ISR nur das second++; zu machen und den
Rest im Main. Hat zwar hier keine Auswirkung, aber man sollte sich von
Anfang an so etwas nicht angewöhnen.

Hubert

von Hubert.G (Gast)


Lesenswert?

Und im TCCR1B gehört auch noch das CTC1 Bit gesetzt

von Richard Brose (Gast)


Lesenswert?

Kann mir hier einer Codebeispiele zeigen? Bin noch ein Anfänger ist
nicht leicht die Tipps einzubauen.

von Hubert.G (Gast)


Lesenswert?

OCR1AL = 0x09;
OCR1AH = 0x3d;

TCCR1B |= (1<<CTC1)|(1<<CS10)|(1<<CS12); //1024
TIMSK |= (1 << TOIE1);
sei();

Initialisiere den Timer mal so. Die letzte Zeile (TCNT1=0....)in der
ISR lass weg. Den Rest aus der ISR kannst du später verlegen wenn es
mal grundsätzlich klappt.
Mit dem selben Takt kannst du auch das LCD ansteuern.

von Richard Brose (Gast)


Lesenswert?

Der hat irgendwie probleme mit CTC1:

Compiling: main.c
avr-gcc -c -mmcu=attiny2313 -I. -g -Os -funsigned-char
-funsigned-bitfields -fpack-struct -fshort-enums -Wall
-Wstrict-prototypes -Wa,-adhlns=main.lst  -std=gnu99 main.c -o main.o
main.c:19: warning: `SIG_OVERFLOW1' appears to be a misspelled signal
handler
main.c: In function `main':
main.c:52: error: `CTC1' undeclared (first use in this function)
main.c:52: error: (Each undeclared identifier is reported only once
main.c:52: error: for each function it appears in.)

von Hubert.G (Gast)


Lesenswert?

Wenn du noch einen älteren Compiler hast ist das WGM12

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.