Hallo liebe Leute,
ich bin gerade dabei, neu in das Hobby uC einzusteigen. Nun bin ich
dabei, ein kleines Stück Code zu schreiben, das über den PortC vom
Mega32 bytes ausgibt, die ein DAC0808 dann als Sinus, Dreieck usw
ausgeben soll. Für das Rechteck und Sägezähn klappt das ganze auch
wunderbar. Nun wollte ich selbiges auch für den Sinus machen, habe mir
ne Tabelle mit den entsprechenden 8bit-Werten besorgt. Diese habe ich im
EEPROM abgelegt, der DAC funktioniert, wie bei den anderen Wellenformen
gesehen, er gibt von 0V-5V aus. Aber auf dem Oszi sehe ich keine
Sinuskurve, sondern ein Gebilde, das von 0-2,5V wie eine Sinuskurve
steigt(1/4pi), dann aber auf 0V zurückspringt,weiterläuft wie ein Sinus
aber quasi die 2,5V nach unten versetzt. Wenn dann bei (3/4pi) wieder
null erreicht ist, wird auf 2,5 volt zurückgesprungen, das letzte
Viertel der oberen Sinushälfte wird normal durchlaufen. Nach unten ist
es das selbe. Quasi so ähnlich
+ + + +
+ + + +
+ + + +
+ + + + + + +
+ + + +
+ + + +
+ + + +
Ich programmiere im AVR Studio, Programmer ist nen mysmart usb mk2, uC
ist ein Atmega32 16pu
Hier noch der Code,den teil fürs Rechteck usw hab ich mal weggelassen.
Vielen Dank im vorraus schonmal,
mit gespannten Grüßen, Jendrik
P.S.
Da die anderen Wellenformen richtig ausgeben werden, denke ich das man
sowas wie MSB am DAC vertauscht auschließen kann, obwohl das Fehlerbild
schon darauf schließen lässt..
jendrik t. schrieb:> der DAC funktioniert ... er gibt von 0V-5V aus.
Was gibt er bei 0x00 aus, was bei 0x7f, was bei 0x80, was bei 0xff?
> der DAC funktioniert, wie bei den anderen Wellenformen gesehen
Woher hattest du die Werte für diese Wellenformen?
> out eearl,zl
Ist diese Tabelle wirklich an einer Page-Grenze abgelegt? Reicht es aus,
wenn du das Low-Byte manipulierst?
> Aber auf dem Oszi sehe ich keine> Sinuskurve, sondern ein Gebilde, das von 0-2,5V wie eine Sinuskurve> steigt(1/4pi), dann aber auf 0V zurückspringt,weiterläuft wie ein Sinus> aber quasi die 2,5V nach unten versetzt. Wenn dann bei (3/4pi) wieder> null erreicht ist, wird auf 2,5 volt zurückgesprungen, das letzte> Viertel der oberen Sinushälfte wird normal durchlaufen.> Nach unten ist es das selbe. Quasi so ähnlich
Aber nur Quasi?
Nehmen wir mal das Bild hier und tragen die Spannungen nach deiner
Beschreibung ein, dann habe ich ein Problem:
0 pi/4 pi/2 3pi/4
>2.5V + + + +> + + + +> + + + +> 0V + + + + + + +> + + + +> + + + +> ???V + + + +
Was müsste denn bei ???V stehen?
1
sin1:
2
3
ldi a2,8
4
5
sin2:
6
...
7
call sin_time ;schleife für byteausgabedauer aufrufen
8
...
9
brne sin2 ;nächstes byte ausgeben
10
...
11
12
sin_time:
13
dec a2
14
brne sin_time
15
ret
Dir ist klar, dass a2 nicht so richtig wirken kann?
Das der Wert 8 nur einmal ganz am Anfang des sinus gilt?
1
Sin1:
2
3
ldi a3,255
4
5
sin2:
6
...
7
dec a3 ;zähler für ausgabe eins runter
8
brne sin2 ;nächstes byte ausgeben wenn nicht null
9
jmp sin1 ;sonst wieder von vorn
Du könntest einfach ohne Vergleich mit a3 weitermachen, denn 0-1 ist -1
und das ist 0xFF und das ist 255...
Und das Beste zuletzt: du bräuchtest a3 gar nicht, weil zl schon den
index beinhaltet und kostenlos überläuft. Und weil du fürderhin zh
ignorierst.
1
Sinus:
2
ldi zh,high(2*sinustab)
3
out eearh,zh
4
ldi zl,low(2*sinustab)
5
out eearl,zl
6
ldi a2,8
7
sin2:
8
out eearl,zl ;tabellenposition NUR LOW-BYTE !!!
9
sbi eecr,eere ;eeprom lesen
10
in a1,eedr ;wert aus eeprom in a1
11
out portc,a1
12
inc zl ;eins weiter --> läuft automatisch von 255 auf 0 über
13
call sin_time ;schleife für byteausgabedauer aufrufen
14
jmp sin2 ;--> the never ending story
15
16
sin_time:
17
dec a2
18
brne sin_time
19
ldi a2,8 ;Zeit wieder laden
20
ret
BTW: dir ist schon klar, dass ein viertel vom ganzen Sinus ausreichen
würde? Der Rest kann mit Offset, Invertierung und einer Subtraktion
erledigt werden...
BTW2: Warum legst du die Tabelle in EEPROM? Im ROM wäre so eine
statische Tabelle doch viel besser aufgehoben...
Hi
>Kann das sein, dass der Compiler "2xsinustab" als Byte rechnet? (fixed>overflow)?
Nein. Wobei '2*sinustab' für den EEprom sowieso falsch ist. Führt hier
nur nicht zu einem Fehler, weil die Adresse von sinustab Null ist.
MfG Spess
Hi, danke erstmal für die Antworten.
Also die Geschichte mit der multiplikation der Adresse mit 2 hab ich aus
sonnem kleinen Anfängerbuch. Hab da auch nicht ganz verstanden was das
soll. Evtl könnte mir das auch jdm erklären. Ich hatte es aber auch mit
ldi zh,high(sinustab) versucht, mit dem selben Ergebnis.
@ Lothar Miller
>Was gibt er bei 0x00 aus, was bei 0x7f, was bei 0x80, was bei 0xff?
das müsst ich mal nachmessen..
tadaa
Messen ist doch ne feine Sache, vor allem, wenn mans richtig macht. *gg
die "schicke" Sinuskurve ging von 0v bis ca 3,65v, womit dann doch klar
war, das ein Bit nicht richtig geschaltet wird.... Das Breadboard war
schuld. Also vielen danke für eure Hilfsversuche, und über eine
Erklärung was das mit dieser ominösen (2*Sinustab) auf sich hat, wann
man das macht, wäre ich immernoch dankbar.
>Was müsste denn bei ???V stehen?
da müsste die 0V stehen, hatte das nur schnell ausm kopf gezeichnet *g
>Dir ist klar, dass a2 nicht so richtig wirken kann?>Das der Wert 8 nur einmal ganz am Anfang des sinus gilt?
Nein ist es mir nicht... Aber nachdem ich es nun nochmal durchgegangen
bin, leuchtet es mir ein! Danke für den Hinweis, das erklärt schonmal
warum er beim sinus quasi überhaupt nicht auf änderungen vom a2 wert
reagiert hat, bei den anderen wellenformen hat sich das nämlich in
durchaus wahrnehmbaren Tonhöhenänderungen geäussert *g.
>Du könntest einfach ohne Vergleich mit a3 weitermachen, denn 0-1 ist -1>und das ist 0xFF und das ist 255...>Und das Beste zuletzt: du bräuchtest a3 gar nicht, weil zl schon den>index beinhaltet und kostenlos überläuft. Und weil du fürderhin zh>ignorierst.
*g, den Vergleich hab ich gemacht, damit er dann eigl nach jedem Zeichen
den a2 wert aus sin1 wieder laden kann.. aber das war mein Denkfehler in
der vorherigen Frage
>BTW: dir ist schon klar, dass ein viertel vom ganzen Sinus ausreichen>würde? Der Rest kann mit Offset, Invertierung und einer Subtraktion>erledigt werden...
Diese Möglichkeit ist mir bekannt, aber da ich ne Sinustabelle für nen
kompletten Sinus gefunden habe, und mir noch nicht richtig im klaren
darüber bin, wie ich die Tabelle dann rückwärts auslese und invertiere,
dachte ich, erstmal die leichtere Variante, daran werd ich mich dann mal
machen, falls der Speicherplatz im Mega32 doch mal eng wird. Wobei das
ja ganicht so kompliziert sein kann, man muss ja nur die Adresse
andersrum laufen lassen, und in der 2ten Hälfte den jeweiligen Wert
invertieren...oder nicht? aber dann muss doch in dem Teil ohne
Invertierung darauf achten, das er gleich viele Steps bis zur
Ausgabe am Port braucht, damit der sinus nicht in der ersten Hälfte
schneller läuft?
>BTW2: Warum legst du die Tabelle in EEPROM? Im ROM wäre so eine>statische Tabelle doch viel besser aufgehoben...
Das hab ich auch aus diesem wahnsinnig schlauen Buch, das sagt dass man
die Adresse mit 2 multiplizieren soll... Wie greife ich denn auf das ROM
zu? Ich wusste bisher nur vom Flashspeicher und vom EEPROM
P.S. Die Werte für die anderen Wellenformen hab ich nicht aus einer
Tabelle. Für den Sägezahn lass ich einfach n Zähler hochlaufen und
ausgeben. Geht gleichmäßig rauf und springt auf null zurück, so wie es
sein soll. Für das Rechteck lass ich einfach 0X00 und 0Xff ausgeben und
dazwischen zählt ein Timer für die Frequenz
Hi
>Das hab ich auch aus diesem wahnsinnig schlauen Buch, das sagt dass man>die Adresse mit 2 multiplizieren soll... Wie greife ich denn auf das ROM>zu? Ich wusste bisher nur vom Flashspeicher und vom EEPROM
Mit ROM ist der Flashspeicher gemeint. Der ist aber Wordweise (16 Bit)
organisiert. Um die Adresse eines Bytes (8 Bit) zu erhalten muss man die
Wordadresse verdoppeln.
>Wie greife ich denn auf das ROM zu?
Du legst die Tabelle mit z.B.
1
.org $1000
2
sinustab:
3
.db 127,130,133,136,139,1...
die Tabelle in den Flash. Wichtig ist, das die beiden Ziffern $00 oder
$80 sind. Im Programm greifst du mit
Alles klar, das werd ich direkt mal versuchen =)
Danke schön
MfG des Chaoskind
p.s. doch noch nicht ganz klar, welche beiden ziffern müssen $00 oder
$80 sein? entspricht $00 0x00?