Forum: Mikrocontroller und Digitale Elektronik Timer1 / Sekundentakt Problem


von Matthias T. (matthias_199)


Lesenswert?

Ja also ich hab mein Counter mal zur Uhr umgebaut.
Jetzt habe ich aber Probleme einen gescheiten Sekundentakt zu erstellen.
Ich muss feststellen von Minute zu Minute läuft meine AVR Uhr mehr vor 
im vergleich zur Windows Uhr
Ich häng mal den Quellcode ran.
Wobei ich mal auch die Rechnung darstellen will vlt habe ich ja da einen 
Denkfehler
1
$regfile "m8def.dat"
2
$crystal = 4000000
3
Config Portd = Output
4
Config Portb.0 = Input
5
Config Portb.1 = Output
6
Config Portb.2 = Output
7
Config Portb.3 = Output
8
Config Portb.4 = Output
9
Config Portb.5 = Output
10
Portb.5 = 0
11
Portb.0 = 1
12
Dim H_h As Byte
13
Dim H_l As Byte
14
Dim M_h As Byte
15
Dim M_l As Byte
16
Dim Sekunden As Byte
17
H_h = 1
18
H_l = 8
19
M_h = 2
20
M_l = 6
21
Sekunden = 0
22
Dim Ziffercounter As Byte
23
Ziffercounter = 0
24
Dim Pressed As Bit
25
Pressed = 0
26
Dim Dis(10) As Byte
27
Dis(1) = &B00000010
28
Dis(2) = &B11101010
29
Dis(3) = &B00110000
30
Dis(4) = &B10100000
31
Dis(5) = &B11001100
32
Dis(6) = &B10000101
33
Dis(7) = &B00000101
34
Dis(8) = &B11100010
35
Dis(9) = &B00000000
36
Dis(10) = &B10000000
37
Portd = &B11111111
38
39
Config Timer0 = Timer , Prescale = 64
40
Enable Timer0
41
On Timer0 Anezige_aktuall
42
43
Config Timer1 = Timer , Prescale = 64
44
Enable Timer1
45
On Timer1 Sekundenx
46
Timer1 = 3036
47
Enable Interrupts
48
49
50
Do
51
   If Sekunden = 60 Then
52
      Sekunden = 0
53
      Incr M_l
54
   End If
55
   If M_l = 10 Then
56
      M_l = 0
57
      Incr M_h
58
   End If
59
   If M_h = 6 Then
60
      M_h = 0
61
      Incr H_l
62
   End If
63
   If H_l = 10 Then
64
      H_l = 0
65
      Incr H_h
66
   End If
67
   If H_h = 2 And H_l = 4 Then
68
      H_h = 0
69
      H_l = 0
70
      M_h = 0
71
      M_l = 0
72
   End If
73
Loop
74
75
76
Sekundenx:
77
   Timer1 = 3036
78
   Toggle Portb.5
79
   Incr Sekunden
80
Return
81
82
83
Anezige_aktuall:
84
   If Ziffercounter = 4 Then Ziffercounter = 0
85
   Incr Ziffercounter
86
   Select Case Ziffercounter
87
      Case 1:
88
         Portb.1 = 0
89
         Portb.2 = 1
90
         Portb.3 = 1
91
         Portb.4 = 1
92
         Portd = Dis(h_h + 1)
93
94
      Case 2:
95
         Portb.1 = 1
96
         Portb.2 = 0
97
         Portb.3 = 1
98
         Portb.4 = 1
99
         Portd = Dis(h_l + 1)
100
101
      Case 3:
102
         Portb.1 = 1
103
         Portb.2 = 1
104
         Portb.3 = 0
105
         Portb.4 = 1
106
         Portd = Dis(m_h + 1)
107
      Case 4:
108
         Portb.1 = 1
109
         Portb.2 = 1
110
         Portb.3 = 1
111
         Portb.4 = 0
112
         Portd = Dis(m_l + 1)
113
   End Select
114
Return

