Forum: Mikrocontroller und Digitale Elektronik Programmverständnis ADC Toturial(mega8)


von A. C. (michael1988)


Lesenswert?

HI Ich arbeite gerade das Toturial durch und es kalppt auch ganz gut.
Nur habe ich jetzt das Problem, dass ich den Sourcecode aus dem 
ADC-Kapitel nicht vollstandig verstehe,was den andere Anfängern wohl 
auch so gehen dürfte.

Hier die betreffende Passage:
1
   cpi  temp2,128          ; "Kommastelle" kleiner als 128 ?
2
    brlo no_round           ; ist kleiner ==> Sprung
Welche Kommastelle ist hier gemeint?
1
; Aufrunden
2
    subi temp3, low(-1)       ; addieren von 1
3
    sbci temp4, high(-1)      ; addieren des Carry
Was bedeutet hier das "low(-1)" bze. gigh(-1)? Wie iwrd aufgerundet?
1
;in ASCII umwandeln
2
outp:
3
    ldi  temp5, -1 + '0'
4
_a6ser:
5
    inc  temp5
6
    subi adlow, low(10000)   ; -10,000
7
    sbci adhigh, high(10000)
8
    brcc _a6ser
9
 
10
    ldi  temp6, 10 + '0'
11
_a7ser:
12
    dec  temp6
13
    subi adlow, low(-1000)   ; +1000
14
    sbci adhigh, high(-1000)
15
    brcs _a7ser
16
 
17
    ldi  temp7, -1 + '0'
18
_a8ser:
19
    inc   temp7
20
    subi  adlow, low(100)    ; -100
21
    sbci  adhigh, high(100)
22
    brcc  _a8ser
23
 
24
    ldi  temp8, 10 + '0'
25
_a9ser:
26
    dec  temp8
27
    subi adlow, -10          ; +10
28
    brcs _a9ser
29
    subi adlow,-'0'
Was hat es mit der 10000 auf sich und warum wrid mal addiert und mal 
subtrahiert?

Ich denke ich frage hier im Interesse einiger,die das Toturial 
bearbeiten.

Mfg Michael

von Karl H. (kbuchegg)


Lesenswert?

Michael D. wrote:
> HI Ich arbeite gerade das Toturial durch und es kalppt auch ganz gut.
> Nur habe ich jetzt das Problem, dass ich den Sourcecode aus dem
> ADC-Kapitel nicht vollstandig verstehe,was den andere Anfängern wohl
> auch so gehen dürfte.
>
> Hier die betreffende Passage:
>
>
1
>    cpi  temp2,128          ; "Kommastelle" kleiner als 128 ?
2
>     brlo no_round           ; ist kleiner ==> Sprung
3
>
> Welche Kommastelle ist hier gemeint?

Es geht um Folgendes.

Angenommen du liest vom ADC 10 mal ein und summierst
die Ergebnisse auf und kriegst als Ergebnis eine Summe
von 127.
Dann wäre ja der Mittelwert, also der Wert der bei einer
enzigen Messung herauskommt, 12.7

Nun kannst du aber 12.7 nicht in einem Ganzzahl Register
speichern. Das Ergebnis kann entweder 12 oder 13 sein.
Bei 12.7 wirst da als Ergebnis 13 haben wollen, da 12.7
gerundet ja 13 ergibt.
Nur kannst du diese Rundung nicht mehr nach der Division
machen. 127 durch 10 ergibt 12 (Keine Kommastellen!) Ergo
musst du die Rundung vor der Division machen. Das was nach
der Division als Kommastelle auftauchen würde, ist aber
vor der Division die Einerstelle, weil du ja durch 10
dividieren wirst. Insofern ist es diese 'Kommastelle'
die dir verrät ob, du das Ergebnis nun 12 oder 13 sein
soll.
Du betrachtest ganz einfach die Einerstelle und siehst
nach ob sie größer oder kleiner als 5 (die Hälfte von
10, durch die später dividiert wird) ist. Ist sie
größer, dann wird aufgerundet. Bei kleiner wird abgerundet.

