mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Rechnen mit AVR


Autor: Manuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
HI!

Für eine DDS ansteuerung benötige ich ein 32 bit Datenwort das dem
DDS-Chip die gewünschte Frequenz angibt.

pro Hz ergibt sich also die Fromel: 2^32/180MHz = 23,86092942

Wenn ich also eine Frequenz von 121 Hz haben möchte:
121 * 23,86092942 = 2887,17245982

Dieses Ergebnis soll der AVR auf- oder abrunden.
somit habe ich 2887 dezimal sind binär 101101000111

Dieses Ergebnis kann bis zu 32 bit erreichen.
Nun meine Fragen:

Wie sag ich dem AVR das er die gewünschte Freq. mit 23,86...
multiplizieren soll, also wie geht das mit den Nachkommastellen ?

Wie kann ich es verwirklichen mit 32 bit also 4 Registern zu rechnen?

MfG
Manuel

Autor: Profi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Zauberwort heißt fixed-point-arithmetik.
Du skalierst mit z.B. 1024, 4096 oder einer anderen Zweierpotenz und
kürzt nach der Multiplikation.

23. *65536 = 1563749,8706147556
1563750 * 121 = 189213750
189213750 / 65536 = 2887,172698974609375

Runden geht einfach: Du addierst einfach das bit15 des
Zwischenergebnisses zum End-Ergebnis.
Wenn das Ergebnis 32 bit lang werden kann, muss das Zwischenergebnis
mindestens 48 bit lang sein, d.h. Du musst "mit der Hand"
multiplizieren. Das ist aber gar nicht soo schwer.

Alternativ kannst Du die Formel umstellen:
dds = 2^32 * freq / xtal;

Die Multiplikation ist einfach: freq um 32 bit nach links, oder anders
gesagt: 32 Nullen anhängen.
Dann hast Du aber das Problem, dass vielstellig dividiert werden muss.
Da ist das Multiplizieren deutlich einfacher.

Wenn Du willst, suche ich Dir eine
32x32=64-bit-Multiplikations-Routine.

