Timer sek zähler

OP #5898184
Lesenswert?
• ▲
▼
Hallo zusammen,


Ich teste gerade ein Programm für den Atmega8 das gewünschte Zeitpausen 
per Timer erzeugt. Im Beispiel unten wird mit dem Timer per Interrupt 
ein 1 sek takt generiert, der wiederum das Zählerregister temp5(r20) bei 
jeder Sekunde erhöht.

Will ich jetzt zum beispiel für eine Funktion 5 Sekunden Wartezeit, muss 
ich nur temp5 mit 0 laden, und warten bis das Register den wert 5 
enthält. Folglich sind 5 Sekunden vergangen.  Das mache ich in der 
Hauptschleifen mit:
1
main:
2

3
cpi     temp5,5 ; 5 Sekunden
4
breq  led_stat
5
rjmp  main
6

7
led_stat:
8

9
sbis  PINC,0
10
sbi  PORTC,0
11
sbic  PINC,0
12
cbi  PORTC,0
13

14
ldi  temp5,0 ; Wieder auf 0 und von vorne...
15

16
rjmp    main

Momentan lasse ich damit noch ein LED blinken, damit ich mit dem Oszi 
den Zeitabstand messen kann.

Leider bekomme ich jedes mal nur den 1Hz Takt auf den Oszi, was ja 
eigentlich nicht sein dürfte, da ja temp5 erst die 5 errechen muss, 
damit led_stat ausgeführt wird. Und ich hab keine Ahnung an was das 
liegen mag.



Noch mein gesamter Testcode...

Atmega läuft mit 4MHz, Fuses (E:FF, H:D9, L:E3)
1
;###########################################################################################################################################################
2
.nolist
3
.include "/home/lukas/Dokumente/AVR/includes/m8def.inc"
4
.list
5

6
;**************************************************************
7
;Registerdefinitionen
8
;**************************************************************
9

10
.def    temp     = r16
11
.def    temp2    = r17
12
.def    temp3    = r18
13
.def    temp4    = r19
14

15
.def   temp5   =r20
16

17
;**************************************************************
18
;Konstanten
19
;**************************************************************
20

21
;~ .equ    PD      = PORTD ;Inerruptsempfang
22

23

24
; SPI
25

26
.equ SS         = 1 ;Output active low
27
.equ SDO        = 0 ;Input
28
.equ SCK        = 2 ;Output
29
.equ SDI        = 3 ;Output
30
.equ LED    = 4 ; LED
31

32
;**************************************************************
33
;SRAM
34
;**************************************************************
35

36
.dseg
37

38
sec_counter:          .BYTE 3
39
ms_counter:          .BYTE 1
40
;~ segment_nr:        .BYTE 1
41

42

43
.cseg
44

45
;**************************************************************
46
;UART
47
;**************************************************************
48

49
;Berechnungen
50
;~ .equ F_CPU = 4000000                            ; Systemtakt in Hz
51
;~ .equ BAUD  = 9600                               ; Baudrate
52

53
;~ .equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
54
;~ .equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate
55
;~ .equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille
56

57
;~ .if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille Fehler
58
  ;~ .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
59
;~ .endif
60

61

62
;**************************************************************
63
;Vektorentabelle
64
;**************************************************************
65

66
.org 0x0000
67
    rjmp    init
68
    
69
.org 0x0009
70
   rjmp  timerB_overflow      
71

72

73
;**************************************************************
74
;Interruptprogramme (Am ende reti)
75
;**************************************************************
76
timerB_overflow: 
77

78

79
push  temp
80
push  temp2
81
push  temp3
82
push  temp4
83

84
; Sekundenroutine
85
lds     temp,sec_counter
86
lds     temp2,sec_counter+1
87

88
ldi     temp3,LOW(1953)
89
ldi     temp4,HIGH(1953)
90

91
cp      temp3,temp
92
cpc     temp4,temp2
93
breq    sec_counter_zero
94

95
ldi     temp3,1 
96
ldi     temp4,0
97

98
add     temp,temp3
99
adc     temp2,temp4
100

101
sts     sec_counter,temp
102
sts     sec_counter+1,temp2
103

104
rjmp    timer0_exit
105

106
sec_counter_zero:
107

108
ldi     temp,0
109
sts     sec_counter,temp
110
sts     sec_counter+1,temp
111

112
inc   temp5
113

114

115

116

117
timer0_exit:
118

119
pop    temp4
120
pop    temp3
121
pop    temp2
122
pop    temp
123
reti
124

125