Zurück zum konkreten Beispiel. Hier werden nicht 10 Ergebnisse
aufaddiert, sondern 256. Um den Mittelwert zu erhalten, wird
daher auch durch 256 dividiert. Das geht besonders einfach,
weil nämlich nicht dividiert werden muss, sondern das nieder-
wertigste Byte weggeworfen wird, und die beiden höherwertigen
Bytes um 1 Stelle nach rechts rücken.
Aber: Das ändert nichts am Runden. Wieder wird der Teil, der
nach der Division als Kommastelle auftauchen wird untersucht
(in völliger Analogie zu oben) und entschieden, ob auf oder
abgerundet werden soll.

>
>
1
> ; Aufrunden
2
>     subi temp3, low(-1)       ; addieren von 1
3
>     sbci temp4, high(-1)      ; addieren des Carry
4
>
> Was bedeutet hier das "low(-1)" bze. gigh(-1)? Wie iwrd aufgerundet?

Um wieder bei 127 zu bleiben.
Aufgerundet wird in diesem Fall, indem 10 addiert wird.
127 + 10 macht 137. Nach der Division durch 10 ergibt sich
13, das gerundete Ergebnis.

Im Code passiert auch nichts anderes. Nur wird hier 256 addiert.
Weil ja 256 Ergebnisse aufsummiert wurden und durch 256 dividiert
wird.
Der Schluessel im Code besteht jetzt darin, dass die Summe byteweise
in 3 Registern gebildet wird:
  temp2      das niederwertigste Byte (welches nach der 'Division'
             wegfällt. Es entspricht in gewisser Weise der 7 in den 127
  temp3      das mittlere Byte
  temp4      das höherwertigste Byte

Eine Addition von 256 entspricht daher der Addition

    temp4  temp3  temp2
+      00     01     00    (hex)

Zu temp2 braucht man aber keine 0 addieren, das ändert nichts
an temp2.

>
> [avrasm]
> ;in ASCII umwandeln
> outp:
>     ldi  temp5, -1 + '0'

> Was hat es mit der 10000 auf sich und warum wrid mal addiert und mal
> subtrahiert?

Weil festgestellt werden soll wieviele 10000 sich in der Zahl
verbergen.

Es geht darum eine Zahl, nehmen wir mal 837, in die
einzelnen Stellen zu zerlegen: 8, 3 und 7

um die erste Stelle zu erhalten, musst du feststellen wieviele
Hunderter in der Zahl enthalten sind. Das kann man mit einer
Division machen:  837 / 100  ergibt 8.
Nur leider sind Divisionen aufwändig. Es ist einfacher von der
Zahl in einer Schleife immer 100 abzuziehen und mitzuzählen
wie oft das ging, bevor die Zahl negativ wurde

  Zahl        Zähler
  837            0   ->    -100
  737            1   ->    -100
  637            2   ->    -100
  537            3   ->    -100
  437            4   ->    -100
  337            5   ->    -100
  237            6   ->    -100
  137            7   ->    -100
   37            8   ->    -100
  -63                -> Zahl ist negativ, fertig

Also lautet die erste Stelle 8.

Um die nächste Stelle zu bestimmen, kann man jetzt wieder 100
addieren und das ganze Spielchen mit einer Subtraktion von
10 wiederholen.
Man kann aber auch anders vorgehen: Man belässt es bei der
negativen Zahl und addiert immer 10. Nur muss man dann allerdings
den Zähler von 9 herunterzählen anstatt von 0 beginnend hinaufzählen:

    -63         9   ->  +10
    -53         8   ->  +10
    -43         7   ->  +10
    -33         6   ->  +10
    -23         5   ->  +10
    -13         4   ->  +10
     -3         3   ->  +10
      7             -> Zahl ist positiv, fertig

Die nächste Stelle lautet also 3

Die Einerstelle steht  bleibt dann übrig.
Die Zerlegung von 837 in die einzelnen STellen lautet also
8, 3 und 7

Da eine 16 Bit Zahl aber nicht nur Zahlen bis 999 darstellen kann,
sondern bis hinauf zu 65536 geht, wird dasselbe Schema angewandt,
nur beginnt die Zerlegun mit der 10000-er Stelle.

> Ich denke ich frage hier im Interesse einiger,die das Toturial
> bearbeiten.
>
> Mfg Michael

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.