www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik DDS mit Mega8 und Bascom


Autor: Thomas Scherer (zeilentrafo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe einem mit 14,7456 Mhz (Baudratenquarz) getakteten ATMega8 auf Bus D 
ein R2R Netzwerk verpasst und möchte damit einen abstimmbaren Oszillator 
für Klangerzeugung programmieren. Zur Veranschaulichung wird eine 
Sinuskurve in einer indizierten Variablen abgespeichert und dann in der 
IRQ-Routine abgerufen. Mich verwundert, dass Bascom anscheinend doch 
wesentlich mehr Takte benötigt als für eine Klangerzeugung vom IRQ 
vorgegeben. So würde ich gern eine Hüllkurve mit reinprogrammieren oder 
bspw. einen Ringmodulator. Aber da kommt immer der nächste IRQ während 
der vorige noch abgearbeitet wird. Brauche ein paar Tipps.

Unten der Bascom Quellcode.

Meine Fragen: (1) grundsätzlich: Habe ich DDS richtig verstanden ?
(2) Gibt es eine Methode ganzzahlig, im Rahmen von 8 Bit zu 
multiplizieren (für die Lautstärkenkontrolle und für DDS) ? Wenn ich 
bspw. in der IRQ Routine schreibe "IF Versatz > 255 then ..." dann 
reichen die 8 * 256 Takte bereits nicht mehr aus, auf die Timer0 
eingestellt ist !

~~~~~~~~~~~~~

$regfile = "m8def.dat"
$crystal = 14745600
$hwstack = 32                                               ' default 
use 32 for the hardware stack
$swstack = 10                                               ' default 
use 10 for the SW stack
$framesize = 40                                             ' default 
use 40 for the frame space

Config Timer0 = Timer , Prescale = 8
On Timer0 Tmr0

Config Portd = Output

Dim A As Byte , B As Byte , Sinus(256) As Byte
Dim C As Single , Laut As Single , Amplitude As Single , Freq As Byte , 
Versatz As Single

B = 0
For A = 0 To 255
C = A * 360
C = C / 256
C = Deg2rad(c)
C = Sin(c)
C = C * 128
C = C + 128
Sinus(b) = Int(c)
B = B + 1
Next

Enable Timer0
Enable Interrupts
Do
Laut = 1
For Freq = 1 To 255
Waitms 5
Next
For Freq = 255 To 1 Step -1
Waitms 5
Next
Loop

Tmr0:
C = Freq \ 100
C = C + 1
Versatz = Versatz + C
A = Int(versatz)
If A > 255 Then Versatz = 0
Portd = Sinus(a)
Return

~~~~~~~~~~

Danke und Gruß

Autor: Ulrich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der BAscom Compiler ist nicht gerade der Schnellste. Bei ISRs kommt da 
noch ein relativ langer Teil zum retten und wiederherstellend er 
Register dazu. Es könnte nötig sein die ISR als ganzes als inline ASM zu 
schreiben. Immerhin geht das relativ einfach.

Wenn man mutig ist, und in Kauf nimmt, dass das Programm eventuell nicht 
mehr so mit neuere Compilerversionen läuft, könnte man sogar ausnutzen 
das der Compiler einige Register gar nicht nutzt.

Unabhäng davon sollte die ISR nicht mit Fließkomma arbeiten, und auch 
keine Division enthalten.  Das allein kann die ISR schon über 10 mal 
schneller machen.
Und auch so ist die ISR auch noch logisch falsch, beim Überlauf fängt 
man nicht wieder genau bei 0 an.

Autor: Thomas Scherer (zeilentrafo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ulrich schrieb:

> Und auch so ist die ISR auch noch logisch falsch, beim Überlauf fängt
> man nicht wieder genau bei 0 an.

Danke Dir. Stimmt, bei Freq > 100 wird Sinus(0) nicht mehr aufgerufen. 
Komischerweise sieht es auf dem Oszi noch recht sauber aus.

Man kann in Bascom bei den IRQ "nosave" angeben, dann werden die 
Register nicht auf den Stack geschoben. Als ich es probiert habe, ist 
nur Müll rausgekommen. Komischerweise hatte ich auch Müll, wenn ich die 
DDS-Division aus der IRQ Routine rausgenommen habe.

Problematisch wird es bei der Hüllkurveneinstellung. Da sehe ich keine 
Möglichkeit, die Division aus der IRQ Routine zu entfernen. Daher 
nochmal meine Frage, wie man eine Division (oder Multiplikation mit dem 
Kehrwert) auf ganzzahlige Werte im 8-Bit-Raum beschränken kann ?

Autor: Ulrich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Option NOSAVE bei der SIR ist nur brauchbar, wenn man die ISR in 
inline ASM schreibt, und da die wrklich benötigsten Register von Hand 
rettet. Ohne geht es nicht (bis auf extreme Ausnahmen).

So wie die ISR oben ist, könnte man die Division ganz einfach nach außen 
ziehen und eine Freq/100 als extra Variable speichern.
Für eine DDS Funktion sollte die Variable für die Phase (versatz) vom 
Typ Word (oder ggf. dem 32 Bit equivalent) sein. Die addition dann auch 
mit einen Word Typen für die Frequenz, wobei der Wert ausherlalb der ISR 
berechent wird. Für die Sinustabelle wird dann nur das High-byte der 
Phase benutzt. Für das High byte kann man bei der Deklaration eine extra 
Varabel an der gleichen Postion wie die Phase extra definieren.

Also C und versatz als WORD. und die ISR etwa so:

versatz = verstatz + c
A = versatz / 256             ( hier besser spez. Varablenzugriff)
portd = sinus (A)

Autor: Maik Werner (werner01)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Division durch 256 geht auch mit MSB auf LSB kopieren

Autor: Peter R. (pnu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für die Nutzung eines Kontrollers als DDS-IC muss die Grundoperation 
(Addierschleife) ohne Eingriff durch interupts ablaufen.Also als 
inline-ASM-Routine. Der Kontroller sollte NUR die DDS-Schleife arbeiten.

Dann läuft diese Schleife mit etwa 6 bis 8 Takten ab und man kommt mit 
14,..MHz bis etwa 50 kHz auf eine einigermaßen gute Kurvenform, kann 
also den NF-Bereich überdecken.

Zusätzliche Operationen, wie Multiplikation wegen der Amplitude, sollte 
man nicht machen. Nicht nur,dass dann die DDS-Schleife verlangsamt wird 
und man nur maximal einige kHz erzeugen kann, auch die Auflösung von 256 
Schritten vertikal wird zerstört.

Die Steuerung, wie Eingabe der Sollfrequenz, Berechnung der Steuerzahl 
usw. sollte von einem zweiten Kontroller ausgeführt werden, der nach 
Änderungen die fertig berechnete Additionszahl an das "DDS-IC" übergibt, 
z.B über eine serielle Schnittstelle.

google mal "poor man's DDS-synthesizer".

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.