126
;**************************************************************
127
;Unterprogramme (Am ende ret)
128
;**************************************************************
129

130

131
;**************************************************************
132
;Initialisierung
133
;**************************************************************
134

135
init:
136

137
;Port (Richung & Pegel)
138

139
ldi     temp,0xFF
140
out     DDRC,temp
141

142
ldi     temp,0x00; F = aus 0 = ein
143
out     PORTC,temp
144

145

146
;Stackpointer init
147
ldi         temp,HIGH(RAMEND) ;Stackpointer HIGH
148
out         SPH,temp
149
ldi         temp,LOW(RAMEND)  ;Stackpointer LOW
150
out         SPL,temp
151

152

153
; Init Timer
154

155
ldi       temp,0b00000010 ; Prescaler auf 8
156
out      TCCR0,temp
157

158
ldi      temp,1 << TOIE0
159
out      TIMSK,temp
160

161
ldi     temp,0
162
sts     sec_counter,temp
163
sts     sec_counter+1,temp
164

165
ldi    temp,0
166
sts    ms_counter,temp
167

168
ldi    temp5,0
169

170

171

172
;Interrupts an INT0
173

174
;ldi     temp,(1<<ISC01)|(1<<ISC00) ; INT0 und INT1 auf fallende Flanke konfigurieren
175
;out     MCUCR,temp
176

177
;ldi     temp,0b01000000 ; INT0 aktivieren adresse 0x0001
178
;out     GIMSK,temp
179

180
;ldi     temp,0b01000000 ; INT0 aktivieren adresse 0x0001
181
;out     GIFR,temp
182

183

184
sei ;Interrupts an
185

186

187
;**************************************************************
188
;Hauprogramm
189
;**************************************************************
190

191
main:
192

193

194
cpi    temp5,5
195
breq  led_stat
196
rjmp  main
197

198
led_stat:
199

200
sbis  PINC,0
201
sbi    PORTC,0
202
sbic  PINC,0
203
cbi    PORTC,0
204

205
ldi    temp5,0
206
rjmp    main
OP #5898202
Lesenswert?
• ▲
▼
Es hat tatsächlich daran gelegen....

SREG gesichert und funktioniert wie gewünscht!

Scheinbar hat mir der Timer die Prüfung CPI immer 
unterbrochen/verfälscht.


Kenne zwar die SREG Sicherung bei Interrupts, bis jetzt habe ich sie 
jedoch nur mäßig angewandt. Muss ich wohl in Zukunft Standardmäßig 
einbauen, um Konflikte zu vermeiden.

Schon wieder was gelernt....


Vielen Dank!
Gast #5899936
Lesenswert?
• ▲
▼
SREG sichern ist das eine:
Schön, wenn du das jetzt als "Ohne geht's nicht!" verinnerlicht
hast.

Deine 5 Sekunden Verzögerung sind (unabhängig von SREG & Co.)
vom Prinzip her nur irgendwas von 4...5 Sekunden.

Wenn dir das reicht, OK. Wenn es genauer sein soll, muss dein
Zähler mit Steps von z.B. ms von Null bis 5000 gezählt haben.
Gast #5900073
Lesenswert?
• ▲
▼
Jacko schrieb:
> Wenn dir das reicht, OK. Wenn es genauer sein soll, muss dein
> Zähler mit Steps von z.B. ms von Null bis 5000 gezählt haben.

Meist ist es deutlich günstiger, den Zähler mit dem Wert für die Dauer 
zu initialisieren und dann runter zu zählen. Der Vergleich kann dann 
immer gegen die 0 stattfinden und ist damit unabhängig von der 
gewünschten Verzögerung.
Gast #5900117
Lesenswert?
• ▲
▼
Wolfgang schrieb:
> Meist ist es deutlich günstiger, den Zähler mit dem Wert für die Dauer
> zu initialisieren und dann runter zu zählen.

Ich denke nicht, dass das irgend etwas an der Ungenauigkeit von 4 bis 5 
Sekunden ändert. Auch beim herunterzählen weißt du nicht, wann der erste 
Interrupt stattfindet.
Gast #5901091
Lesenswert?
• ▲
▼
... da kann man viel von der Ungenauigkeit durch viel zu
geringe Zeitauflösung erzählen...

Die Leute, die Erfolgserlebnisse suchen, werden irgendwann schon
durch Erfahrung klüger werden. Bei den anderen ist es eh Wurscht.

- Oder habt ihr jeden Einwand von nörgelnden Lehrern  Eltern 
Tanten beherzigt? DANN wärt ihr jetzt so dumm, wie damals! ;-)

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