Und zwar mein AVR läuft mit 4MHz = 4000000Hz.
Also 4 Millionen Takte pro Sekunde.
Mein Prescale ist 64.
Daraus folgt:
4000000Hz / 64 = 62500Hz
Also zählt der Timer1 in einer Sekunde bis auf 62500.
Timer1 hat 16 Bit bzw. 2 Byte das heißt er kann nur bis 65535 zählen.
Da ich jetzt genau jede Sekunde ein Interrupt will lade ich 65535 – 
62500 = 3035
Am Anfang in den Timer1 und bei jedem Überlauf.
Stimmt das oder hab ich was übersehen ?

MFG Matthias

von Paul Baumann (Gast)


Lesenswert?

Erhöhe mal den Vorteiler von Timer 1 auf 256.

Beispiel:
' ******************1Hz mit Timer1 erzeugen by Paul Baumann

'
$regfile = "m8def.dat"
$crystal = 4000000            'Quarz: 4 MHz
Config Pinb.7 = Output

Dim Ftoggle As Bit            'Schnaggelt bei jedem Interrupt



On Timer1 Ontimer1            'Interrupt-Routine für Timer1Overflow
Config Timer1 = Timer , Prescale = 256       'Takt: Quarz/256=15625Hz
Enable Timer1                 'Timer1-Overflow-Interrupt einschalten
Enable Interrupts             'Interrupts global zulassen
Timer1 = 49911                'Abstand=65536-49911=15625

Do
    'Hier könnte man eine Uhr realisieren, wenn man nur wollte...;-)
Loop


Ontimer1:                     'Interrupt-Routine
  Timer1 = 49911              'Timer 1 wieder voreinstellen
  Ftoggle = Not Ftoggle       'Toggle-Bit invertieren
  Portb.7 = Ftoggle           'Leuchtidiot als Anzeige
                                                             'für die 
Sekunden
Return                        'und zurück vom Interrupt
' **** END OF PROGRAM

von holger (Gast)


Lesenswert?

>Da ich jetzt genau jede Sekunde ein Interrupt will lade ich 65535 –
>62500 = 3035
>Am Anfang in den Timer1 und bei jedem Überlauf.

Nimm den CTC Modus vom Timer. Das neue laden des Timers
kostet Zeit, und die geht dir verloren.

von spess53 (Gast)


Lesenswert?

Hi

Was soll denn dieses blöde Vorgelade? CTC sollte doch auch mit BASCOM 
möglich sein.

MfG Spess

von Paul Baumann (Gast)


Lesenswert?

Holger schrob:
>Das neue laden des Timers kostet Zeit, und die geht dir verloren.

Er hat ja Zeit, wenn er den Timer nicht so hoch taktet und den Vorteiler
größer wählt.

Die Takterzeugung mit meinen Werten arbeitet in meiner Uhr so genau, daß 
ich sie nur zur Sommerzeitumstellung anfassen muß.

MfG Paul

von holger (Gast)


Lesenswert?

>Da ich jetzt genau jede Sekunde ein Interrupt will lade ich 65535 –
>62500 = 3035

Es müssen aber 65536 – 62500 = 3036 sein.
Deshalb läuft deine Uhr zu schnell.

von holger (Gast)


Lesenswert?

>Es müssen aber 65536 – 62500 = 3036 sein.

Upps, machst du ja. Verwendest du den Int RC Osci?
Der taugt nicht für ne Uhr.

von Paul Baumann (Gast)


Lesenswert?

Spess schrob:
>CTC sollte doch auch mit BASCOM möglich sein.

Ja, das ist auch möglich, aber nicht mit den vorgefertigten Config-
Möglichkeiten. Man muß sich dann alle Register, die damit zusammenhängen
aus dem Datenblatt heraussuchen und die entsprechenden Bits darin "von 
Hand" setzen.

Klar hat der CTC_Modus mehr Möglichkeiten, sich alle möglichen Zeiten
von einem Timer abzuleiten, aber für diese Aufgabe hier braucht er
doch nur den Sekundentakt und für das Multiplexen der Anzeige hat er
doch den Timer 0 genommen, der sonst nur faul herumläge.

