Hallo Forum, ich habe folgendes kleines Programm geschrieben.
1
.dseg
2
frequ_hoch:
3
.byte 1
4
frequ_mittel:
5
.byte 1
6
frequ_nieder:
7
.byte 1
8
frequ_hoch_temp_temp:
9
.byte 1
10
frequenz_status:
11
.byte 1
12
zaehl_ergeb_spei:
13
.byte 27
14
zaehl_spei_schr_z:
15
.byte 1
16
17
.cseg
18
frequenzmessen_vor:
19
ldi tmp1,0
20
out TCCR1A,tmp1
21
ldi tmp1,0b00000010
22
out TCCR1B,tmp1
23
;Timer Interupt Mask
24
in tmp1,TIMSK
25
ori tmp1,0b00100100
26
out TIMSK,tmp1
27
ldi tmp1,0
28
sts frequ_hoch,tmp1
29
sts frequ_mittel,tmp1
30
sts frequ_nieder,tmp1
31
ret
32
;----------------------------------
33
frequenz_int1:
34
push tmp6
35
in tmp6,sreg
36
push tmp6
37
38
lds tmp6,frequ_hoch_temp_temp
39
inc tmp6
40
sts frequ_hoch_temp_temp,tmp6
41
42
pop tmp6
43
out sreg,tmp6
44
pop tmp6
45
reti
46
;-----------------------------------
47
frequenz_start_stop:
48
push tmp5
49
push tmp6
50
in tmp6,sreg
51
push tmp6
52
push xl
53
push xh
54
55
lds tmp6,zaehl_spei_schr_z
56
cpi tmp6,27
57
brlo frequenz_start_stop_10
58
ldi tmp6,0
59
60
frequenz_start_stop_10:
61
ldi xl,low(zaehl_ergeb_spei)
62
ldi xh,high(zaehl_ergeb_spei)
63
add xl,tmp6
64
clr tmp5
65
adc xh,tmp5
66
67
in tmp5,TCNT1L
68
rcall frequenz_start_stop_100
69
in tmp5,TCNT1H
70
rcall frequenz_start_stop_100
71
lds tmp5,frequ_hoch_temp_temp
72
rcall frequenz_start_stop_100
73
74
ldi tmp5,0
75
sts frequ_hoch_temp_temp,tmp5
76
sts zaehl_spei_schr_z,tmp6
77
78
pop xh
79
pop xl
80
pop tmp6
81
out sreg,tmp6
82
pop tmp6
83
pop tmp5
84
reti
85
86
frequenz_start_stop_100:
87
st x+,tmp5
88
inc tmp6
89
ret
90
;-----------------------------------
91
92
frequenz_berechnung:
93
ldi xl,low(zaehl_ergeb_spei)
94
ldi xh,high(zaehl_ergeb_spei)
95
mov yl,xl
96
mov yh,xh
97
98
ldi tmp5,3
99
add yl,tmp5
100
clr tmp3
101
adc yh,tmp3
102
103
;Adressen für die indirekten Zeiger sind berechnet
104
frequenz_berechnung_10:
105
ld tmp5,x
106
ld tmp8,y
107
108
adiw x,1
109
adiw y,1
110
111
ld tmp6,x
112
ld tmp9,y
113
114
adiw x,1
115
adiw y,1
116
117
ld tmp7,x
118
ld tmp10,y
119
120
adiw x,1
121
adiw y,1
122
123
sub tmp5,tmp8
124
sbc tmp6,tmp9
125
sbc tmp7,tmp10
126
127
brtc frequenz_berechnung_20
128
neg tmp5
129
neg tmp6
130
neg tmp7
131
132
frequenz_berechnung_20:
133
lds tmp4,frequ_nieder
134
add tmp4,tmp5
135
sts frequ_nieder,tmp4
136
137
lds tmp4,frequ_mittel
138
add tmp4,tmp6
139
sts frequ_mittel,tmp4
140
141
lds tmp4,frequ_hoch
142
add tmp4,tmp7
143
sts frequ_hoch,tmp4
144
145
inc tmp5
146
cpi tmp5,9
147
brsh frequenz_berechnung_40
148
rjmp frequenz_berechnung_10
149
150
frequenz_berechnung_40:
151
ldi tmp5,0
152
153
frequenz_berechnung_50:
154
lds tmp7,frequ_hoch
155
lsr tmp7
156
sts frequ_hoch,tmp7
157
158
lds tmp7,frequ_mittel
159
ror tmp7
160
sts frequ_mittel,tmp7
161
162
lds tmp7,frequ_nieder
163
ror tmp7
164
sts frequ_nieder,tmp7
165
166
inc tmp5
167
cpi tmp5,4
168
brlo frequenz_berechnung_50
169
170
171
frequenz_berechnung_100:
172
ldi tmp3,199
173
rcall frequenz_darstellen
174
ret
In "frequenzmessen_vor" werden Voreinstellungen gemacht.
In "frequenz_int1" wird der Zähler "frequ_hoch_temp_temp" bei jedem
Zähler 1 überlauf um eins erhöht.
In "frequenz_start_stop" wird eine 9 x 3 Tabelle mit den Low und High
Bytes des Zähler 1 und dem Byte "frequ_hoch_temp_temp" gefüllt.
In "frequenz_berechnung" soll nun der Durchschnittswert der Tabelle
berechnet werden. Dazu werden zuerst die einzelnen Dreiergruppen geladen
und voneinander abgezogen. Müßte normalerweise, wenn sich die Frequenz
nicht ändert immer den gleichen Wert ergeben. Die Ergebnisse der
Subtraktion werde aufaddiert und dann durch 8 geteilt. Und das sollte
dann einen Wert ergeben von dem ich die Frequenz berechnen kann. Nur so
weit bin ich noch nicht da dieser Wert schon nicht stabil ist, sondern
im ganzen Bereich umherspringt. Was mach ich falsch?
Vielen Dank im vorraus.
Ich wühl' mich da jetzt nicht durch - aber es hilft ungemein,
Unterprogramme und bei Assembler sogar einzelne Zeilen mit einem
Kommentar zu versehen. Nicht nur für uns Ahnungslose, sondern auch für
dich selber, damit du in 3 Wochen auch noch verstehst, was du da
eigentlich programmiert hast.
Und noch ein Tipp: Wenn du Kontrollstrukturen in z.B. Timerregistern
schreibst, ist solche eine Schreibweise wesentlich besser:
1
ldir16,(1<<COM1A)|(1<<COM1B)
2
outTCCR0A,r16
als das Bitgewurschtel, wo jeder nochmal ins Datenblatt gucken muss, obs
denn auch an der richtigen Stelle ist.
anfänger0815 schrieb:> und voneinander abgezogen. Müßte normalerweise, wenn sich die Frequenz> nicht ändert immer den gleichen Wert ergeben.
Das lässt sich ja testen.
Sind die Werte (im wesentlichen) immer gleich?
Dann wüsste man schon mal, warauf man genauer schauen muss: auf die
Datenerfassung oder die Berechnung.
Auf Deutsch: schau dir halt mal die Werte an, die deine Datenerfassung
liefert. Wenn die schon nicht plausibel sind, dann brauchst du dich erst
mal um die ganze Subtraktion bzw. Mittelwertbildung nicht kümmern. Sind
die Werte aber gut, dann kann man das alles in den Simulator laden und
dort in Einzelschritten nachgehen und die Berechnung kontrollieren.
> in tmp1,TIMSK> ori tmp1,0b00100100> out TIMSK,tmp1
Das eine ist wohl der Overflow Interrupt.
Aber was ist der andere? Ist das ein Capture Interrupt?
Ich hab jetzt ehrlich gesagt keine Lust, mir aus dem Datenblatt
rauszusuchen, welcher Interrupt das ist. Warum verwendest du da keine
Bitnamen? Dann müsste man an dieser Stelle nicht das Datenblatt suchen.
Aus dem Bauch heraus denke ich aber, dein Problem liegt in den gezählten
Overflows.
Diesen Zähler setzt du nach jeder Messung wieder auf 0, den
Timer-Counter lässt du aber weiter laufen.
Das ist ungefähr so, als ob du mit einer Uhr stoppen würdest (nur
Sekunden) und zwar registrierst, dass du über 100 Sekunden kommst, dann
aber die Hunderterstelle jeweils wieder auf 0 setzt.
d.h. du kriegst Werte von
1
88
2
123
3
79
4
101
5
56
und wenn du da jetzt die Differenzen nimmst, dann kommt Unsinn raus. Du
müsstest eigentlich Werte haben
1
88
2
123
3
179
4
201
5
256
und dann kannst du auch mit den Differenzen rechnen.
Ist aber nur so ein Bauchgefühl. Wie gesagt: ich würde mir erst mal die
aufgezeichneten Daten ansehen.
Das mit den Bitnamen habe ich noch nie gemacht. Müßte ich vielleicht
langsam mal machen. Ich bin von Kindesbeinen auf gewohnt des so zu
machen wie ich es halt mache. Tut mir scho leid. Werde mich aber mal
drüber machen wie des so geht.
Hallo Karl Heinz der Tipp war goldrichtig. Ich lasse jetz bei jedem
Durchgang die gleichen Werte in die Tabelle eintragen und siehe da, die
Anzeige ändert sich noch immer.
anfänger0815 schrieb:> Das mit den Bitnamen habe ich noch nie gemacht.
Dann wirds Zeit
Was ist (auf einem Mega16) der Unterschied zwischen
1
in tmp1,TIMSK
2
ori tmp1,0b00100100
3
out TIMSK,tmp1]
und
1
in tmp1,TIMSK
2
ori tmp1, (1<<TICIE1) | ( 1<<TOIE1)
3
out TIMSK,tmp1
Antwort: technisch gesehen - keiner
Die 2-te Form ist für Menschen aber besser lesbar. Du musst dir dazu
noch nicht mal viel merken, denn die Bitnamen stehen im Datenblatt genau
an der Stelle dabei, an der du dir sonst die Bits rausliest.
Und nach 3 mal machen hast du dir auch gemerkt, dass TOIE1 für "Timer
Overflow Interrupt Enable vom timer 1" steht und TICIE1 für "Timer Input
Capture Interrupt Enable vom timer 1" steht. D.h. beim Code lesen,
kannst du ganz leicht im Code lesen, was du eigentlich eingeschaltet
hast. Aus den binär-Bits siehst du das aber nicht so schnell.
Jetzt habe ich die ganze Geschichte umgeschrieben, den Timer 1 Überlauf
mal "ausgeschaltet". Ein Problem habe ich jetzt aber immer noch, dei
Anzeige ist zwar ruhiger aber zeigt zu viel an. Und da hätte ich gleich
noch eine Frage: Wie verhält es sich mit dem Überlauf, wenn ich von
einem Timerwert vor dem Überlauf einen Timerwert nach dem Überlauf
abziehe? Ich denke mir ich muß dann per neg-Befehl ein Zweierkomplement
machen. Aber wie mache ich des bei einer 3-Byte langen Zahl? Bei dem
Komplement wird doch 1 hinzu addiert. Wie mach ich das wenn es dann
einen Überlauf nach der Addition gibt?
Hi
>Warum nicht?
Weil das 2er-Komplement einer 24-Bit-Zahl etwas anders ist, als das
2er-Komplement der einzelnen Bytes. Bei einer 24-Bitzahl muss das so
1
neg24: com r16
2
com r17
3
com r18
4
subi r16,Low(-1)
5
sbci r17,byte2(-1)
6
sbci r18,byte3(-1)
7
ret
aussehen. Die Register solltest du allerdings an dein Programm anpassen.
MfG Spess
Des mit dem Zweierkomplement ist leuchtet schon ein,ich verstehe die
Befehle nicht so richtig:
subi r16,Low(-1)
sbci r17,byte2(-1)
sbci r18,byte3(-1)
Was subi und sbci machen ist mir klar, aber was dann nach dem Komma
kommt erschließt sich mir nicht so ganz.
Hallo anfänger0815 ,
-1 besteht als 24-Bit Zahl aus 3 Byte, diese werden mit dem Operatoren
ausgewählt.
Also Erst Byte 0, 1 und 2.
eine Subtraktion von -1 ist eine Addition - klar ?
anfänger0815 schrieb:> Hoffe jetzt ist es besser
Noch besser wäre, wenn du deine seitenlangen Listings als Anhang postet.
Vor lauter Scrollerei findet man sonst kaum noch die Textbeiträge ;-)
anfänger0815 schrieb:> auch so schreiben:neg24: com r16> com r17> com r18> ldi r19,1> add r16,r19> ldi r19,0> addc r17,r19> addc r18,r19> ret
Ja, aber warum so umstaendlich? Mach dir ein Macro draus und du kannst
es quasi als neuen Befehl verwenden.