Forum: Mikrocontroller und Digitale Elektronik ATMega328P Timer1 beeinflusst Timer0 Interrupt


von Holger (Gast)


Angehängte Dateien:

Lesenswert?

Moin,

im Rahmen eines größeren Projektes bin ich auf ein Problem gestoßen, 
welches ich nicht lösen kann.

Ich habe daher mein Projekt eingedampft um das Problem zu verdeutlichen. 
Dieses Programm soll nun auch nicht einen wissenschaftlichen Anspruch 
haben sondern nur das Problem aufzeigen.

Also mit Timer0 sowie zwei Registern erzeuge ich Perioden von ca. 10 
Sekunden Länge. Während dieser Zeit werden drei Register hochgezählt. 
Dies geschieht in der Schleife loop.

Nach ca. zehn Sekunden werden die Zählerwerte ausgegeben.


Als Taktquelle dient ein eingelaufener OCXO mit 10 MHz (9.99999964 MHz).

HTerm_Output_1.PNG zeigt nun, den Output in HTerm. Nach der vierten 
Ausgabe sind die Zählerstände stabil.

Nun zum Problem: Wenn ich diese beiden Zeilen einfüge,
1
  ;*************************
2
  ldi      temp0, (1<<CS12)
3
  sts      TCCR1B, temp0
4
  ;*************************

dann wird ja lediglich für Timer1 die Taktquelle ausgewählt. Es ist 
übrigens egal, welchen Teiler man wählt.

Aber, dann läuft das eigentliche Programm nicht mehr "rund", wie man in 
HTerm_Output_2.PNG sehen kann. Schaut man sich das länger an, dann 
scheinen die Werte zu oszillieren. Ich meine fast schon sägezahnähnlich 
...

Woran kann das liegen?


Gruß
Holger



1
.include "m328Pdef.inc"
2
3
.DEF temp0      = r16
4
.DEF temp1      = r17
5
.DEF temp2      = r18
6
.DEF temp3      = r19
7
.DEF temp4      = r20
8
.DEF temp5      = r21
9
 
10
.equ F_CPU = 10000000
11
12
.equ BAUD  = 9600                               ;Baudrate
13
 
14
; Berechnungen
15
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ;clever runden
16
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ;Reale Baudrate
17
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ;Fehler in Promille
18
 
19
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ;max. +/-10 Promille Fehler
20
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
21
.endif
22
23
.cseg
24
 
25
.org 0x0000
26
     jmp    start
27
28
.org OVF0addr
29
   jmp   timer0_overflow_interrupt
30
31
start:
32
    ;Stackpointer initialisieren 
33
    ldi     temp0, HIGH(RAMEND)
34
    out     SPH, temp0
35
    ldi     temp0, LOW(RAMEND)
36
    out     SPL, temp0
37
   
38
    ;Baudrate einstellen
39
    ldi     temp0, HIGH(UBRR_VAL)
40
    sts     UBRR0H, temp0
41
    ldi     temp0, LOW(UBRR_VAL)
42
    sts     UBRR0L, temp0
43
 
44
    ;Frame-Format: 8 Bit
45
    ldi     temp0, (1<<USBS0)|(1<<UCSZ00)|(1<<UCSZ01)
46
    sts     UCSR0C, temp0
47
 
48
  ;TX, RX und RX-Interrupt aktivieren
49
    ldi     temp0, (1<<TXEN0)
50
  sts     UCSR0B, temp0
51
52
  clr    temp0                
53
  clr    temp1
54
  clr    temp2
55
  clr    temp3
56
  clr    temp4
57
  clr    temp5
58
  
59
  ;TIMER0-stopp
60
  ldi     temp0, (0<<CS02)|(0<<CS01)|(0<<CS00)
61
  out     TCCR0B, temp0
62
  
63
  ;TIMER0-Overflow-Interrupt-Disable
64
  ldi     temp0, (0<<TOIE0)
65
  sts     TIMSK0, temp0
66
  
67
  ;TIMER0 auf 0 setzen
68
  clr     temp0
69
  sts     TCNT0, temp0
70
  
71
72
73
74
75
76
  ;*************************
77
  ldi      temp0, (1<<CS12)
78
  sts      TCCR1B, temp0
79
  ;*************************
80
81
82
83
84
85
86
  ;TIMER0-Prescaler 1024
87
  ldi     temp0, (1<<CS02)|(1<<CS00)
88
  out     TCCR0B, temp0
89
90
  ;TIMER0-Overflow-Interrupt-Enable
91
  ldi     temp0, (1<<TOIE0)
92
  sts     TIMSK0, temp0
93
94
  ;TIMER0 auf 0 setzen
95
  clr     temp0
96
  sts     TCNT0, temp0
97
98
  sei
99
  
100
loop:
101
  inc    temp3
102
  tst    temp3
103
  brne  loop
104
105
  inc    temp4
106
  tst    temp4
107
  brne  loop
108
109
  inc    temp5
110
  rjmp  loop
111
  
112
timer0_overflow_interrupt:
113
  inc    temp1
114
  cpi    temp1, 38
115
  brne  timer0_overflow_interrupt_end
116
  clr    temp1
117
  
118
  inc    temp2
119
  cpi    temp2, 10
120
  brne  timer0_overflow_interrupt_end
121
122
  ;TIMER0-Prescaler 0
123
  ldi     temp0, (0<<CS02)|(0<<CS00)
124
  out     TCCR0B, temp0
125
  
126
  mov    temp0, temp5
127
  rcall  serout_raw
128
  mov    temp0, temp4
129
  rcall  serout_raw
130
  mov    temp0, temp3
131
  rcall  serout_raw
132
  ldi    temp0, 13
133
  rcall  serout_raw
134
  ldi    temp0, 10
135
  rcall  serout_raw
136
  
137
  clr    temp2
138
  clr    temp3
139
  clr    temp4
140
  clr    temp5
141
142
  ;TIMER0 auf 0 setzen
143
  sts     TCNT0, temp0
144
145
  ;TIMER0-Prescaler 1024
146
  ldi     temp0, (1<<CS02)|(1<<CS00)
147
  out     TCCR0B, temp0
148
149
timer0_overflow_interrupt_end:
150
  reti 
151
  
152
serout_raw:
153
  push  temp1
154
155
serout_raw0:
156
  lds    temp1, UCSR0A            ;Warten bis UDRE0 für das nächste
157
                        ;Byte bereit ist
158
  sbrs  temp1, 5              ;UDR0  
159
            
160
    rjmp    serout_raw0
161
162
  sts     UDR0, temp0
163
  pop    temp1
164
    ret                      ;zurück zum Hauptprogramm

von holger (Gast)


Lesenswert?

>Woran kann das liegen?

Warum sicherst du beim Eintritt in den Interrupt das
Statusregister nicht?

von Karl M. (Gast)


Lesenswert?

Hallo,

man muss außerdem noch Fragen, warum auch die verwendeten Register, 
neben dem SRRG, in der ISR nicht gesichert werden?

Warum verwendet man keine Hochsprache ?
Dadurch kommt man schneller ans Ziel und kann einen Code besser warten 
und verstehen.

Über Datentypen und deren Arithmetik muss man sich auch keine weiteren 
Gedanken, hier Programmcode, machen.

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.