mfG Paul

von Matthias T. (matthias_199)


Lesenswert?

Danke für alle Vorschläge und Hilfen.
Es geht jetz mit  Paul Baumann methode.

Ich dachte je höher der prescale desto genauer :D stimmt wohl ned

von MWS (Gast)


Lesenswert?

Paul Baumann schrieb:
> Ja, das ist auch möglich, aber nicht mit den vorgefertigten Config-
> Möglichkeiten. Man muß sich dann alle Register, die damit zusammenhängen
> aus dem Datenblatt heraussuchen und die entsprechenden Bits darin "von
> Hand" setzen.

Da spricht der Bascom-Unsachverständige :D

Klar geht das:
1
Config Timer1 = Timer , ... , Clear Timer = 1, ...

von Matthias T. (matthias_199)


Lesenswert?

Kannte dan auch ein beispiel geben wie man den wert setzt bei dem er 
neustarten soll? bzw wenn er neustartet tut der dan die routine 
ausführen?

von MWS (Gast)


Lesenswert?

Matthias T. schrieb:
> Kannte dan auch ein beispiel geben wie man den wert setzt bei dem er
> neustarten soll? bzw wenn er neustartet tut der dan die routine
> ausführen?

Und wie lautet die Frage in Deutsch ?

Egal, ob man die Register "zu Fuß" oder per Clear Timer = ... einstellt, 
immer ist CompareXA für den Top-Wert zuständig.

Die zuständige ISR lautet dann für diesen Fall entsprechend:
1
On Compare1A Anezige_aktuall
Der Rest ist einfach selbst zusammenzustellen.

von Paul Baumann (Gast)


Lesenswert?

@MWS

Bleib mal ganz gelöst, Zarter! Immerhin habe ich ein funktionsfähiges
Beispiel geliefert. Das steht bei Dir noch aus. Diesen Parameter
"clear Timer..." gibt es wahrscheinlich auch noch nicht allzu lange.

;-)
MfG Paul

von spess53 (Gast)


Lesenswert?

Hi

>Diesen Parameter
>"clear Timer..." gibt es wahrscheinlich auch noch nicht allzu lange.

Mindestens seit 2008.

MfG Spess

von Matthias T. (matthias_199)


Lesenswert?

Jetz bin ich ratlos,
Das ist der momentane code.
1
$regfile "m8def.dat"
2
$crystal = 4000000
3
Config Portd = Output
4
Config Portb.0 = Input
5
Config Portb.1 = Output
6
Config Portb.2 = Output
7
Config Portb.3 = Output
8
Config Portb.4 = Output
9
Config Portb.5 = Output
10
Portb.5 = 0
11
Portb.0 = 1
12
Dim H_h As Byte
13
Dim H_l As Byte
14
Dim M_h As Byte
15
Dim M_l As Byte
16
Dim Sekunden As Byte
17
H_h = 2
18
H_l = 1
19
M_h = 1
20
M_l = 5
21
Sekunden = 0
22
Const Timerstart = 50100
23
Dim Toggelbit As Bit
24
Toggelbit = 0
25
Dim Ziffercounter As Byte
26
Ziffercounter = 0
27
Dim Pressed As Bit
28
Pressed = 0
29
Dim Dis(10) As Byte
30
Dis(1) = &B00000010
31
Dis(2) = &B11101010
32
Dis(3) = &B00110000
33
Dis(4) = &B10100000
34
Dis(5) = &B11001100
35
Dis(6) = &B10000101
36
Dis(7) = &B00000101
37
Dis(8) = &B11100010
38
Dis(9) = &B00000000
39
Dis(10) = &B10000000
40
Portd = &B11111111
41
42
Config Timer0 = Timer , Prescale = 64
43
Enable Timer0
44
On Timer0 Anezige_aktuall
45
46
Config Timer1 = Timer , Prescale = 256 , Clear Timer = 1
47
Compare1a = 15625
48
On Compare1a Sekundenx
49
Enable Compare1a
50
Enable Timer1
51
'On Timer1 Sekundenx
52
Enable Interrupts
53
54
55
Do
56
   If Sekunden = 60 Then