Autor: Jadeclaw Dinosaur (jadeclaw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erste Grundlagen für die Rechnerei und Zahlenumwandlung gibt es auch
hier:
http://www.avr-asm-tutorial.net/avr_de/rechnen/index.html

Gruss
Jadeclaw.

Autor: gerd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo.
Eine Frage von Manuel bleibt da noch offen: Wie rechnet man mit vier
Registern. Gar nicht! Man rechnet alle vier Register einzeln und
behandelt die Überläufe in das nächsthöhere Byte, z.B. beim Addieren,
durch Hinzuaddieren des Carrybits aus der niedrigeren Addition (ADC
statt ADD). Beim Malnehmen (Linksschieben) rotiert das höchste Bit ins
Carry und von da aus in das nächsthöhere Register (ROL statt LSL).

mfg
gerd

Autor: Manuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, erstmal danke für eure Antworten!

Ich werde wohl ne Zeit brauchen um das zu verdauen und ein bischen mit
dem Studio rumprobieren müssen.
Aber das Grundprinzip ist mir schonmal klar geworden.
Sollte es dennoch Probleme geben werde ich hier in nächster Zeit wohl
noch die ein oder andere Frage stellen.

@ Profi: Ich werde es zwar selber versuchen, aber solch eine Routine
wäre vielleicht trozdem nicht schlecht.

MfG
Manuel

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In der Codesammlung sind letztens Routinen für Rechenoperationen in Asm
aufgetaucht...

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
man kann auch 10er potenzen nehmen bei der fixed point arithmetik. dank
MUL befehl braucht das auch nur 2takte (meine ich).

Autor: Profi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die folgenden Beispiele sind so getippt, dass man sie bis einschließlich
=-Zeichen markieren, kopieren und in den Win-Rechner im
wissenschaftlichen hex-Modus (Alt+a w F5) kopieren kann, der rechnet
dann das Ergebnis aus.

Man muss praktisch jedes Byte mit jedem des anderen Multiplikanden
multiplizieren und das Ergebnis um eine bestimmte Bytezahl nach links
versetzt addieren.
Beachte: auch die Bitschiebezahl (8,10,18,20) ist hex -> 8,16,24,32
dez.


16 x 8 bit
1234 * 56 = 061D78
           --------
  34 * 56 =   1178
12   * 56 = 060C


16 x 16 bit
1234 * 5678 = 06260060
             ----------
  34 *   78 =     1860
12   *   78 =    870
  34 * 56   =   1178
12   * 56   = 060C

32 x 32 bit
01234567 * 89abcdef = 9CA39DC94E4629   (hat nur 14 Stellen wg. 0123..)
          10FEDCB29
         E93E937B
       C28F5BCD
     9BE0241F
    ----------------
     9CA39DC94E4629

          6029+
        527B00+
      44CD0000+
    371F000000=
37641FDB29

auf 8x8 Multiplikationen zurückgeführt

67*ef+
67*cd<8+
67*ab<10+
67*89<18+
45*ef<8+
45*cd<10+
45*ab<18+
45*89<20+
23*ef<10+
23*cd<18+
23*ab<20+
23*89<28+
01*ef<18+
01*cd<20+
01*ab<28+
01*89<30=
9CA39DC94E4629



        37641FDB29+
      251B4E816B00+
    12D27D27AD0000+
    89abcdef000000=
 ==================
    9CA39DC94E4629

fedcba98*89abcdef=

fedcba98*fedcba98=FDBAC096DD413A40  (hat 16 Stellen)
      98*      98   +
      98*    ba  < 8+
      98*  dc    <10+
      98*fe      <18+
    ba  *      98< 8+
    ba  *    ba  <10+
    ba  *  dc    <18+
    ba  *fe      <20+
  dc    *      98<10+
  dc    *    ba  <18+
  dc    *  dc    <20+
  dc    *fe      <28+
fe      *      98<18+
fe      *    ba  <20+
fe      *  dc    <28+
fe      *fe      <30=
==================
 FDBAC096DD413A40


      98*      98+
      98*    ba00+
      98*  dc0000+
      98*fe000000+
    ba00*      98+
    ba00*    ba00+
    ba00*  dc0000+
    ba00*fe000000+
  dc0000*      98+
  dc0000*    ba00+
  dc0000*  dc0000+
  dc0000*fe000000+
fe000000*      98+
fe000000*    ba00+
fe000000*  dc0000+
fe000000*fe000000=
==================
 FDBAC096DD413A40

fedcba98*89abcdef=890F2A50AD05EBE8
      98*      ef   +
      98*    cd  < 8+
      98*  ab    <10+
      98*89      <18+
    ba  *      ef< 8+
    ba  *    cd  <10+
    ba  *  ab    <18+
    ba  *89      <20+
  dc    *      ef<10+
  dc    *    cd  <18+
  dc    *  ab    <20+
  dc    *89      <28+
fe      *      ef<18+
fe      *    cd  <20+
fe      *  ab    <28+
fe      *89      <30=
==================
 890F2A50AD05EBE8


ffffffff*ffffffff=FFFFFFFE00000001
       FEFFFFFF01
     FEFFFFFF01
   FEFFFFFF01
 FEFFFFFF01
------------------
 FFFFFFFE00000001

ffffffffffffffff-FFFFFFFE00000001=1FFFFFFFE=2*ffffffff (beim
Hardware-MAC sind 2 Summanden möglich)
ffffffff00000000-FFFFFFFE00000001=FFFFFFFF

Autor: Ale (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Manuel

Hallo,

Wenn du möchtest 120Hz mit ein DDS chip, du kanst viellecht günstiger
mit einer 1 oder 4 MHz Crystal arbeiten. DDS mit 180 MHz sind teuerer
als eine mit 25 MHz max Takt. (Hoffe es hilft).

Ale

Autor: gerd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo.
Ich finde die Methode von "Profi" nicht so arg attraktiv. Man
verliert so leicht den Überblick. Bitweises Addieren und Linksschieben
ist nach meinem Geschmack systematischer und vielleicht sogar
schneller, insbesondere bei 24*24 Bit.

mfg
gerd

Autor: Tubie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, habe das auf ganz einfache weise gelöst, denn ich habe auch mit
dem AD9851 einen DDS Synthi aufgebaut:

              Fout(Hertz) * FF FF FF FF
Delta Phase = -------------------------
                    0A BA 95 00



im klartext:
es sollen 20 MHz ausgegeben werden

an die Ausgangsfrequenz einfach noch
4 Register mit 00 00 00 00

sieht dann so aus
    01 31 2D 00  00 00 00 00
(20.000.000 Hz)  (+ erweiterung)

diese 8 Byte Zahl wird jetzt dividiert durch 180.000.000 Mhz
also 0A BA 95 00

das Ergebnis lautet 1C 71 C7 1C und kann dierekt in den DDS Chip
geladen werden.

Moment... ich suche grade mal die routine raus...

Gruß, Tubie

Autor: Tubie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Voila und hier die Routine:

;-----------------------------------------------------------------------
; divisionsroutine
; temp 0(MSB)-7(LSB) / temp 20(MSB)-23(LSB) = temp 10(MSB)-17(LSB)
; hilfsreg temp30-temp33


division:
push temp30
push temp31
push temp32
push temp33

clr temp10    ; Ergebnis löschen
clr temp11
clr temp12
clr temp13
clr temp14
clr temp15
clr temp16
clr temp17


ldi temp,0
cp temp0,temp
cpc temp1,temp
cpc temp2,temp
cpc temp3,temp
cpc temp4,temp
cpc temp5,temp
cpc temp6,temp
cpc temp7,temp

breq divi_fertig

inc temp17

; Hilfsreg löschen
clr temp30
clr temp31
clr temp32
clr temp33
; Divisionsschleife anfang

divi_a:
clc        ; lösche carry
rol temp7    ; nächsthöheres bit in hilfsreg rollen
rol temp6
rol temp5
rol temp4
rol temp3
rol temp2
rol temp1
rol temp0

rol temp33    ; Entspricht multiplikation mit 2
rol temp32
rol temp31
rol temp30

brcs divi_b    ; Eine 1 ist herrausgerollt, ziehe ab
cp temp33,temp23  ; Divisionsergebnis 1 oder 0 ?
cpc temp32,temp22
cpc temp31,temp21
cpc temp30,temp20

brcs divi_c    ; Überspringe subtraktion, wenn kleiner

divi_b:
sub temp33,temp23
sbc temp32,temp22  ; subtrahiere divisor
sbc temp31,temp21
sbc temp30,temp20

sec          ; carry bit setzen, ergebnis ist eine 1

rjmp divi_d    ; zum schieben des ergebnisses

divi_c:

clc          ; carry löschen, ergebnis ist eine 0

divi_d:

rol temp17
rol temp16
rol temp15
rol temp14      ; carry bit ins ergebnis rollen
rol temp13
rol temp12
rol temp11
rol temp10

brcc divi_a    ; solange wiederholen, bis eine 1 rausrollt

; ergebnis ist jetzt berechnet und in temp14(MSB)-17(LSB) gespeichert

divi_fertig:
pop temp33
pop temp32
pop temp31
pop temp30
ret

Autor: Tubie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn man einmal den Wert ausgerechnet hat, kann man sogar problemlos
eine Start / Endfrequenz ausrechnen, diese in einzelschritte zerlegen
(je nach verwendetem AVR und geschwindigkeit) und dann passend dazu
eine Analoge Rampe auf einem externen D/A wandler ausgeben. Der DDS
Chip läuft dann von start bis endfrequenz und der Atmel gibt die Rampe
aus. Ich habe das ganze programmiert von 0.5 - 25 Hz rampenfrequenz.

Ist ne recht feine Sache. Allerdings fehlt mir momentan die Zeit hier
weiterzumachen.

Gruß,
Tubie

Autor: Profi (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@Tubie:
ich meine, eine Multiplikation mit dem Kehrwert ist allemal einfacher
und schneller als eine Division.

Übrigens, Deine Formel hat FFFFFFFF als Multiplikand:
20000000 * 4294967295 = 85899345900000000
 1312D00 *   FFFFFFFF =   1312CFFFECED300

Das Anhängen von von 4 Nullbytes ist eine Multiplikation mit
4294967296!
20000000 * 4294967296 = 85899345920000000
 1312D00 *  100000000 =   1312D0000000000

Du rechnest mit Division:
0131 2D00 0000 0000 / 0ABA 9500 = 1C71 C71C
Ich rechne mit Multiplikation:
0131 2D00        * 17 DC65 DEE0 = 1C71 C71C 710D 6000 (ist eigentlich
eine 25 x 37 --> 62-Bit-Multiplikation, das Ergebis ist jedoch
identisch)

So, jetzt kommt die Hohe Kunst der Skalierung zum Zuge, damit wir die
Wertebereiche voll ausschöpfen und maximale Genauigkeit erreichen:

Als erstes müssen wir die gewünschte maximale Ausgangsfrequenz
festlegen, z.B. 33,5 MHz (2^25). Es bleiben noch 32-25=7 Bits übrig,
die wir als "Nachkommabits" verwenden können.
Wir skalieren (=multiplizieren) mit 2^7=128, d.h. wir können die
Frequenz auf 1/128 Hz genau einstellen.

Nun brauchen wir den Wert 2^64/180000000=102481911520,60862008889 =
0x17DC65DEE0.
Der hat 37 Bits, also skalieren wir durch 2^(37-32=5)=32, bleibt
0xBEE32EF7.

20000000*128 * 3202559735 = 8198552921600000000
  9896 8000  * BEE3 2EF7  = 71C7 1C71 C435 8000
71C7 1C71 C435 8000 / 4   = 1C71 C71C 710D 6000
                            ^       ^
                            DDS-Wert


Einfacher wird es, wenn beide Male mit 2^5=32 skaliert wird, weil dann
das Ergebnis nicht mehr geschoben werden muss:
20000000*32 * 3202559735 = 2049638230400000000
  2625 A000 * BEE3 2EF7  = 1C71 C71C 710D 6000
                           ^       ^
                           DDS-Wert

Der Skalierungsfaktor muss nicht unbedingt eine Zweierpotenz sein.
Es bietet sich z.B. an, mit 10 zu skalieren, dann erleichtert sich die
Dezimalumrechnung.
Wenn man beide Zahlen mit dem selben Faktor skaliert, kann dieser jeden
x-beliebigen krummen Wert haben.

@Gerd:
Übersichtlicher? Vielleicht habe ich es unübersichtlich hingeschrieben,
aber wenn man sich ein wenig hineinarbeitet, wird das Prinzip schnell
klar.
Und ohne jetzt die Clock-Cycles gezählt zu haben, das Schiebeverfahren
dürfte viel langsamer sein, unabhängig ob mit 24x24 oder 32x32.
Was braucht mein Verfahren:
4x 4= 16 Multiplikationen =  32 Cycles
8x15=120 Additionen       = 120 Cycles, welche man durch geschicktes
Kombinieren der Produkte auf 36 reduzieren kann.
Summe: 68 Cycles zzgl. Ladezeiten. Das dürfte kaum unterboten werden
können.
Wohlgemerkt bei voller Genauigkeit. Wird das Ergebnis nach der Mult
wieder auf 32 Bit gekürzt, kann man getrost nochmal 10-20 Cycles
einsparen.


Im Anhang eine 32x32 Multiplikation in C, für ASM-Konvertierung
"vorgekaut".
Dürfte in ASM ca. 70 - 100 Zeilen schleifenlosen Code ergeben.
Habe leider keinen ASM auf diesem Rechner installiert.

Autor: Tubie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Profi,

alle Achtung! Wie sagt man so schön: Wiele Wege führen nach Rom :-)

Habe gerade mal die Divisions Routine durchlaufen lassen bei
Fout=20.000.000 Hz und ich komme auf stolze 2097 Zyklen ist also nur
unbedeutend langsamer wie deine 68 Zyklen. Damit könnte ich dann
endlich mal FM in Angriff nehmen. Dreieck, Rechteck, Sägezahn, Sinus -
Sabber!

Habe es beim Sweepen bisher immer so gemacht Start und Endfrequenz
berechnen und dann überprüfen, was der µC ausgeben kann und dann mir
eine Schrittweite ausgerechnet, die ich auf den Basiswert dazuaddierte.
Geht auch sehr schnell, da ja eigentlich nur 2 berechnungen gemacht
werden. Vorteilhaft wäre dies z.B. beim durchdrehen mittels Drehgeber.
Hier merkt man ganz deutlich die 2000 Zyklen.

Ganz tolle Leistung!

Gruß,
Tubie

P.S. Ich mache mir nur Gedanken, das solches Gedankengut in den Tiefen
des Forums verschwindet denn unter dem Thread "Rechnen mit AVR" kann
man viel meinen.

Autor: Jadeclaw Dinosaur (jadeclaw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> P.S. Ich mache mir nur Gedanken, das solches Gedankengut in den
> Tiefen des Forums verschwindet [...]

Vorschlag: Evtl. didaktisch noch etwas nachbearbeiten und in die
Codesammlung einstellen.

Gruss
Jadeclaw.

Autor: Profi (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Und, was ist los? Noch kein ASM file zu sehen?

Na, dann habe ich eines gemacht. Mein erstes AVR-Programm!

Das ganze Programm incl. Loads hat 71+8=79 Words und braucht 86+8=94
Takte. Fast wie versprochen.

Schade, dass der MUL-Befehl das Carry beeinflusst, sonst wäre es
nochmal um 12 Words und Takte kürzer geworden.


Werde noch einen Wiki-Beitrag dazu schreiben, damit das besagte Wissen
gut auffindbar ist.

Erweiterung auf jede beliebige Bitzahl ist problemlos möglich, auch
ungleiche Breiten der Multiplikanden (z.B. 80x48-->128).

Autor: Tubie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da war doch wieder mal einer schneller.  :-)

Wenn ich das Projekt wieder aufgreife, werde ich die Routine auf jeden
Fall verwenden. So wird das ganze noch leistungsfähiger.

Der große Vorteil, ich habe alles mit 2 AVR's aufgebaut. Der erste
steuert das Display, liest einen Drehgeber, die Potis und die
Kippschalter ein. Dieser gibt die Werte via RS-232(5V) weiter an den
zweiten und dieser generiert mir das DDS wort und generiert dazu
passend die Rampe fürs Sweepen.

Bin aber momentan noch am bau meines Röhrenverstärkers, der seit 5
Jahren darauf wartet, fertiggestellt zu werden.

Falls es jemanden interessiert:
http://people.freenet.de/tubefan/

Gruß,
Tubie

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Tubie

"Vorteilhaft wäre dies z.B. beim durchdrehen mittels Drehgeber. Hier
merkt man ganz deutlich die 2000 Zyklen."


Wie bitte ?

2000 Zyklen sind 0,25ms bei 8MHz, das kann kein Mensch merken.

Alles unter 10ms kann nicht bemerkt werden.


Peter

Autor: Tubie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

rechnerisch mag das eine recht kurze zeit sein, allerdings wenn ich
eine Rampe mittels D/A wandler erzeuge und die auf den "External
Sweep" Eingang meines Oskars gebe und den DDS von sagen wir 10.6 -
10.8 MHz syncron zur Rampe durchlaufen lasse, dann merkt man schon ein
ruckelndes und verwackeltes Bild während des Drehens am Drehgeber also
immer dann, wenn eine Berechnung durchgeführt wird. Dies könnte
wesentlich besser sein mit der genialen Routine von Profi.

Gruß,
Tubie

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Tubie

"dann merkt man schon ein ruckelndes und verwackeltes Bild während des
Drehens am Drehgeber also immer dann, wenn eine Berechnung durchgeführt
wird."


Diese Störungen haben dann aber eine andere Ursache.

Ein biologisches Nervensystem ist definitiv nicht in der Lage, etwas
0,25ms genau zu erkennen oder zu bewegen.

Du müßtest also schon den Drehgeber über einen Synchronmotor antreiben
und damit auch den Oszi synchronisieren, damit die 0,25ms auffallen.


Peter

Autor: Christoph Kessler (db1uq) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bob Pease von National Semiconductor ( www.national.com/RAP ) hat mal
vorgerechnet, welche Reaktionszeiten ein Baseballspieler haben muß, ich
meine er kam deutlich unter 1 msec, ich sollte mal den Artikel suchen.
Er hat auch mal den Dynamikbereich von Auge und Ohr bestimmt, beide zu
ca 140dB

Autor: Christoph Kessler (db1uq) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falsch, das "rap" muß klein geschrieben werden, die haben scheints
keinen Widows-Rechner, also: http://www.national.com/rap
die 140 dB hab ich gefunden:
http://www.elecdesign.com/Articles/ArticleID/6059/6059.html
nein die Baseball-Geschichte finde ich nicht, aber die schöne Story, wo
er (vermutlich mitten in der Nacht) die Resonanzfrequenz seiner Matraze
durch "gewobbeltes Summen " bestimmt...:
http://www.elecdesign.com/Articles/ArticleID/9328/9328.html

Autor: Marco S. (masterof)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
abo

Autor: Tubie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@peter dannegger

Ich gebe mich geschlagen. Kann ja wirklich auch sein, das in der
Software noch etwas verkehrt läuft und ich den Miesepeter in der
längsten Routine gesucht habe.

Gruß, Tubie

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kann man denn mit der eingebauten mul funktion nichts machen? Fast jeder
neue Atmel AVR hat den mul befehl. der dauert jedenfalls nicht so lange
wie so eine eigene mul routine

Autor: Profi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Christoph:
http://www.electronicdesign.com/Articles/ArticleID...
meinst Du den? Ich glaube, es gibt noch einen anderen.

mit electronicdesign statt elecdesign geht's ohne Cookies und
Skripte.

@Simon: der AVR-MUL ist 8x8-->16 bit, hier geht es um 32x32-->64
In meiner Routine verwende ich keine Shifts, sondern 16 MULs.
Schau sie Dir mal an.

Autor: Christoph Kessler (db1uq) (christoph_kessler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genau das wars:
And he has learned to release the ball with a precision of as small as
100 µs—just one tenth of a millisecond.*
*Computations: If a ball at the end of your arm, at a radius of 3 ft.,
is moving at 90 mph or 132 ft./s, it will change its ANGLE by 0.0044
radians, or 0.252°, every 100 µs. And an angle of 0.0044 radians
corresponds with an uncertainty of 6.4 in. (±3.2 in.), after the
ball—or rock—has gone 60 ft.

Autor: Profi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was mich auch verblüfft hat, ist die Tatsache, dass das Auge problemlos
erkennt, wenn eine LED 1µs lang leuchtet (falls die Umgebung relativ
dunkel ist). Hab ich selbst probiert.

Kann mich sogar an eine Diskussion (war die nicht hier im Forum?)
erinnern, dass das Auge sogar einzelne Photonen sehen kann.

Autor: Manuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Der Winter geht wieder los, und ich wieder in sachen elektronik aktiv.
Ein Grund mehr, mein schon etwas älteres Projekt endlich 
fertigzustellen.
Es fehlt nichtmehr viel, die Peripherie mit LCD, Drehgeber, usw. 
funktioniert einwandfrei, und auch die serielle übertragung zum dem AVR 
der für die DDS ansteuerung zuständig ist klappt! Zum berechnen des 
Datenwortes benutze ich die routine von Profi (Danke!!!) die ich zwar 
immernochnicht komplett verstehe, aber ich gehe mal fest davon aus das 
sie funktioniert!
Nun muss ich das 8 Byte ergebnis e0 - e7 ja noch durch 65536 teilen und 
da stehe ich grade noch ein bischen auf dem Schlauch.
Ich subtrahiere also 65536 und zähle gleichzeitig 4 Register hoch, also 
immer nur das LSB und die anderen falls ein carry auftaucht.
Aber muss ich mit dem Subrahieren bei e0 oder bei e7 anfangen?

Manuel

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welches ist das LSB?
Dort fängst du an. Das ist nicht anders
als woe wenn du mit Papier und Bleistift
subtrahierst.

Wenn du durch 65536 dividieren willst, brauchst
du gar nicht rechnen. 65536 ist eine 2-er Potenz
(2^16). Lass die beiden untersten Bytes weg und
schieb alle anderen um 2 Bytes nach rechts.

Das ist so, als ob du auf dem Papier eine Zahl
durch 100 teilst, indem du wie wild zu rechnen
anfängst. 1234 / 100 rechnet dir jeder im Kopf
aus, indem er die letzten beiden Stellen wegfallen
lässt und alles andere um 2 Stellen nach rechts
verschiebt: 1234 / 100 ergibt 12

Autor: Manuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh man, ich habe glaube ich einfach ein Problem mit dem binärsystem...
Ich wusste zwar, das es ne 2er potenz ist und habe auch lang überlegt, 
ob man da nicht einfach was mit rol oder ror machen kann, aber einfach 
weglassen wäre zu einfach gewesen ums in betracht zu ziehen ;)

Ich bin dir sehr dankbar!

Gruß Manuel

Autor: Uwe S. (de0508)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo allerseits,

ich möchte diesen Thread wieder aufleben lassen, nachdem ich die Tage 
verschiedene Verfahren für die FTW Berechnung eines AD9851 real mit 
Tickmessung auf einem atMega32 und avr gcc durchgespielt habe:

Basierend auf der 32-Bit Skalierung von 2^64  DDS-TAKT  2^5 und
anschließendem skalieren der Ziel Frequenz (freq) auf freq32 = (freq << 
5);

- Beitrag "Re: Rechnen mit AVR"
- Beitrag "Re: Rechnen mit AVR"


Konnte ich mit der "C" Variante [1] des Algorithmus das FTW in 611 Tick 
und mit der angepassten ASM-Datei des Algorithmus das FTW in nur 223 
Tick berechnen !

Hier noch die Berechnung des FTW:
#ifndef U64_UNION_B
 typedef union {
  uint8_t  b[8];
  uint16_t w[4];
  uint32_t q[2];
  uint64_t o;
 } u64_union_t;

 #define U64_UNION_B(var_,id_)  ((*(u64_union_t*)&(var_)).b[id_])
 #define U64_UNION_W(var_,id_)  ((*(u64_union_t*)&(var_)).w[id_])
 #define U64_UNION_Q(var_,id_)  ((*(u64_union_t*)&(var_)).q[id_])
 #define U64_UNION_O(var_,id_)  ((*(u64_union_t*)&(var_)).o)
#endif

uint32_t ftw_mul32_32( uint32_t freq32 )
{
const uint8_t scale = 5;
const uint32_t revers_dds_takt = 0xBEE32EF7; // 2^64 / F_MHZ(180) / 2^5

volatile uint64_t ftw;

ftw = mul32_32 ( revers_dds_takt, (freq32 << scale) );

return U64_UNION_Q(ftw, 1); // liefert die oberen 32 Bit zurück
}

[1] C-Version: 
http://www.qrpforum.de/index.php?page=Attachment&a...

Autor: Vorn Nachn (eprofi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Freut mich, dass nach 5,5 Jahren mein Code immer noch Beachtung findet.

Mich wundert, dass selbst die von Atmel vorgeschlagenen Routinen länger 
waren.

Vor allem wurmt mich, dass das Carry-Bit durch den mul verändert wird, 
was so gut wie nie ausgewertet wird.
Wenn sie schon darauf bestehen, wäre es besser, es gäbe 2 mul-Versionen, 
eine wie gehabt und eine, die das Carry-Flag unverändert lässt.


Zum C-Code: man müsste sich das ASM-Listing mal anschauen, in wieweit 
optimiert wird, da z.B. statt
  a[1] = (u16 & 0xff00)>>8;
  a[1] = u16 >> 8;
ausreicht.


Sehe ich das richtig, dass die Hopf-Routinen keine muls verwenden, 
sondern nur schieben und addieren?

Vielleicht sollten wir ihn mal hierher lotsen...


So weit ich sehe, sind die momentanen Verbesserungen für 64-Bit gcc 
schon recht gut:
http://gcc.gnu.org/viewcvs/trunk/libgcc/config/avr...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.