Hallo,
Ich bin auf der Suche nach einem IC, wie dem ML2035 ( Programable Sine
Wave Oscillator ), der ja nun leider nichtmehr hergestellt wird.
Ich habe gesucht, und habe nichts vergleichbares gefunden.
Ich würde das ganze ja gerne per µC machen, aber wenn man bedenkt, dass
man 256 Werte eines Sinus speichert, und das mit 16MHz Takt mit einem µC
macht, ist die Frequenz nach oben hin irgendwie stark begrenzt, bzw.
sind zu große Sprünge.
Würde also gerne zb. 17kHz genauso wie 17.5kHz ausgeben können, was so
nicht möglich wäre.
Brauche also einen programmierbaren Sinus Generator ( wie eben der
ML2035 )
Freue mich auf eure Antworten
Danke schonmal
Kingt nach jemanden der es gerne analog mag: Switched-Capacitor Low-Pass
Filter. Davor einen Rechteck erzeugen, z.B. mit Controller. Das dann in
den SCLPF einspeisenm, wobei dessen Takteingang benutzt wird. Raus kommt
ein super Sinus.
Bausteinchen gibts von LTC und Maxim. Bei LTC ist dafür ne App Note zu
finden.
Hallo!
Danke für die Antworten. Ja DDS hab ich mir eben gerade angeschaut, ich
versteh es noch nicht 100%ig wie es funktioniert.
Meines erachtens wird zb. bei einer Sinus look up Tabelle mit 2000
Werten einfach 1 Wert ausgelassen, um damit die nächst höhere Frequenz
zu erhalten, geh ich da richtig in der Annahme ?
Das ganze funktioniert nun mit einem "Phase Akkumulator" und einem
"Frequency Increment"
Versteh nur nicht ganz, wie das ganze funktioniert.
Es geht doch darum, dass er je nach Frequency Increment, wohl einen Wert
von 0-2000 auslässt, oder eben mehr, je nach Frequenz.
Habe mir unzählige Seiten dazu nun angesehen, und verstehe nicht ganz
die Funktion.
Machs dir einfach. Geh zu Analog Devices und kauf dir einen von den ganz
kleinen DDS-Chips. Dahinter noch ein Primitivfilter und einen kräftigen
OpAmp-Buffer. BUF634 oder so.
Bei AD gibts auch die ganzen Erklärungen verlinkt.
Heißt das, dass das "tuning word" also, was ich ihn per Seriellen oder
Parallelen Anschluss zuführe zu der Taktfrequenz hinzugezählt wird.
heißt also liegt 1 an, ist Taktfrequenz die Geschwindigkeit, mit der der
Counter die Sinus look up table hinaufzählt.
liegt 2 an, ist die Taktfrequenz nur halb so groß?
bei 3 1/3
bei 4 1/4
usw.
Oder verstehe ich hier was falsch ? Wie würde dann über den gesamten
Frequenzbereich eine gleichbleibende Frequenzänderung delta f von ein
paar mHz erzeugt werden können?
Heinrich
Hallo!
Das Problem ist, ich versteh den Phasenakkumulator nicht ganz.
Ich weiß in der Sinus look up table, sind für jeden Phasenwinkel der
Amplitudenwert gespeichert.
Zb. 2000 Werte also zw. 0-360° hab ich 200 verschiedene Amplitudenwerte
( ohne jetzt eine optimierung zu haben durch 1/4 des sinus speichern,
usw. )
Eingang für den Phasenakkumulator ist die Frequenz des DDS und
andererseits der Wert den ich gerne als Ausgangsfrequenz hätte.
Was macht der Phasenakkumulator nun? Ausgang dessen ist, die Adresse des
Amplitudenwerts in der Sinus look up table ( irgendwas zw. 0 und 1999 )
Nur wie kann der nun eine Frequenz, die ja ständig zw. 0 und 1 ändert,
und eine konstante, nehmen wir mal 100 an, so vergleichen, addieren,
multiplizieren, dividieren ( Keine Ahnung eben ? ) um danach die Adresse
richtig hoch zu zählen. Bin etwas verwirrt.
Nimm einmal an, der Phasenakkumulator habe als höchste Zahl die Zahl 360
000.
die 360 seien dann die Grade einer Sinusschwingung.
Wenn jetzt in einer Sekunde 360-tausendmal die 1 addiert wird, wird in
den oberen drei Stellen 0 bis 355 in einer Sekunde durchfahren. also
eine Schwingung je Sekunde erzeugt.
Wird dagegen 2 addiert, dauert es nur die halbe Zeit. also wird 0..355
zweimal je Sekunde durchfahren.
Die Zahl, die addiert wird, bestimmt also direkt die Dauer der
Schwingung:
Große Zahl = kurze Schwingungsdauer = hohe Frequenz.
Es gilt die Verhältnisgleichung:
Taktfrequenz / Ausgangsfrequenz = Höchstzahl / Additionskonstante
Bei DDS-IC's hat man z.B. einen sehr schnellen 32-bit Addierer. Von der
Summe werden dann die oberen 10..14 Bit über eine ROM-Tabelle auf einen
DA-Wandler gegeben, der einen der momentanen Phase entsprechenden
Analogwert ausgibt.
Hallo Peter!
Ja das habe ich soweit verstanden.
Die "verschaltung" des Addierers für den Phasenakkumulator verstehe ich
aber nicht.
Der Addierer muss doch die Additionskonstante ( bestimmt die Frequenz )
zum derzeitigen Wert der Adresse addieren richtig?
Ist das nun ein Taktflankengesteuerter Addierer der als Eingang einmal
die Additionskonstante hat, und einmal seinen eigenen Ausgang wieder an
den Eingang zurückführt.
Heißt also zb. 10001000 am Ausgang ( Daher auch Eingang ) und 1 als
Additionskonstante, kommt am Ausgang 10001001 heraus, und bei der
nächsten Taktflanke eben 10001010 usw.
Ist das so richtig ?
Heinrich schrieb:> Ist das nun ein Taktflankengesteuerter Addierer der als Eingang einmal> die Additionskonstante hat, und einmal seinen eigenen Ausgang wieder an> den Eingang zurückführt.>> Heißt also zb. 10001000 am Ausgang ( Daher auch Eingang ) und 1 als> Additionskonstante, kommt am Ausgang 10001001 heraus, und bei der> nächsten Taktflanke eben 10001010 usw.
Das ist richtig. So zaehlt er bei einer Konstante von 2 immer in 2
Schritten hoch bei 3 in 3 Schritten u.s.w.
Also immer um einen entsprechenden Phasenwinkel der Sinusspannung. Und
so baut sich deine Sinusschwingung Stueckchenweise auf. Weil da
allerdings auch Stoerkomponenten in dem Signal vorhanden sind (durch die
Taktung) brauchst du am Ausgang noch einen Tiefpass der alles was
hoeherfrequent als Fc/2 ist unterdrueckt.
Hallo!
Wui jetzt hab ichs endlich verstanden ;)
Danke!
Hab auf die schnelle was programmiert um das nachzuvollziehen,
funktioniert!
1
intmain(void)
2
{uint16_tx=1;
3
DDRD=0xFF;
4
while(1)
5
{
6
for(uint16_ti=0;i<65535;i+=x)
7
{if(!(i%256))
8
PORTD=sinus[i>>8];
9
}
10
}
11
12
}
Ist alles andere als schön oder genau. Bräuchte einen Timer, aber so
konnte ich die funktion nachvollziehen.
die Abfrage "if(!(i%256))" zoomt mir die Sinustabelle sozusagen auf, es
wäre also ob ich 256 mal soviele Werte hätte. Damit komme ich auf eine
tiefe Frequenz und auf kleine Frequenzschritte.
Wie kann ich das nun besser ausprogrammieren?
Mit einem Timer + Interrupt richtig?
Wieviele Werte sollte ich in der Sinustabelle speichern. Bis 20kHz
sollte es einigermaßen schönen Sinus liefern.
Danke!
google mal nach "poor man's Synthesizer" von einem Jesper...
Bis ca. 20 kHz liefert das einen für viele Zwecke ausreichenden Sinus
wenn der Quarz 20 MHz hat.
Hallo!
Den führe ich mir gerade zu gemüte.
Ist allerdings in asm programmiert.
Geh ich recht in der annahme, dass ich das in c nicht in 9 Zyklen in der
main Loop schaffe?
1
LOOP1:
2
add r28,r24 ; 1
3
adc r29,r25 ; 1
4
adc r30,r26 ; 1
5
lpm ; 3
6
out PORTB,r0 ; 1
7
rjmp LOOP1 ; 2 => 9 cycles
Das ist seine gesamte schleife.
Er addiert also die 24 Bit des Phasenakkumulators mit den 24 Bit der
Frequenz die man haben möchte. Soweit so klar.
das wäre ja noch einfach per c möglich. Einfach a=a+b zb. alleine hier,
sind schon mehr Zyklen nötig, als in asm ( laut der .lss Datei ) warum
auch immer.
Die Ausgabe versteh ich bei ihm nicht so ganz.
lpm bedeutet irgendwas mit r30 und r31, r30 sind also die obersten 8 Bit
des Phasenakkumulators, das ist klar soweit. r31 weiß ich nicht.
es scheint als würde lpm die Speicherstelle x(steht in r30) aus der
sinus wave table nehmen und in r0 hauen.
Danach den r0 auf PORTB ausgeben.
Kann mir vielleicht jemand erklären was es mit dem lpm auf sich hat?
Wäre toll, von Assembler hab ich leider keine Ahnung :( Habs versucht
selbst herauszufinden, aber schaff es leider nicht
Ok ich schreib mal auf wie ich mir das denke, bitte berichtigt mich.
lpm geht auf die Adresse die in r30, und r31 steht, und ladet das darin
enthaltene Byte in r0
am Anfang macht er:
1
; set sinewave output as default
2
3
ldi r31,hi8(sine) ; setup Z pointer hi
4
ldi r30,lo8(sine) ; setup Z pointer lo
ldi heißt schreibe das rechts davon stehende ( hi8(sine) ) in das linke
Register.
also hier ladet er hi8(sine) in r31 und lo8(sine) in r30, es liegt nun
in den beiden 8 Bit Registern die Adresse von dem Feld sine
das heißt also, dadurch dass nur 256 Werte im Feld gespeichert sind,
bleibt über das gesamte Feld r31 konstant, und r30 wird verändert, heißt
wenn in r30 0 steht ist es das Feld an der Stelle 0 und wenn in r30 255
steht, ist es die Stelle 255 also das letzte Byte im sine Feld?
Hab ich das so richtig verstanden?
lpm heißt load from program memory (nach r0)
Aus der Adresse des Programmspeichers, die der Z-pointer (r31+r30)
angibt, wird gelesen und an r0 übergeben.
Hier wird noch getrickst, indem r30 die oberen 8 bit des Phasenakku
bilden und gleichzeitig das low-Byte des Z-Pointers sind.
Nach dem Lesen steht also der für die aktuelle Phase passende 8-bit-Wert
in r0. Der wird dann in Spannung umgewandelt.
Mit der Speicheradresse gibt es noch eine Komplikation:
Da der Programmspeicher mit 16-bit Befehlen gefüllt wird, unterscheidet
sich die Adresse beim Lesen und die Zahl, die im Z-Pointer steht um den
Faktor zwei.
Beim Initialisieren muss r31 auf 0x04 gesetzt werden, wenn die Tabelle
bei Adresse 0x200 beginnt.
Leider haben C-Compiler oft die Eigenschaft, dass sie nicht in die
kürzeste Form umsetzen. Vielleicht hilft es, wenn man beim Compiler eine
Option wie "Codeoptimierung" aktiviert/deaktiviert ( Ich bin zwar in
Assembler zuhause, C kann ich aber nicht)
Das mit dem ldi stimmt schon weitgehend, nur wird mit hi(sine) nix
gemacht.
Die Adresse in r31,r30 ist 16 bit, die Daten umfassen nur 8 bit.
Also landet in r0 lo(sine) in 8-bit Form.
lo(sine) steht in der Tabelle auf die per r31,r30 zugegriffen wird.
Sehr schön, also soweit hab ichs verstanden bis auf:
"Mit der Speicheradresse gibt es noch eine Komplikation:
Da der Programmspeicher mit 16-bit Befehlen gefüllt wird, unterscheidet
sich die Adresse beim Lesen und die Zahl, die im Z-Pointer steht um den
Faktor zwei.
Beim Initialisieren muss r31 auf 0x04 gesetzt werden, wenn die Tabelle
bei Adresse 0x200 beginnt."
Beim Initalisieren setzt er doch r31 auf den Wert, der das obere Byte
der Speicherstelle von sine beschreibt.
Wieso unterscheidet sich die Adresse beim Lesen und die Zahl im
Z-Pointer um 2 ?
die unteren 8-Bit stehen im r30 die oberen 8-Bit im r31
direkt in r30 kann ich nun die 256 verschiedenen Amplitudenwerte für den
Sinus abgreifen.
Wenns bei Adresse 0x200 beginnt, sollte im r30 doch 0 stehen ( 0tes
Element ) und im r31 0x02, aber wieso genau sinds nun doch 0x04? Hab ich
noch nicht ganz durchschaut
Jo, da hab ich etwas Schwierigkeiten mit dem Erklären.
Es liegt daran, dass im Porgrammspeicher eigentlich nur 16-bit Befehle
erwartet werden, also opcode und Argument immer zusammen gelesen werden.
Befehl 0 steht auf den Plätzen 0 und 1, Befehl 1 steht auf den Plätzen 2
und 3,....
Wenn im Programm .org 0x200 steht, ist das 0x200-ste 16-bit Wort
gemeint, das steht aber auf den Adressen 0x0400 und 0x0401.
.db 0x16,0x61,0x65,.... schreibt in Wirklichkeit in den
Programmspeicher:
0x0016,0x0061,0x0065,... obgleich es nur 8-bit-Angaben sind.
Ich hoffe, das klärt die Sache.
Also:
lpm greift, wenn in r31 und r30 0x0201 steht, auf den Platz ox0403 zu
liefert dann also 0x61 in R0
Hallo!
Danke, aber so ganz verstehe ich es noch immer nicht, ich werde es
einfach mal so hinnehmen.
Ich wollte gerade probieren, die assembler programmteile in c zu
integrieren.
Leider nicht wirklich erfolgreich.
Ich kann zwar variablen in die Register speichern, sodass ich weiß wo
sie liegen und danach per asm Befehle darauf zugreifen, allerdings kann
ich wohl aus asm heraus nicht auf mein sinus Feld zugreifen.
1
registeruint8_tcounter_1asm("r24");
2
registeruint8_tcounter_2asm("r25");
3
registeruint8_tcounter_3asm("r26");
4
registeruint8_tacc_1asm("r28");
5
registeruint8_tacc_2asm("r29");
6
registeruint8_tacc_3asm("r30");
7
8
asm("ldi r31,hi8(sinus)");
9
asm("ldi r30,lo8(sinus)");
10
11
while(1)
12
{
13
asm("add r28,r24");
14
asm("add r29,r25");
15
asm("add r30,r26");
16
asm("lpm");
17
//asm("out PORTD,r0");
18
}
19
20
}
asm("out PORTD,r0"); mag er auch nicht, er meint es muss eine konstante
drinstehen.
Gibt es dennoch eine möglichkeit die Schleife bzw. die wichtigen
Programmteile in asm zu integrieren?
Danke
so muss es heißen, da er mit PORTD in c was anderes meint als in asm, da
sonst PORTD=0xFF; oder dergleichen nicht funktionieren würde.
Hab das Programm aufgespielt, funktioniert aber trotzdem aus irgendeinem
Grund nicht, wäre super, wenn sich das einer anschauen könnte warum!
Danke
Hi
> asm("ldi r31,hi8(sinus)");> asm("ldi r30,lo8(sinus)");
Falsch.
> R31=((uint16_t)(&sinus[0]))>>8;> R30=((uint16_t)(&sinus[0]))&0xFF;
Auch nicht besser.
asm("ldi r31,hi8(sinus<<1)");
asm("ldi r30,lo8(sinus<<1)");
Die Adresse muss von Word nach Byte umgerechnet werden.
MfG Spess
"Error: undefined symbol `sinus' in operation"
Das meldet er als Fehler!
Kann es sein, dass er aus "asm" heraus nicht auf das sinus Feld
zugreifen kann?
Lg
schonmal die Folge add r28,r24...
muss heißen: add r28,r24 adc r29,r25 adc r30,r26 da es sich um eine
24-bit Addition handelt, die Carry-Übertrag berücksichtigen muss.
da oben r26 Null ist, bleibt im Moment r30 auf konstantem Wert.
versuchs also mit irgendeiner Zahl >0 in r26 und gib erst einmal mit
"out 0x12,r30" r30 aus, um zu sehen ob sich r30 ändert.
Für eine Erfolg fehlen dann noch folgende Aktionen:
Erstens: Eine Tabelle mit den Sinuswerten im Programmspeicher an
definiertem Ort anlegen, beim Einschreiben des Programms in den
Programmspeicher.
assembler macht das mit .org 0x0200 (Anfang der Tabelle)
und folgendem .db ...... (Aufreihung der einzuschreibenden Werte)
auf diese Tabelle in Abhängigkeit von r30 zugreifen und das Ergebnis
ausgeben
Hallo!
das mit adc hab ich auch schon gemerkt, habs oben nur noch falsch
stehen. Danke
Wieso sollte sich r30 nicht ändern weil r26=0 ist, nachdem x-ten
Schleifendurchlauf ändert sich r30 ja trotzdem, da ja ganze zeit was von
r25 und r26 dazuaddiert wird, und daher auch nach einiger Zeit r30
verändert wird. Wenn ich das richtig sehe?
r30 bildet ein Sägezahn ab. Also soweit richtig wie ich das sehe.
Problem bleibt allerdings mit dem Array, weiß nicht wie ich das mit asm
machen kann. Er meldet dabei immer Fehler wenn ich es so versuche
einfach mit asm(" ... "); und das originale einzufügen.
Hallo, da bin ich wieder, hatte gerade Anderes zu tun.
Also, da sind wir ja schon so weit, dass die Phasenschritte in r30
durchlaufen werden. Jetzt bleibt noch das Problem mit der Tabelle und
dem lookup.
Man kann die Tabelle (mit .byte ?) auch im RAM installieren, es sind ja
nur 256 byte.
Dann kann man mit LD R0,Z indiziert aus der Tabelle lesen und so den
lookup ausführen.
Da wird die Schleife sogar um einen Takt kürzer.
Das Problem für mich, der C nicht beherrscht, besteht darin, diesen
RAM-Bereich freizuhalten, denn C benutzt ja recht viel RAM für den Stack
und diverse Variablen.
Hi
>Er legt momentan nichtmal das Array an, wieso auch immer ?
Wie kann man etwas permanent im RAM anlegen? Hirn einschalten. Viel
Spass noch.
MfG Spess
Stimmt.
Aber wie dann .db funktioniert auch nicht ? was bleibt übrig ;) alles
ausm fenster schmeißen und hoffen dass sich die sine table während des
fluges eingebrannt hat?
Natürlich kann man im RAM eine Tabelle anlegen:
Das Programm beginnt dann eben nach einem reset damit, die Werte ins RAM
zu schreiben, im Extremfall mit 256 LDI R16,K und anschließendem STX,R16
bis 256 Werte des Laufindex X durchgearbeitet sind.
Anschließend führt dann die DDS-Schleife mit diesem RAM-Bereich per LD
R0,Z den lookup durch.
Also Hallo,
irgendjemand, der C soweit beherrscht, wird doch die Zeilen liefern
können, wie man eine page im Programmspeicher mit einer Tabelle belegt
und wie man diese per eingebundenes Assemblerprogramm :add, adc, adc,
lpm, out, rjmp (wie oben) benutzt.
Oder wie man eine page im RAM mit einer Tabelle füllt, sie vom Stack
frei hält und sie für lookup benutzt.
So weit weg ist Heinrich doch wirklich nicht weg von der Lösung.
Sonst mault doch jeder, dass nur unqualifizierte Fragen gestellt werden
und sich niemand selbst Mühe gibt. - Was bei Heinrich doch
offensichtlich nicht der Fall ist.
Hallo Peter!
So ich hab mir jetzt was überlegt, sieht so aus als würde es
funktionieren.
Ich mache ein 512 Byte Array auf, und schreibe 2x einen kompletten Sinus
rein, somit ist auf der Adresse der oberen 8 Bit des Arrays + 1 sicher
ein kompletter Sinus abgebildet ( ob der bei Phase 0 oder Phase x
beginnt ist ja egal )
in R31 schreib ich danach das:
R31=(((uint16_t)&sinus[0])>>8)/2;
Warum es /2 heißt weiß ich nicht, aber es könnte doch mit deinem
zusammenhängen, wie du mir vorhin erzählt hast, mit dem 0x200 bzw. 0x400
usw. liegt daran richtig ?
Auf jedenfall funktioniert es so, ein Sinus bekomm ich am PORTD raus.
Will trotzdem noch wissen ob das so stimmt :)
Ok, also das haut so nicht hin.
Wenn ich mit &sinus[0]>>8 das high byte der Adresse auslese, kommt 0x06
raus, aber nur wenn ich r31 auf 2 setze, funktioniert es perfekt. ist
r31 auf 1, fehlt ein Teil vom sinus, bei 3 fehlt auch ein Teil ( ist ja
logisch, bei 512 Bytes sinus ist ein Teil vor und ein Teil danach )
Aber wieso kommt die Adresse 0x06 raus, und in wirklichkeit muss ich auf
0x02 zugreifen?
Bei diesen Termen: R31 = ((uint16... usw.
muss ich dann passen, denn das sind C- spezifische Formulierungen.
Offensichtlich hast Du ja schon einen Sinus, der mit r31 = 2 richtig
gelesen wird.
Mir kommts einigermaßen richtig vor:
mit org 0x100 ist der Beginn der Tabelle auf word 0x0100 gesetzt, dessen
erstes byte auf Speicherplatz 0x0200 liegt. und 256 words umfasst.also
bis Speicherplatz 3ff geht.
mit r31 = 2 liest Du die Tabelle komplett, aber immer nur die geraden
bytes davon wegen des Halbierens in dem komischen Term.
mit r31 = 1 bekommst Du eine Verschiebung um 256 bytes nach unten, das
laufende Term mit r30 erwischt also nur die Hälfte der Tabelle. bei r31
= 3 läuft es entsprechend oberen Bereich der Tabelle
So, jetzt mach ich aber Schluss, Viel Erfolg beim Weitermachen und Gute
Nacht.
Hallo!
Ich hab das ganze jetzt auch nochmals simuliert.
Auch per simulation meint er es liegt an 0x065C das erste Element, aber
jetzt muss ich trotzdem in r31 1 hineinschreiben, damit es funktioniert.
Kann sich das mal ein c-geschulter ansehen?
Danke!
Ich habe mir einmal im instruction set den befehl lpm angesehen (S.91),
was ich schon längst hätte tun sollen:
Der LESEBEFEHL lpm arbeitet BYTEweise, adressiert mit r31,r30 und
übergibt 8bit an r0.
Das ANLEGEN DER TABELLE muss WORDweise (16bit) geschehen.
-Man muss also den Befehl .dw0x5876 verwenden.
-Der Platzierungsbefehl .org muss das Halbe des Z-Pointers r31,r30
betragen, sonst erwischt man beim Lesen die Tabelle nicht
direkt nach dem .org200 schreibt man also mit .dw0x5876:
die 0x58 in den byteplatz Nr. 0x0401 und die 0x76 in den byteplatz
0x400, was dem wordplatz 0x200 entspricht.
Wenn r31 4 enthält und r30 die 0 liest man 0x76, wenn r31 die 4 und r30
die 1 enthält liest man die 0x58.
Hi
Das ist Unsinn. Deine Tabelle liegt immer auf einer Wordadresse.
Da lpm aber byteweise adressiert muss Z den doppelten Wert der Adresse
der Tabelle bekommen.
Daher:
ldi r31,high(sinus<<1)
ldi r30,low(sinus<<1)
Und damit kann man problemlos .db verwenden. Die Anzahl der Werte in
einer Zeile muss geradzahlig sein.
MfG Spess
Das Problem ist, momentan erstelle ich das Array ganz normal in c
also uint8_t sinus[]={..............};
weil wenn ich es mit inline assembler mache und .db verwenden möchte,
sagt er dass er den Befehl nicht kennt ?
Es gibt wieder Neuigkeiten.
Mit Avr Studio simuliert meint er er legt aus auf die Adresse 0x06.. ab.
Ich muss aber im R31 immer die letzte Adresse in der Daten im SRAM
vorhanden sind eintragen. Das heißt wenn der Code länger wird, muss ich
auch R31 ändern.
Was mir noch aufgefallen ist, es wäre wohl besser wenn ich erreichen
kann, dass ich lediglich in der Assembler Hauptschleife, Assembler
Befehle brauche.
Dazu müsste ich aber sachen wie zb.:
1
asmvolatile(
2
"lds r21,counter_1 \n\t"
3
"lds r22,counter_2 \n\t"
4
"lds r23,counter_3 \n\t"
5
"lds r24,acc_1 \n\t"
6
"lds r25,acc_2 \n\t"
7
"lds r30,RDN \n\t"
8
"lds r31,RDE \n\t"
9
"lds r20,run \n\t"
10
);
Wegbringen.
Nur wie mache ich das, kann ich in C variable definieren, die er immer
im Register haben soll, damit C auch weiß dass er diese Register für
nichts anderes verwenden darf? Ich denk damit wäre schon einiges
geschafft, dass sich Asembler und C nicht gegenseitig "beißen"
Grüße
Heinrich