57
      Sekunden = 0
58
      Incr M_l
59
   Elseif M_l = 10 Then
60
      M_l = 0
61
      Incr M_h
62
   Elseif M_h = 6 Then
63
      M_h = 0
64
      Incr H_l
65
   Elseif H_l = 10 Then
66
      H_l = 0
67
      Incr H_h
68
   Elseif H_h = 2 And H_l = 4 Then
69
      H_h = 0
70
      H_l = 0
71
      M_h = 0
72
      M_l = 0
73
   End If
74
Loop
75
76
77
Sekundenx:
78
   Toggle Toggelbit
79
   Incr Sekunden
80
Return
81
82
83
Anezige_aktuall:
84
85
   If Ziffercounter = 4 Then Ziffercounter = 0
86
   Incr Ziffercounter
87
   Portd = &B11111111
88
   Portb.5 = 1
89
   Select Case Ziffercounter
90
      Case 1:
91
         Portb.1 = 0
92
         Portb.2 = 1
93
         Portb.3 = 1
94
         Portb.4 = 1
95
         Portd = Dis(h_h + 1)
96
         Portb.5 = 1
97
      Case 2:
98
         Portb.1 = 1
99
         Portb.2 = 0
100
         Portb.3 = 1
101
         Portb.4 = 1
102
         Portd = Dis(h_l + 1)
103
         Portb.5 = Toggelbit
104
      Case 3:
105
         Portb.1 = 1
106
         Portb.2 = 1
107
         Portb.3 = 0
108
         Portb.4 = 1
109
         Portd = Dis(m_h + 1)
110
         Portb.5 = 1
111
      Case 4:
112
         Portb.1 = 1
113
         Portb.2 = 1
114
         Portb.3 = 1
115
         Portb.4 = 0
116
         Portd = Dis(m_l + 1)
117
         Portb.5 = 1
118
   End Select
119
Return

Und sie fängt wieder an vorzulaufen ... XD`?
es fällt aber erst nach 2-3 min auf, so 1-2 sec

von spess53 (Gast)


Lesenswert?

Hi

>Compare1a = 15625

Muss 15624 sein. Ausserdem ist dir schon gesagt worden, das der interne 
Oszillator nicht sonderlich genau ist.

MfG Spess

von Paul Baumann (Gast)


Lesenswert?

Spess schrob:
>Mindestens seit 2008.

Ach, das weißt Du?

>CTC sollte doch auch mit BASCOM möglich sein.

und das weißt Du nicht? Seltsam...

Der Vollständigkeit halber sollte nicht der Hinweis fehlen, daß man
dann aber auch noch den Parameter "Disconnect" bei der Timerinitiali-
sierung angeben muß, damit die Portpins PB1 bzw. PB2 nicht vom Timer1
"erschüttert" werden. Die sind in obigem Programm benutzt und würden
seine Anzeige "kaputtmachen"

Hier gilt wieder das Sprichwort:
Tu Niemand Gutes, dann geschieht Dir nichts Böses.

Paul

von Matthias T. (matthias_199)


Lesenswert?

Okey also soll ich mir am besten mal morgen einen externen Oszillator 
holen?

von MWS (Gast)


Lesenswert?

Paul Baumann schrieb:
> Bleib mal ganz gelöst, Zarter! Immerhin habe ich ein funktionsfähiges
> Beispiel geliefert. Das steht bei Dir noch aus. Diesen Parameter
> "clear Timer..." gibt es wahrscheinlich auch noch nicht allzu lange.

Was ist denn das für ein warmes Geschwätz ?
Für so einen Standard-Parameter muss man niemand Code vorkauen.

Gib einfach zu, daß Du keine Ahnung hast und gut ist's :D

von spess53 (Gast)


Lesenswert?

Hi

>Spess schrob:
>>Mindestens seit 2008.

>Ach, das weißt Du?

Ja. Habe hier eine fast neuwertige bzw. unbenutzte Version aus dieser 
Zeit auf meinem Rechner. Hatte ich allerdings nur um mal spaßenshalber 
heruntergeladen um die 4K-Grenze zu knacken. War relativ simpel. Danach 
hatte sich BASCOM für mich erledigt.

>>CTC sollte doch auch mit BASCOM möglich sein.
>und das weißt Du nicht? Seltsam...

Entschuldige, ich benutze BASCOM nicht. Das es über direkten 
Registerzugriff möglich ist, ist mir klar. Allerdings hatte ich keine 
Lust für andere herauszufinden, wie 'Clear Timer = 1' wirklich 
funktioniert.

Meine eher dürftigen BASCOM-Kenntnisse (gilt auch für C) nutze ich 
eigentlich hier um Leuten zu helfen. Willst du mir das jetzt ankreiden?

MfG Spess

von Paul Baumann (Gast)


Lesenswert?

MWS schrob:
>Gib einfach zu, daß Du keine Ahnung hast und gut ist's :D

Na gut: Ich gebe zu, daß Du keine Ahnung hast.
Grins

Ich kann nicht sämtliche Parameter für alle Befehle im Kopf haben,
zumal sie ständig erweitert werden. Es gibt Befehle, die ich noch nie
genutzt habe. Wenn Du ehrlich bist, dann mußt Du das auch von Dir selbst 
sagen.

Spess schrob:
>....nutze ich eigentlich hier um Leuten zu helfen. Willst du mir das >jetzt 
ankreiden?

Nein, ganz bestimmt nicht. Auch ich habe nur geholfen, aber mir ist 
das
angekreidet worden.

Letzten Endes lag es doch daran, daß der TO mit dem internen Oszillator
gearbeitet hat.

Nichts für ungut
MfG Paul

von MWS (Gast)


Lesenswert?

Paul Baumann schrieb:
> Ich kann nicht sämtliche Parameter für alle Befehle im Kopf haben,
> zumal sie ständig erweitert werden.

Der Fehler ist, daß Du:

1) etwas als bestimmt behauptest, obwohl Du Dich mit geringem Aufwand 
(Lesen der Hilfe, bzw. timer1.bas im Samples-Verzeichnis) vom Gegenteil 
hättest überzeugen können.

2) Du dann denkst, daß mit der Kopf-durch-die-Wand Methode das Gesicht 
zu wahren ist.

Klappt aber Beides so nicht. Das hat schon bei Tschernobyl nicht 
hingehauen.

> Es gibt Befehle, die ich noch nie genutzt habe. Wenn Du ehrlich bist,
> dann mußt Du das auch von Dir selbst sagen.

Wenn ich einen Befehl bisher nicht verwendet habe, bin ich vorsichtig 
mit zu bestimmten Aussagen. Bei Clear Timer handelt es sich zudem um 
Standardfunktionalität, da greift das "noch nie genutzt" Argument nicht.

Eben hattest Du die Erde noch als Scheibe betrachtet, obwohl sie's nicht 
war. Also versuch' nicht rumzureden, sondern trag' Deine Unwissenheit 
mit Anstand.

von Paul Baumann (Gast)


Lesenswert?

> Also versuch' nicht rumzureden, sondern trag' Deine Unwissenheit
>mit Anstand.

Ich habe schon Sachen vergessen, die Andere noch nie gewußt haben.

Du suchst Stunk. Ich helfe Dir nicht dabei.

...und ab dafür

Paul

von MWS (Gast)


Lesenswert?

Paul Baumann schrieb:
> Du suchst Stunk. Ich helfe Dir nicht dabei.

Nö, Du warst nur so peinlich bemüht Deinen Fehler zu vertuschen, daß Du 
Dir meine Antwort redlich verdient hast :D

Aber zweckfrei Dir das weiter erklären zu wollen.

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.